Chromium Code Reviews| Index: sync/syncable/directory.cc |
| diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc |
| index 75c1bec56188b998b3fe9c5e86f4cec4b6138a99..00cd4a7472098b6e5da7de28c27e6f7b546b5932 100644 |
| --- a/sync/syncable/directory.cc |
| +++ b/sync/syncable/directory.cc |
| @@ -10,6 +10,7 @@ |
| #include "base/debug/trace_event.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| +#include "sync/api/attachments/attachment_id.h" |
| #include "sync/internal_api/public/base/unique_position.h" |
| #include "sync/internal_api/public/util/unrecoverable_error_handler.h" |
| #include "sync/syncable/entry.h" |
| @@ -123,6 +124,7 @@ DirOpenResult Directory::Open( |
| } |
| void Directory::InitializeIndices(MetahandlesMap* handles_map) { |
| + ScopedKernelLock lock(this); |
| kernel_->metahandles_map.swap(*handles_map); |
| for (MetahandlesMap::const_iterator it = kernel_->metahandles_map.begin(); |
| it != kernel_->metahandles_map.end(); ++it) { |
| @@ -152,6 +154,7 @@ void Directory::InitializeIndices(MetahandlesMap* handles_map) { |
| kernel_->ids_map.end()) << "Unexpected duplicate use of ID"; |
| kernel_->ids_map[entry->ref(ID).value()] = entry; |
| DCHECK(!entry->is_dirty()); |
| + AddToAttachmentIndex(metahandle, entry->ref(ATTACHMENT_METADATA), lock); |
| } |
| } |
| @@ -362,6 +365,8 @@ bool Directory::InsertEntry(BaseWriteTransaction* trans, |
| return false; |
| } |
| } |
| + AddToAttachmentIndex( |
| + entry->ref(META_HANDLE), entry->ref(ATTACHMENT_METADATA), *lock); |
| // Should NEVER be created with a client tag or server tag. |
| if (!SyncAssert(entry->ref(UNIQUE_SERVER_TAG).empty(), FROM_HERE, |
| @@ -408,6 +413,51 @@ bool Directory::ReindexParentId(BaseWriteTransaction* trans, |
| return true; |
| } |
| +void Directory::RemoveFromAttachmentIndex( |
| + const int64 metahandle, |
| + const sync_pb::AttachmentMetadata& attachment_metadata, |
| + const ScopedKernelLock& lock) { |
| + for (int i = 0; i < attachment_metadata.record_size(); ++i) { |
| + AttachmentIdUniqueId unique_id = |
| + attachment_metadata.record(i).id().unique_id(); |
| + IndexByAttachmenId::iterator iter = |
| + kernel_->index_by_attachment_id.find(unique_id); |
| + if (iter != kernel_->index_by_attachment_id.end()) { |
| + iter->second.erase(metahandle); |
|
pavely
2014/04/28 23:26:27
Can entity reference attachment multiple times? Se
maniscalco
2014/04/29 20:53:22
Good point. No, a single SyncData (or entry) shou
|
| + if (iter->second.empty()) { |
| + kernel_->index_by_attachment_id.erase(iter); |
| + } |
| + } |
| + } |
| +} |
| + |
| +void Directory::AddToAttachmentIndex( |
| + const int64 metahandle, |
| + const sync_pb::AttachmentMetadata& attachment_metadata, |
| + const ScopedKernelLock& lock) { |
| + for (int i = 0; i < attachment_metadata.record_size(); ++i) { |
| + AttachmentIdUniqueId unique_id = |
| + attachment_metadata.record(i).id().unique_id(); |
| + IndexByAttachmenId::iterator iter = |
| + kernel_->index_by_attachment_id.find(unique_id); |
| + if (iter == kernel_->index_by_attachment_id.end()) { |
| + iter = kernel_->index_by_attachment_id.insert(std::make_pair( |
| + unique_id, |
| + MetahandleSet())).first; |
| + } |
| + iter->second.insert(metahandle); |
| + } |
| +} |
| + |
| +void Directory::UpdateAttachmentIndex( |
| + const int64 metahandle, |
| + const sync_pb::AttachmentMetadata& old_metadata, |
| + const sync_pb::AttachmentMetadata& new_metadata) { |
| + ScopedKernelLock lock(this); |
| + RemoveFromAttachmentIndex(metahandle, old_metadata, lock); |
| + AddToAttachmentIndex(metahandle, new_metadata, lock); |
| +} |
| + |
| bool Directory::unrecoverable_error_set(const BaseTransaction* trans) const { |
| DCHECK(trans != NULL); |
| return unrecoverable_error_set_; |
| @@ -548,6 +598,9 @@ bool Directory::VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot) { |
| "Deleted entry still present", |
| (&trans))) |
| return false; |
| + RemoveFromAttachmentIndex( |
| + entry->ref(META_HANDLE), entry->ref(ATTACHMENT_METADATA), lock); |
| + |
| delete entry; |
| } |
| if (trans.unrecoverable_error_set()) |
| @@ -607,7 +660,8 @@ void Directory::UnapplyEntry(EntryKernel* entry) { |
| void Directory::DeleteEntry(bool save_to_journal, |
| EntryKernel* entry, |
| - EntryKernelSet* entries_to_journal) { |
| + EntryKernelSet* entries_to_journal, |
| + const ScopedKernelLock& lock) { |
| int64 handle = entry->ref(META_HANDLE); |
| ModelType server_type = GetModelTypeFromSpecifics( |
| entry->ref(SERVER_SPECIFICS)); |
| @@ -637,6 +691,7 @@ void Directory::DeleteEntry(bool save_to_journal, |
| kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); |
| DCHECK_EQ(1u, num_erased); |
| } |
| + RemoveFromAttachmentIndex(handle, entry->ref(ATTACHMENT_METADATA), lock); |
| if (save_to_journal) { |
| entries_to_journal->insert(entry); |
| @@ -704,7 +759,7 @@ bool Directory::PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, |
| types_to_journal.Has(server_type)) && |
| (delete_journal_->IsDeleteJournalEnabled(local_type) || |
| delete_journal_->IsDeleteJournalEnabled(server_type)); |
| - DeleteEntry(save_to_journal, entry, &entries_to_journal); |
| + DeleteEntry(save_to_journal, entry, &entries_to_journal, lock); |
| } |
| } |
| @@ -762,6 +817,17 @@ bool Directory::ResetVersionsForType(BaseWriteTransaction* trans, |
| return true; |
| } |
| +bool Directory::IsAttachmentLinked(const AttachmentId& attachment_id) const { |
| + ScopedKernelLock lock(this); |
| + IndexByAttachmenId::const_iterator iter = |
| + kernel_->index_by_attachment_id.find( |
| + attachment_id.GetProto().unique_id()); |
| + if (iter != kernel_->index_by_attachment_id.end() && !iter->second.empty()) { |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { |
| WriteTransaction trans(FROM_HERE, HANDLE_SAVE_FAILURE, this); |
| ScopedKernelLock lock(this); |