Index: chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc |
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc |
index 7a73cd3504d10163d5b759099acadedfb4c8d2dd..d18050cae8fed72b0f7054b040686826044270a3 100644 |
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc |
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc |
@@ -80,6 +80,20 @@ std::string GenerateAppRootIDByAppIDKey(const std::string& app_id) { |
return kAppRootIDByAppIDKeyPrefix + app_id; |
} |
+std::string GenerateActiveIDByFileIDKey(const std::string& file_id) { |
+ return kActiveIDByFileIDKeyPrefix + file_id; |
+} |
+ |
+std::string GenerateTrackerIDByFileIDKeyPrefix(const std::string& file_id) { |
+ std::ostringstream oss; |
+ oss << kTrackerIDByFileIDKeyPrefix << file_id << '\0'; |
+ return oss.str(); |
+} |
+ |
+std::string GenerateMultiTrackerKey(const std::string& file_id) { |
+ return kMultiTrackerByFileIDKeyPrefix + file_id; |
+} |
+ |
std::string GenerateDirtyIDKey(int64 tracker_id) { |
return kDirtyIDKeyPrefix + base::Int64ToString(tracker_id); |
} |
@@ -101,7 +115,7 @@ MetadataDatabaseIndexOnDisk::~MetadataDatabaseIndexOnDisk() {} |
bool MetadataDatabaseIndexOnDisk::GetFileMetadata( |
const std::string& file_id, FileMetadata* metadata) const { |
- const std::string key(kFileMetadataKeyPrefix + file_id); |
+ const std::string key = kFileMetadataKeyPrefix + file_id; |
std::string value; |
leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); |
@@ -131,8 +145,8 @@ bool MetadataDatabaseIndexOnDisk::GetFileMetadata( |
bool MetadataDatabaseIndexOnDisk::GetFileTracker( |
int64 tracker_id, FileTracker* tracker) const { |
- const std::string key(kFileTrackerKeyPrefix + |
- base::Int64ToString(tracker_id)); |
+ const std::string key = |
+ kFileTrackerKeyPrefix + base::Int64ToString(tracker_id); |
std::string value; |
leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); |
@@ -177,12 +191,14 @@ void MetadataDatabaseIndexOnDisk::StoreFileTracker( |
DVLOG(3) << "Adding new tracker: " << tracker->tracker_id() |
<< " " << GetTrackerTitle(*tracker); |
AddToAppIDIndex(*tracker, batch); |
+ AddToFileIDIndexes(*tracker, batch); |
AddToDirtyTrackerIndexes(*tracker, batch); |
// TODO(peria): Add other indexes. |
} else { |
DVLOG(3) << "Updating tracker: " << tracker->tracker_id() |
<< " " << GetTrackerTitle(*tracker); |
UpdateInAppIDIndex(old_tracker, *tracker, batch); |
+ UpdateInFileIDIndexes(old_tracker, *tracker, batch); |
UpdateInDirtyTrackerIndexes(old_tracker, *tracker, batch); |
// TODO(peria): Update other indexes. |
} |
@@ -203,23 +219,23 @@ void MetadataDatabaseIndexOnDisk::RemoveFileTracker( |
return; |
} |
- DVLOG(3) << "Removing tracker: " |
+ DVLOG(1) << "Removing tracker: " |
<< tracker.tracker_id() << " " << GetTrackerTitle(tracker); |
RemoveFromAppIDIndex(tracker, batch); |
+ RemoveFromFileIDIndexes(tracker, batch); |
RemoveFromDirtyTrackerIndexes(tracker, batch); |
// TODO(peria): Remove from other indexes. |
} |
TrackerIDSet MetadataDatabaseIndexOnDisk::GetFileTrackerIDsByFileID( |
const std::string& file_id) const { |
- // TODO(peria): Implement here |
- NOTIMPLEMENTED(); |
- return TrackerIDSet(); |
+ return GetTrackerIDSetByPrefix(kActiveIDByFileIDKeyPrefix + file_id, |
+ GenerateTrackerIDByFileIDKeyPrefix(file_id)); |
} |
int64 MetadataDatabaseIndexOnDisk::GetAppRootTracker( |
const std::string& app_id) const { |
- const std::string& key(GenerateAppRootIDByAppIDKey(app_id)); |
+ const std::string key = GenerateAppRootIDByAppIDKey(app_id); |
std::string value; |
leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); |
@@ -291,7 +307,7 @@ int64 MetadataDatabaseIndexOnDisk::PickDirtyTracker() const { |
void MetadataDatabaseIndexOnDisk::DemoteDirtyTracker( |
int64 tracker_id, leveldb::WriteBatch* batch) { |
- const std::string& key(GenerateDirtyIDKey(tracker_id)); |
+ const std::string key = GenerateDirtyIDKey(tracker_id); |
std::string value; |
leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); |
@@ -314,8 +330,7 @@ bool MetadataDatabaseIndexOnDisk::HasDemotedDirtyTracker() const { |
itr->Seek(kDemotedDirtyIDKeyPrefix); |
if (!itr->Valid()) |
return false; |
- const std::string& key(itr->key().ToString()); |
- return StartsWithASCII(key, kDemotedDirtyIDKeyPrefix, true); |
+ return StartsWithASCII(itr->key().ToString(), kDemotedDirtyIDKeyPrefix, true); |
} |
void MetadataDatabaseIndexOnDisk::PromoteDemotedDirtyTrackers( |
@@ -342,15 +357,13 @@ size_t MetadataDatabaseIndexOnDisk::CountDirtyTracker() const { |
// everytime. |
scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
for (itr->Seek(kDirtyIDKeyPrefix); itr->Valid(); itr->Next()) { |
- const std::string& key(itr->key().ToString()); |
- if (!StartsWithASCII(key, kDirtyIDKeyPrefix, true)) |
+ if (!StartsWithASCII(itr->key().ToString(), kDirtyIDKeyPrefix, true)) |
break; |
++num_dirty_trackers; |
} |
for (itr->Seek(kDemotedDirtyIDKeyPrefix); itr->Valid(); itr->Next()) { |
- const std::string& key(itr->key().ToString()); |
- if (!StartsWithASCII(key, kDemotedDirtyIDKeyPrefix, true)) |
+ if (!StartsWithASCII(itr->key().ToString(), kDemotedDirtyIDKeyPrefix, true)) |
break; |
++num_dirty_trackers; |
} |
@@ -431,9 +444,9 @@ void MetadataDatabaseIndexOnDisk::AddToAppIDIndex( |
return; |
} |
- DVLOG(1) << " Add to app_root_by_app_id: " << tracker.app_id(); |
+ DVLOG(1) << " Add to App root by App ID: " << tracker.app_id(); |
- const std::string& db_key(GenerateAppRootIDByAppIDKey(tracker.app_id())); |
+ const std::string db_key = GenerateAppRootIDByAppIDKey(tracker.app_id()); |
DCHECK(tracker.active()); |
DCHECK(!DBHasKey(db_key)); |
batch->Put(db_key, base::Int64ToString(tracker.tracker_id())); |
@@ -448,18 +461,18 @@ void MetadataDatabaseIndexOnDisk::UpdateInAppIDIndex( |
if (IsAppRoot(old_tracker) && !IsAppRoot(new_tracker)) { |
DCHECK(old_tracker.active()); |
DCHECK(!new_tracker.active()); |
- const std::string& key(GenerateAppRootIDByAppIDKey(old_tracker.app_id())); |
+ const std::string key = GenerateAppRootIDByAppIDKey(old_tracker.app_id()); |
DCHECK(DBHasKey(key)); |
- DVLOG(1) << " Remove from app_root_by_app_id: " << old_tracker.app_id(); |
+ DVLOG(1) << " Remove from App root by App ID: " << old_tracker.app_id(); |
batch->Delete(key); |
} else if (!IsAppRoot(old_tracker) && IsAppRoot(new_tracker)) { |
DCHECK(!old_tracker.active()); |
DCHECK(new_tracker.active()); |
- const std::string& key(GenerateAppRootIDByAppIDKey(new_tracker.app_id())); |
+ const std::string key = GenerateAppRootIDByAppIDKey(new_tracker.app_id()); |
DCHECK(!DBHasKey(key)); |
- DVLOG(1) << " Add to app_root_by_app_id: " << new_tracker.app_id(); |
+ DVLOG(1) << " Add to App root by App ID: " << new_tracker.app_id(); |
batch->Put(key, base::Int64ToString(new_tracker.tracker_id())); |
} |
} |
@@ -472,17 +485,112 @@ void MetadataDatabaseIndexOnDisk::RemoveFromAppIDIndex( |
} |
DCHECK(tracker.active()); |
- const std::string& key(GenerateAppRootIDByAppIDKey(tracker.app_id())); |
+ const std::string key = GenerateAppRootIDByAppIDKey(tracker.app_id()); |
DCHECK(DBHasKey(key)); |
- DVLOG(1) << " Remove from app_root_by_app_id: " << tracker.app_id(); |
+ DVLOG(1) << " Remove from App root by App ID: " << tracker.app_id(); |
+ batch->Delete(key); |
+} |
+ |
+void MetadataDatabaseIndexOnDisk::AddToFileIDIndexes( |
+ const FileTracker& new_tracker, leveldb::WriteBatch* batch) { |
+ DVLOG(1) << " Add to trackers by file ID: " << new_tracker.file_id(); |
+ const std::string prefix = |
+ GenerateTrackerIDByFileIDKeyPrefix(new_tracker.file_id()); |
+ |
+ batch->Put(prefix + base::Int64ToString(new_tracker.tracker_id()), ""); |
+ if (new_tracker.active()) { |
+ batch->Put(GenerateActiveIDByFileIDKey(new_tracker.file_id()), |
+ base::Int64ToString(new_tracker.tracker_id())); |
+ } |
+ |
+ scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
+ for (itr->Seek(prefix); itr->Valid(); itr->Next()) { |
+ std::string id_str; |
+ if (!RemovePrefix(itr->key().ToString(), prefix, &id_str)) |
+ break; |
+ |
+ int64 tracker_id; |
+ base::StringToInt64(id_str, &tracker_id); |
+ if (tracker_id == new_tracker.tracker_id()) |
+ continue; |
+ |
+ DVLOG_IF(1, !DBHasKey(GenerateMultiTrackerKey(new_tracker.file_id()))) |
+ << " Add to multi-tracker file IDs: " << new_tracker.file_id(); |
+ batch->Put(GenerateMultiTrackerKey(new_tracker.file_id()), ""); |
+ break; |
+ } |
+} |
+ |
+void MetadataDatabaseIndexOnDisk::UpdateInFileIDIndexes( |
+ const FileTracker& old_tracker, |
+ const FileTracker& new_tracker, |
+ leveldb::WriteBatch* batch) { |
+ DCHECK_EQ(old_tracker.tracker_id(), new_tracker.tracker_id()); |
+ DCHECK_EQ(old_tracker.file_id(), new_tracker.file_id()); |
+ |
+ const std::string& file_id = new_tracker.file_id(); |
+ DCHECK(DBHasKey(GenerateTrackerIDByFileIDKeyPrefix(file_id) + |
+ base::Int64ToString(new_tracker.tracker_id()))); |
+ |
+ if (old_tracker.active() && !new_tracker.active()) { |
+ batch->Delete(GenerateActiveIDByFileIDKey(file_id)); |
+ } else if (!old_tracker.active() && new_tracker.active()) { |
+ batch->Put(GenerateActiveIDByFileIDKey(file_id), |
+ base::Int64ToString(new_tracker.tracker_id())); |
+ } |
+} |
+ |
+void MetadataDatabaseIndexOnDisk::RemoveFromFileIDIndexes( |
+ const FileTracker& tracker, leveldb::WriteBatch* batch) { |
+ const std::string prefix = |
+ GenerateTrackerIDByFileIDKeyPrefix(tracker.file_id()); |
+ const std::string key = prefix + base::Int64ToString(tracker.tracker_id()); |
+ |
+ std::string value; |
+ leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); |
+ if (status.IsNotFound()) |
+ return; |
+ |
+ DVLOG(1) << " Remove from trackers by file ID: " << tracker.tracker_id(); |
batch->Delete(key); |
+ |
+ const std::string active_key = |
+ GenerateActiveIDByFileIDKey(tracker.file_id()); |
+ status = db_->Get(leveldb::ReadOptions(), active_key, &value); |
+ if (status.IsNotFound()) |
+ return; |
+ int64 active_id; |
+ if (base::StringToInt64(value, &active_id) && |
+ active_id == tracker.tracker_id()) { |
+ batch->Delete(active_key); |
+ } |
+ |
+ // Deletions are not done yet, so the number looks +1 larger than expected. |
+ size_t count = 0; |
+ scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
+ for (itr->Seek(prefix); itr->Valid() && count <= 2; itr->Next()) { |
+ if (!StartsWithASCII(itr->key().ToString(), prefix, true)) |
+ break; |
+ ++count; |
+ } |
+ |
+ if (count >= 3) |
+ return; |
+ |
+ const std::string multi_key = GenerateMultiTrackerKey(tracker.file_id()); |
+ DVLOG_IF(1, DBHasKey(multi_key)) |
+ << " Remove from multi-tracker file IDs: " << tracker.file_id(); |
+ batch->Delete(multi_key); |
+ |
+ if (count == 0) |
+ batch->Delete(GenerateActiveIDByFileIDKey(tracker.file_id())); |
} |
void MetadataDatabaseIndexOnDisk::AddToDirtyTrackerIndexes( |
const FileTracker& new_tracker, |
leveldb::WriteBatch* batch) { |
- const std::string& dirty_key(GenerateDirtyIDKey(new_tracker.tracker_id())); |
+ const std::string dirty_key = GenerateDirtyIDKey(new_tracker.tracker_id()); |
DCHECK(!DBHasKey(dirty_key)); |
DCHECK(!DBHasKey(GenerateDemotedDirtyIDKey(new_tracker.tracker_id()))); |
@@ -499,8 +607,8 @@ void MetadataDatabaseIndexOnDisk::UpdateInDirtyTrackerIndexes( |
DCHECK_EQ(old_tracker.tracker_id(), new_tracker.tracker_id()); |
int64 tracker_id = new_tracker.tracker_id(); |
- const std::string& dirty_key(GenerateDirtyIDKey(tracker_id)); |
- const std::string& demoted_key(GenerateDemotedDirtyIDKey(tracker_id)); |
+ const std::string dirty_key = GenerateDirtyIDKey(tracker_id); |
+ const std::string demoted_key = GenerateDemotedDirtyIDKey(tracker_id); |
if (old_tracker.dirty() && !new_tracker.dirty()) { |
DCHECK(DBHasKey(dirty_key) || DBHasKey(demoted_key)); |
@@ -519,12 +627,11 @@ void MetadataDatabaseIndexOnDisk::UpdateInDirtyTrackerIndexes( |
} |
void MetadataDatabaseIndexOnDisk::RemoveFromDirtyTrackerIndexes( |
- const FileTracker& tracker, |
- leveldb::WriteBatch* batch) { |
+ const FileTracker& tracker, leveldb::WriteBatch* batch) { |
if (tracker.dirty()) { |
int64 tracker_id = tracker.tracker_id(); |
- const std::string& dirty_key(GenerateDirtyIDKey(tracker_id)); |
- const std::string& demoted_key(GenerateDemotedDirtyIDKey(tracker_id)); |
+ const std::string dirty_key = GenerateDirtyIDKey(tracker_id); |
+ const std::string demoted_key = GenerateDemotedDirtyIDKey(tracker_id); |
DCHECK(DBHasKey(dirty_key) || DBHasKey(demoted_key)); |
DVLOG(1) << " Remove from dirty tracker IDs: " << tracker_id; |
@@ -533,6 +640,34 @@ void MetadataDatabaseIndexOnDisk::RemoveFromDirtyTrackerIndexes( |
} |
} |
+TrackerIDSet MetadataDatabaseIndexOnDisk::GetTrackerIDSetByPrefix( |
+ const std::string& active_key, const std::string& ids_prefix) const { |
+ TrackerIDSet trackers; |
+ |
+ // Seek IDs. |
+ scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
+ for (itr->Seek(ids_prefix); itr->Valid(); itr->Next()) { |
+ const std::string& key(itr->key().ToString()); |
+ std::string id_str; |
+ if (!RemovePrefix(key, ids_prefix, &id_str)) |
+ break; |
+ |
+ int64 tracker_id; |
+ if (!base::StringToInt64(id_str, &tracker_id)) |
+ continue; |
+ trackers.InsertInactiveTracker(tracker_id); |
+ } |
+ |
+ // Set an active tracker ID, if available. |
+ std::string value; |
+ leveldb::Status status = db_->Get(leveldb::ReadOptions(), active_key, &value); |
+ int64 active_tracker; |
+ if (status.ok() && base::StringToInt64(value, &active_tracker)) |
+ trackers.Activate(active_tracker); |
+ |
+ return trackers; |
+} |
+ |
bool MetadataDatabaseIndexOnDisk::DBHasKey(const std::string& key) { |
scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
itr->Seek(key); |