| Index: chrome/browser/sync/syncable/syncable.cc
|
| diff --git a/chrome/browser/sync/syncable/syncable.cc b/chrome/browser/sync/syncable/syncable.cc
|
| index 0050fbf56be7544841852ee4092d13b8fd967b7f..6a931f38f7cd4ed13d2cc4af13639db84d7bee4f 100644
|
| --- a/chrome/browser/sync/syncable/syncable.cc
|
| +++ b/chrome/browser/sync/syncable/syncable.cc
|
| @@ -258,6 +258,20 @@ EntryKernel::EntryKernel() : dirty_(false) {
|
|
|
| EntryKernel::~EntryKernel() {}
|
|
|
| +syncable::ModelType EntryKernel::GetServerModelType() const {
|
| + ModelType specifics_type = GetModelTypeFromSpecifics(ref(SERVER_SPECIFICS));
|
| + if (specifics_type != UNSPECIFIED)
|
| + return specifics_type;
|
| + if (ref(ID).IsRoot())
|
| + return TOP_LEVEL_FOLDER;
|
| + // Loose check for server-created top-level folders that aren't
|
| + // bound to a particular model type.
|
| + if (!ref(UNIQUE_SERVER_TAG).empty() && ref(SERVER_IS_DIR))
|
| + return TOP_LEVEL_FOLDER;
|
| +
|
| + return UNSPECIFIED;
|
| +}
|
| +
|
| bool EntryKernel::ContainsString(const std::string& lowercase_query) const {
|
| // TODO(lipalani) - figure out what to do if the node is encrypted.
|
| const sync_pb::EntitySpecifics& specifics = ref(SPECIFICS);
|
| @@ -328,6 +342,7 @@ StringValue* IdToValue(const Id& id) {
|
| DictionaryValue* EntryKernel::ToValue() const {
|
| DictionaryValue* kernel_info = new DictionaryValue();
|
| kernel_info->SetBoolean("isDirty", is_dirty());
|
| + kernel_info->Set("serverModelType", ModelTypeToValue(GetServerModelType()));
|
|
|
| // Int64 fields.
|
| SetFieldValues(*this, kernel_info,
|
| @@ -433,7 +448,6 @@ Directory::Kernel::Kernel(
|
| ids_index(new Directory::IdsIndex),
|
| parent_id_child_index(new Directory::ParentIdChildIndex),
|
| client_tag_index(new Directory::ClientTagIndex),
|
| - unapplied_update_metahandles(new MetahandleSet),
|
| unsynced_metahandles(new MetahandleSet),
|
| dirty_metahandles(new MetahandleSet),
|
| metahandles_to_purge(new MetahandleSet),
|
| @@ -459,7 +473,6 @@ void Directory::Kernel::Release() {
|
| Directory::Kernel::~Kernel() {
|
| CHECK_EQ(0, refcount);
|
| delete unsynced_metahandles;
|
| - delete unapplied_update_metahandles;
|
| delete dirty_metahandles;
|
| delete metahandles_to_purge;
|
| delete parent_id_child_index;
|
| @@ -496,10 +509,13 @@ void Directory::InitializeIndices() {
|
| kernel_->parent_id_child_index);
|
| InitializeIndexEntry<IdIndexer>(entry, kernel_->ids_index);
|
| InitializeIndexEntry<ClientTagIndexer>(entry, kernel_->client_tag_index);
|
| + const int64 metahandle = entry->ref(META_HANDLE);
|
| if (entry->ref(IS_UNSYNCED))
|
| - kernel_->unsynced_metahandles->insert(entry->ref(META_HANDLE));
|
| - if (entry->ref(IS_UNAPPLIED_UPDATE))
|
| - kernel_->unapplied_update_metahandles->insert(entry->ref(META_HANDLE));
|
| + kernel_->unsynced_metahandles->insert(metahandle);
|
| + if (entry->ref(IS_UNAPPLIED_UPDATE)) {
|
| + const ModelType type = entry->GetServerModelType();
|
| + kernel_->unapplied_update_metahandles[type].insert(metahandle);
|
| + }
|
| DCHECK(!entry->is_dirty());
|
| }
|
| }
|
| @@ -702,11 +718,12 @@ bool Directory::SafeToPurgeFromMemory(const EntryKernel* const entry) const {
|
| !entry->ref(IS_UNSYNCED);
|
|
|
| if (safe) {
|
| - int64 handle = entry->ref(META_HANDLE);
|
| + const int64 handle = entry->ref(META_HANDLE);
|
| + const ModelType type = entry->GetServerModelType();
|
| CHECK_EQ(kernel_->dirty_metahandles->count(handle), 0U);
|
| // TODO(tim): Bug 49278.
|
| CHECK(!kernel_->unsynced_metahandles->count(handle));
|
| - CHECK(!kernel_->unapplied_update_metahandles->count(handle));
|
| + CHECK(!kernel_->unapplied_update_metahandles[type].count(handle));
|
| }
|
|
|
| return safe;
|
| @@ -837,7 +854,8 @@ void Directory::PurgeEntriesWithTypeIn(const std::set<ModelType>& types) {
|
| DCHECK_EQ(entry->ref(UNIQUE_CLIENT_TAG).empty(), !num_erased);
|
| num_erased = kernel_->unsynced_metahandles->erase(handle);
|
| DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0);
|
| - num_erased = kernel_->unapplied_update_metahandles->erase(handle);
|
| + num_erased =
|
| + kernel_->unapplied_update_metahandles[server_type].erase(handle);
|
| DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0);
|
| num_erased = kernel_->parent_id_child_index->erase(entry);
|
| DCHECK_EQ(entry->ref(IS_DEL), !num_erased);
|
| @@ -1007,13 +1025,33 @@ int64 Directory::unsynced_entity_count() const {
|
| return kernel_->unsynced_metahandles->size();
|
| }
|
|
|
| -void Directory::GetUnappliedUpdateMetaHandles(BaseTransaction* trans,
|
| +syncable::ModelTypeBitSet
|
| + Directory::GetServerTypesWithUnappliedUpdates(
|
| + BaseTransaction* trans) const {
|
| + syncable::ModelTypeBitSet server_types;
|
| + ScopedKernelLock lock(this);
|
| + for (int i = 0; i < MODEL_TYPE_COUNT; ++i) {
|
| + if (!kernel_->unapplied_update_metahandles[i].empty()) {
|
| + server_types.set(i);
|
| + }
|
| + }
|
| + return server_types;
|
| +}
|
| +
|
| +void Directory::GetUnappliedUpdateMetaHandles(
|
| + BaseTransaction* trans,
|
| + syncable::ModelTypeBitSet server_types,
|
| UnappliedUpdateMetaHandles* result) {
|
| result->clear();
|
| ScopedKernelLock lock(this);
|
| - copy(kernel_->unapplied_update_metahandles->begin(),
|
| - kernel_->unapplied_update_metahandles->end(),
|
| - back_inserter(*result));
|
| + for (int i = 0; i < MODEL_TYPE_COUNT; ++i) {
|
| + const ModelType type = ModelTypeFromInt(i);
|
| + if (server_types.test(type)) {
|
| + std::copy(kernel_->unapplied_update_metahandles[type].begin(),
|
| + kernel_->unapplied_update_metahandles[type].end(),
|
| + back_inserter(*result));
|
| + }
|
| + }
|
| }
|
|
|
|
|
| @@ -1370,8 +1408,6 @@ DictionaryValue* Entry::ToValue() const {
|
| entry_info->SetBoolean("good", good());
|
| if (good()) {
|
| entry_info->Set("kernel", kernel_->ToValue());
|
| - entry_info->Set("serverModelType",
|
| - ModelTypeToValue(GetServerModelTypeHelper()));
|
| entry_info->Set("modelType",
|
| ModelTypeToValue(GetModelType()));
|
| entry_info->SetBoolean("existsOnClientBecauseNameIsNonEmpty",
|
| @@ -1387,7 +1423,7 @@ const string& Entry::Get(StringField field) const {
|
| }
|
|
|
| syncable::ModelType Entry::GetServerModelType() const {
|
| - ModelType specifics_type = GetServerModelTypeHelper();
|
| + ModelType specifics_type = kernel_->GetServerModelType();
|
| if (specifics_type != UNSPECIFIED)
|
| return specifics_type;
|
|
|
| @@ -1403,20 +1439,6 @@ syncable::ModelType Entry::GetServerModelType() const {
|
| return UNSPECIFIED;
|
| }
|
|
|
| -syncable::ModelType Entry::GetServerModelTypeHelper() const {
|
| - ModelType specifics_type = GetModelTypeFromSpecifics(Get(SERVER_SPECIFICS));
|
| - if (specifics_type != UNSPECIFIED)
|
| - return specifics_type;
|
| - if (IsRoot())
|
| - return TOP_LEVEL_FOLDER;
|
| - // Loose check for server-created top-level folders that aren't
|
| - // bound to a particular model type.
|
| - if (!Get(UNIQUE_SERVER_TAG).empty() && Get(SERVER_IS_DIR))
|
| - return TOP_LEVEL_FOLDER;
|
| -
|
| - return UNSPECIFIED;
|
| -}
|
| -
|
| syncable::ModelType Entry::GetModelType() const {
|
| ModelType specifics_type = GetModelTypeFromSpecifics(Get(SPECIFICS));
|
| if (specifics_type != UNSPECIFIED)
|
| @@ -1603,8 +1625,32 @@ bool MutableEntry::Put(ProtoField field,
|
| // TODO(ncarter): This is unfortunately heavyweight. Can we do
|
| // better?
|
| if (kernel_->ref(field).SerializeAsString() != value.SerializeAsString()) {
|
| + const bool update_unapplied_updates_index =
|
| + (field == SERVER_SPECIFICS) && kernel_->ref(IS_UNAPPLIED_UPDATE);
|
| + if (update_unapplied_updates_index) {
|
| + // Remove ourselves from unapplied_update_metahandles with our
|
| + // old server type.
|
| + const syncable::ModelType old_server_type =
|
| + kernel_->GetServerModelType();
|
| + const int64 metahandle = kernel_->ref(META_HANDLE);
|
| + size_t erase_count =
|
| + dir()->kernel_->unapplied_update_metahandles[old_server_type]
|
| + .erase(metahandle);
|
| + DCHECK_EQ(erase_count, 1u);
|
| + }
|
| +
|
| kernel_->put(field, value);
|
| kernel_->mark_dirty(dir()->kernel_->dirty_metahandles);
|
| +
|
| + if (update_unapplied_updates_index) {
|
| + // Add ourselves back into unapplied_update_metahandles with our
|
| + // new server type.
|
| + const syncable::ModelType new_server_type =
|
| + kernel_->GetServerModelType();
|
| + const int64 metahandle = kernel_->ref(META_HANDLE);
|
| + dir()->kernel_->unapplied_update_metahandles[new_server_type]
|
| + .insert(metahandle);
|
| + }
|
| }
|
| return true;
|
| }
|
| @@ -1667,10 +1713,16 @@ bool MutableEntry::Put(IndexedBitField field, bool value) {
|
| DCHECK(kernel_);
|
| if (kernel_->ref(field) != value) {
|
| MetahandleSet* index;
|
| - if (IS_UNSYNCED == field)
|
| + if (IS_UNSYNCED == field) {
|
| index = dir()->kernel_->unsynced_metahandles;
|
| - else
|
| - index = dir()->kernel_->unapplied_update_metahandles;
|
| + } else {
|
| + // Use kernel_->GetServerModelType() instead of
|
| + // GetServerModelType() as we may trigger some DCHECKs in the
|
| + // latter.
|
| + index =
|
| + &dir()->kernel_->unapplied_update_metahandles[
|
| + kernel_->GetServerModelType()];
|
| + }
|
|
|
| ScopedKernelLock lock(dir());
|
| if (value)
|
|
|