diff --git a/src/cache_manager.cc b/src/cache_manager.cc index 41ac12a7..3e46bc72 100644 --- a/src/cache_manager.cc +++ b/src/cache_manager.cc @@ -54,7 +54,7 @@ struct RealCacheManager : ICacheManager { return nullptr; return Deserialize(config_->cacheFormat, path, *file_content, - IndexFile::kCurrentVersion); + IndexFile::kMajorVersion); } std::string GetCachePath(const std::string& source_file) { diff --git a/src/indexer.cc b/src/indexer.cc index db7242aa..8cc52d18 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -565,9 +565,8 @@ void OnIndexReference_Function(IndexFile* db, } // namespace // static -const int IndexFile::kCurrentVersion = 10; -const uint64_t IndexFile::kMessagePackMagic = 0x637175657279; // "cquery" -const int IndexFile::kMessagePackVersion = 0; +const int IndexFile::kMajorVersion = 10; +const int IndexFile::kMinorVersion = 0; IndexFile::IndexFile(const std::string& path, const optional& contents) diff --git a/src/indexer.h b/src/indexer.h index 9b212a4d..6bf55b4e 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -483,14 +483,13 @@ MAKE_REFLECT_TYPE_PROXY(LanguageId, std::underlying_type::type); struct IndexFile { IdCache id_cache; - static const int kCurrentVersion; - static const uint64_t kMessagePackMagic; - // MessagePack cache files have its own version number. + // For both JSON and MessagePack cache files. + static const int kMajorVersion; + // For MessagePack cache files. // JSON has good forward compatibility because field addition/deletion do not // harm but currently no efforts have been made to make old MessagePack cache // files accepted by newer cquery. - static const int kMessagePackVersion; - int version = 0; + static const int kMinorVersion; std::string path; std::vector args; diff --git a/src/serializer.cc b/src/serializer.cc index 27e5b334..c3c2a76a 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -206,7 +206,6 @@ bool ReflectMemberStart(Writer& visitor, IndexFile& value) { assert(value.Resolve(it->second)->uses.size() == 0); } - value.version = IndexFile::kCurrentVersion; DefaultReflectMemberStart(visitor); return true; } @@ -214,7 +213,6 @@ template void Reflect(TVisitor& visitor, IndexFile& value) { REFLECT_MEMBER_START(); if (!gTestOutputMode) { - REFLECT_MEMBER(version); REFLECT_MEMBER(last_modification_time); REFLECT_MEMBER(language); REFLECT_MEMBER(import_file); @@ -263,6 +261,12 @@ std::string Serialize(SerializeFormat format, IndexFile& file) { rapidjson::PrettyFormatOptions::kFormatSingleLineArray); writer.SetIndent(' ', 2); JsonWriter json_writer(&writer); + if (!gTestOutputMode) { + std::string version = std::to_string(IndexFile::kMajorVersion); + for (char c : version) + output.Put(c); + output.Put('\n'); + } Reflect(json_writer, file); return output.GetString(); } @@ -270,8 +274,8 @@ std::string Serialize(SerializeFormat format, IndexFile& file) { msgpack::sbuffer buf; msgpack::packer pk(&buf); MessagePackWriter msgpack_writer(&pk); - uint64_t magic = IndexFile::kMessagePackMagic; - int version = IndexFile::kMessagePackVersion; + uint64_t magic = IndexFile::kMajorVersion; + int version = IndexFile::kMinorVersion; Reflect(msgpack_writer, magic); Reflect(msgpack_writer, version); Reflect(msgpack_writer, file); @@ -282,27 +286,26 @@ std::string Serialize(SerializeFormat format, IndexFile& file) { } std::unique_ptr Deserialize(SerializeFormat format, - std::string path, - std::string serialized, + const std::string& path, + const std::string& serialized, optional expected_version) { std::unique_ptr file; switch (format) { case SerializeFormat::Json: { rapidjson::Document reader; - reader.Parse(serialized.c_str()); + if (gTestOutputMode) + reader.Parse(serialized.c_str()); + else { + const char* p = strchr(serialized.c_str(), '\n'); + if (!p) + return nullptr; + if (expected_version && atoi(serialized.c_str()) != *expected_version) + return nullptr; + reader.Parse(p + 1); + } if (reader.HasParseError()) return nullptr; - // Do not deserialize a document with a bad version. Doing so could cause - // a crash because the file format may have changed. - if (expected_version) { - auto actual_version = reader.FindMember("version"); - if (actual_version == reader.MemberEnd() || - actual_version->value.GetInt() != expected_version) { - return nullptr; - } - } - file = MakeUnique(path, nullopt); JsonReader json_reader{&reader}; try { @@ -320,8 +323,7 @@ std::unique_ptr Deserialize(SerializeFormat format, if (serialized.empty()) return nullptr; try { - uint64_t magic; - int version; + int major, minor; if (serialized.size() < 8) throw std::invalid_argument("Invalid"); msgpack::unpacker upk; @@ -330,15 +332,11 @@ std::unique_ptr Deserialize(SerializeFormat format, upk.buffer_consumed(serialized.size()); file = MakeUnique(path, nullopt); MessagePackReader reader(&upk); - Reflect(reader, magic); - if (magic != IndexFile::kMessagePackMagic) - throw std::invalid_argument("Invalid magic"); - Reflect(reader, version); - if (version != IndexFile::kMessagePackVersion) { - LOG_S(INFO) << "'" << path << "': skip old msgpack version " - << IndexFile::kMessagePackVersion; - return nullptr; - } + Reflect(reader, major); + Reflect(reader, minor); + if (major != IndexFile::kMajorVersion || + minor != IndexFile::kMinorVersion) + throw std::invalid_argument("Invalid version"); Reflect(reader, *file); } catch (std::invalid_argument& e) { LOG_S(INFO) << "Failed to deserialize msgpack '" << path diff --git a/src/serializer.h b/src/serializer.h index c71c6ae4..75650dc4 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -344,8 +344,8 @@ void ReflectMember(Reader& visitor, const char* name, T& value) { std::string Serialize(SerializeFormat format, IndexFile& file); std::unique_ptr Deserialize(SerializeFormat format, - std::string path, - std::string serialized, + const std::string& path, + const std::string& serialized, optional expected_version); void SetTestOutputMode();