Use major/minor versions for IndexFile

Fixes #364
This commit is contained in:
Fangrui Song 2018-01-27 21:47:37 -08:00
parent 5763201838
commit 70bbe6c64c
5 changed files with 35 additions and 39 deletions

View File

@ -54,7 +54,7 @@ struct RealCacheManager : ICacheManager {
return nullptr; return nullptr;
return Deserialize(config_->cacheFormat, path, *file_content, return Deserialize(config_->cacheFormat, path, *file_content,
IndexFile::kCurrentVersion); IndexFile::kMajorVersion);
} }
std::string GetCachePath(const std::string& source_file) { std::string GetCachePath(const std::string& source_file) {

View File

@ -565,9 +565,8 @@ void OnIndexReference_Function(IndexFile* db,
} // namespace } // namespace
// static // static
const int IndexFile::kCurrentVersion = 10; const int IndexFile::kMajorVersion = 10;
const uint64_t IndexFile::kMessagePackMagic = 0x637175657279; // "cquery" const int IndexFile::kMinorVersion = 0;
const int IndexFile::kMessagePackVersion = 0;
IndexFile::IndexFile(const std::string& path, IndexFile::IndexFile(const std::string& path,
const optional<std::string>& contents) const optional<std::string>& contents)

View File

@ -483,14 +483,13 @@ MAKE_REFLECT_TYPE_PROXY(LanguageId, std::underlying_type<LanguageId>::type);
struct IndexFile { struct IndexFile {
IdCache id_cache; IdCache id_cache;
static const int kCurrentVersion; // For both JSON and MessagePack cache files.
static const uint64_t kMessagePackMagic; static const int kMajorVersion;
// MessagePack cache files have its own version number. // For MessagePack cache files.
// JSON has good forward compatibility because field addition/deletion do not // JSON has good forward compatibility because field addition/deletion do not
// harm but currently no efforts have been made to make old MessagePack cache // harm but currently no efforts have been made to make old MessagePack cache
// files accepted by newer cquery. // files accepted by newer cquery.
static const int kMessagePackVersion; static const int kMinorVersion;
int version = 0;
std::string path; std::string path;
std::vector<std::string> args; std::vector<std::string> args;

View File

@ -206,7 +206,6 @@ bool ReflectMemberStart(Writer& visitor, IndexFile& value) {
assert(value.Resolve(it->second)->uses.size() == 0); assert(value.Resolve(it->second)->uses.size() == 0);
} }
value.version = IndexFile::kCurrentVersion;
DefaultReflectMemberStart(visitor); DefaultReflectMemberStart(visitor);
return true; return true;
} }
@ -214,7 +213,6 @@ template <typename TVisitor>
void Reflect(TVisitor& visitor, IndexFile& value) { void Reflect(TVisitor& visitor, IndexFile& value) {
REFLECT_MEMBER_START(); REFLECT_MEMBER_START();
if (!gTestOutputMode) { if (!gTestOutputMode) {
REFLECT_MEMBER(version);
REFLECT_MEMBER(last_modification_time); REFLECT_MEMBER(last_modification_time);
REFLECT_MEMBER(language); REFLECT_MEMBER(language);
REFLECT_MEMBER(import_file); REFLECT_MEMBER(import_file);
@ -263,6 +261,12 @@ std::string Serialize(SerializeFormat format, IndexFile& file) {
rapidjson::PrettyFormatOptions::kFormatSingleLineArray); rapidjson::PrettyFormatOptions::kFormatSingleLineArray);
writer.SetIndent(' ', 2); writer.SetIndent(' ', 2);
JsonWriter json_writer(&writer); 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); Reflect(json_writer, file);
return output.GetString(); return output.GetString();
} }
@ -270,8 +274,8 @@ std::string Serialize(SerializeFormat format, IndexFile& file) {
msgpack::sbuffer buf; msgpack::sbuffer buf;
msgpack::packer<msgpack::sbuffer> pk(&buf); msgpack::packer<msgpack::sbuffer> pk(&buf);
MessagePackWriter msgpack_writer(&pk); MessagePackWriter msgpack_writer(&pk);
uint64_t magic = IndexFile::kMessagePackMagic; uint64_t magic = IndexFile::kMajorVersion;
int version = IndexFile::kMessagePackVersion; int version = IndexFile::kMinorVersion;
Reflect(msgpack_writer, magic); Reflect(msgpack_writer, magic);
Reflect(msgpack_writer, version); Reflect(msgpack_writer, version);
Reflect(msgpack_writer, file); Reflect(msgpack_writer, file);
@ -282,27 +286,26 @@ std::string Serialize(SerializeFormat format, IndexFile& file) {
} }
std::unique_ptr<IndexFile> Deserialize(SerializeFormat format, std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
std::string path, const std::string& path,
std::string serialized, const std::string& serialized,
optional<int> expected_version) { optional<int> expected_version) {
std::unique_ptr<IndexFile> file; std::unique_ptr<IndexFile> file;
switch (format) { switch (format) {
case SerializeFormat::Json: { case SerializeFormat::Json: {
rapidjson::Document reader; rapidjson::Document reader;
if (gTestOutputMode)
reader.Parse(serialized.c_str()); 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()) if (reader.HasParseError())
return nullptr; 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<IndexFile>(path, nullopt); file = MakeUnique<IndexFile>(path, nullopt);
JsonReader json_reader{&reader}; JsonReader json_reader{&reader};
try { try {
@ -320,8 +323,7 @@ std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
if (serialized.empty()) if (serialized.empty())
return nullptr; return nullptr;
try { try {
uint64_t magic; int major, minor;
int version;
if (serialized.size() < 8) if (serialized.size() < 8)
throw std::invalid_argument("Invalid"); throw std::invalid_argument("Invalid");
msgpack::unpacker upk; msgpack::unpacker upk;
@ -330,15 +332,11 @@ std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
upk.buffer_consumed(serialized.size()); upk.buffer_consumed(serialized.size());
file = MakeUnique<IndexFile>(path, nullopt); file = MakeUnique<IndexFile>(path, nullopt);
MessagePackReader reader(&upk); MessagePackReader reader(&upk);
Reflect(reader, magic); Reflect(reader, major);
if (magic != IndexFile::kMessagePackMagic) Reflect(reader, minor);
throw std::invalid_argument("Invalid magic"); if (major != IndexFile::kMajorVersion ||
Reflect(reader, version); minor != IndexFile::kMinorVersion)
if (version != IndexFile::kMessagePackVersion) { throw std::invalid_argument("Invalid version");
LOG_S(INFO) << "'" << path << "': skip old msgpack version "
<< IndexFile::kMessagePackVersion;
return nullptr;
}
Reflect(reader, *file); Reflect(reader, *file);
} catch (std::invalid_argument& e) { } catch (std::invalid_argument& e) {
LOG_S(INFO) << "Failed to deserialize msgpack '" << path LOG_S(INFO) << "Failed to deserialize msgpack '" << path

View File

@ -344,8 +344,8 @@ void ReflectMember(Reader& visitor, const char* name, T& value) {
std::string Serialize(SerializeFormat format, IndexFile& file); std::string Serialize(SerializeFormat format, IndexFile& file);
std::unique_ptr<IndexFile> Deserialize(SerializeFormat format, std::unique_ptr<IndexFile> Deserialize(SerializeFormat format,
std::string path, const std::string& path,
std::string serialized, const std::string& serialized,
optional<int> expected_version); optional<int> expected_version);
void SetTestOutputMode(); void SetTestOutputMode();