Index: sync/internal_api/attachments/on_disk_attachment_store.cc |
diff --git a/sync/internal_api/attachments/on_disk_attachment_store.cc b/sync/internal_api/attachments/on_disk_attachment_store.cc |
index 2c27e3be186b21ef7310c48ec25d93d69e806f90..09b4811681307271f13e938e8bad9a0536ebf635 100644 |
--- a/sync/internal_api/attachments/on_disk_attachment_store.cc |
+++ b/sync/internal_api/attachments/on_disk_attachment_store.cc |
@@ -9,6 +9,7 @@ |
#include "base/location.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/sequenced_task_runner.h" |
+#include "sync/internal_api/attachments/proto/attachment_store.pb.h" |
#include "sync/protocol/attachments.pb.h" |
#include "third_party/leveldatabase/src/include/leveldb/db.h" |
#include "third_party/leveldatabase/src/include/leveldb/options.h" |
@@ -22,8 +23,45 @@ namespace { |
// Prefix for records containing attachment data. |
const char kDataPrefix[] = "data-"; |
+const char kDatabaseMetadataKey[] = "database-metadata"; |
+ |
+const int32 kCurrentSchemaVersion = 1; |
+ |
const base::FilePath::CharType kLeveldbDirectory[] = |
FILE_PATH_LITERAL("leveldb"); |
+ |
+leveldb::WriteOptions MakeWriteOptions() { |
+ leveldb::WriteOptions write_options; |
+ write_options.sync = true; |
+ return write_options; |
+} |
+ |
+leveldb::Status ReadStoreMetadata( |
+ leveldb::DB* db, |
+ attachment_store_pb::AttachmentStoreMetadata* metadata) { |
+ std::string data_str; |
+ leveldb::ReadOptions read_options; |
+ read_options.fill_cache = false; |
+ read_options.verify_checksums = true; |
+ |
+ leveldb::Status status = |
+ db->Get(read_options, kDatabaseMetadataKey, &data_str); |
+ if (!status.ok()) |
+ return status; |
+ if (!metadata->ParseFromString(data_str)) |
+ return leveldb::Status::Corruption("Metadata record corruption"); |
+ return leveldb::Status::OK(); |
+} |
+ |
+leveldb::Status WriteStoreMetadata( |
+ leveldb::DB* db, |
+ const attachment_store_pb::AttachmentStoreMetadata& metadata) { |
+ std::string data_str; |
+ |
+ metadata.SerializeToString(&data_str); |
+ return db->Put(MakeWriteOptions(), kDatabaseMetadataKey, data_str); |
+} |
+ |
} // namespace |
OnDiskAttachmentStore::OnDiskAttachmentStore( |
@@ -50,7 +88,7 @@ void OnDiskAttachmentStore::Read(const AttachmentIdList& ids, |
AttachmentIdList::const_iterator iter = ids.begin(); |
const AttachmentIdList::const_iterator end = ids.end(); |
for (; iter != end; ++iter) { |
- const std::string key = CreateDataKeyFromAttachmentId(*iter); |
+ const std::string key = MakeDataKeyFromAttachmentId(*iter); |
std::string data_str; |
leveldb::Status status = db_->Get(read_options, key, &data_str); |
if (!status.ok()) { |
@@ -84,13 +122,12 @@ void OnDiskAttachmentStore::Write(const AttachmentList& attachments, |
read_options.fill_cache = false; |
read_options.verify_checksums = true; |
- leveldb::WriteOptions write_options; |
- write_options.sync = true; |
+ leveldb::WriteOptions write_options = MakeWriteOptions(); |
AttachmentList::const_iterator iter = attachments.begin(); |
const AttachmentList::const_iterator end = attachments.end(); |
for (; iter != end; ++iter) { |
- const std::string key = CreateDataKeyFromAttachmentId(iter->GetId()); |
+ const std::string key = MakeDataKeyFromAttachmentId(iter->GetId()); |
std::string data_str; |
// TODO(pavely): crbug/424304 This read is expensive. When I add metadata |
@@ -124,12 +161,11 @@ void OnDiskAttachmentStore::Drop(const AttachmentIdList& ids, |
DCHECK(CalledOnValidThread()); |
DCHECK(db_); |
Result result_code = SUCCESS; |
- leveldb::WriteOptions write_options; |
- write_options.sync = true; |
+ leveldb::WriteOptions write_options = MakeWriteOptions(); |
AttachmentIdList::const_iterator iter = ids.begin(); |
const AttachmentIdList::const_iterator end = ids.end(); |
for (; iter != end; ++iter) { |
- const std::string key = CreateDataKeyFromAttachmentId(*iter); |
+ const std::string key = MakeDataKeyFromAttachmentId(*iter); |
leveldb::Status status = db_->Delete(write_options, key); |
if (!status.ok()) { |
// DB::Delete doesn't check if record exists, it returns ok just like |
@@ -145,27 +181,53 @@ AttachmentStore::Result OnDiskAttachmentStore::OpenOrCreate( |
const base::FilePath& path) { |
DCHECK(CalledOnValidThread()); |
DCHECK(!db_); |
- Result result_code = UNSPECIFIED_ERROR; |
base::FilePath leveldb_path = path.Append(kLeveldbDirectory); |
- leveldb::DB* db; |
+ leveldb::DB* db_raw; |
+ scoped_ptr<leveldb::DB> db; |
leveldb::Options options; |
options.create_if_missing = true; |
// TODO(pavely): crbug/424287 Consider adding info_log, block_cache and |
// filter_policy to options. |
leveldb::Status status = |
- leveldb::DB::Open(options, leveldb_path.AsUTF8Unsafe(), &db); |
+ leveldb::DB::Open(options, leveldb_path.AsUTF8Unsafe(), &db_raw); |
if (!status.ok()) { |
DVLOG(1) << "DB::Open failed: status=" << status.ToString() |
<< ", path=" << path.AsUTF8Unsafe(); |
- } else { |
- db_.reset(db); |
- result_code = SUCCESS; |
+ return UNSPECIFIED_ERROR; |
+ } |
+ |
+ db.reset(db_raw); |
+ |
+ attachment_store_pb::AttachmentStoreMetadata metadata; |
+ status = ReadStoreMetadata(db.get(), &metadata); |
+ if (!status.ok() && !status.IsNotFound()) { |
+ DVLOG(1) << "ReadStoreMetadata failed: status=" << status.ToString(); |
+ return UNSPECIFIED_ERROR; |
} |
- return result_code; |
+ if (status.IsNotFound()) { |
+ // Brand new database. |
+ metadata.set_schema_version(kCurrentSchemaVersion); |
+ status = WriteStoreMetadata(db.get(), metadata); |
+ if (!status.ok()) { |
+ DVLOG(1) << "WriteStoreMetadata failed: status=" << status.ToString(); |
+ return UNSPECIFIED_ERROR; |
+ } |
+ } |
+ DCHECK(status.ok()); |
+ |
+ // Upgrade code goes here. |
+ |
+ if (metadata.schema_version() != kCurrentSchemaVersion) { |
+ DVLOG(1) << "Unknown schema version: " << metadata.schema_version(); |
+ return UNSPECIFIED_ERROR; |
+ } |
+ |
+ db_ = db.Pass(); |
+ return SUCCESS; |
} |
-std::string OnDiskAttachmentStore::CreateDataKeyFromAttachmentId( |
+std::string OnDiskAttachmentStore::MakeDataKeyFromAttachmentId( |
const AttachmentId& attachment_id) { |
std::string key = kDataPrefix + attachment_id.GetProto().unique_id(); |
return key; |