summaryrefslogtreecommitdiffstats
path: root/sync/syncable/model_neutral_mutable_entry.cc
diff options
context:
space:
mode:
authorrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-24 19:44:11 +0000
committerrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-24 19:44:11 +0000
commit4f435f72072eebacebe67316157e440d6cf20383 (patch)
tree2289301d1513931d73b3d283c6997fd6fa005b51 /sync/syncable/model_neutral_mutable_entry.cc
parent0199b017150cd2817485271d206a68c2611635b2 (diff)
downloadchromium_src-4f435f72072eebacebe67316157e440d6cf20383.zip
chromium_src-4f435f72072eebacebe67316157e440d6cf20383.tar.gz
chromium_src-4f435f72072eebacebe67316157e440d6cf20383.tar.bz2
sync: Add ModelNeutralMutableEntry
Add a ModelNeutralMutableEntry that exists between Entry and MutableEntry in the hierarchy of syncable::Entry classes. This new class inherits all of Entry's getter methods, so it can has the same ability to read from entries as the current Entry and MutableEntry classes. All the setter methods from MutableEntry that are not model-changing have been moved into ModelNeutralMutableEntry. The non-model-changing setters are those whose mutations do not need to be communicated to the model-specific change processors. Because we know can guarantee all changes made through the ModelNeutralMutabeEntry functions will not need to be relayed to the change processors, it would be safe to skip calling SaveOriginal() in its setter functions. For now, though, we leave these setter functions unmodified. BUG=284672 Review URL: https://chromiumcodereview.appspot.com/23549038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225052 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync/syncable/model_neutral_mutable_entry.cc')
-rw-r--r--sync/syncable/model_neutral_mutable_entry.cc355
1 files changed, 355 insertions, 0 deletions
diff --git a/sync/syncable/model_neutral_mutable_entry.cc b/sync/syncable/model_neutral_mutable_entry.cc
new file mode 100644
index 0000000..3d019e6
--- /dev/null
+++ b/sync/syncable/model_neutral_mutable_entry.cc
@@ -0,0 +1,355 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/syncable/model_neutral_mutable_entry.h"
+
+#include <string>
+
+#include "sync/internal_api/public/base/unique_position.h"
+#include "sync/syncable/directory.h"
+#include "sync/syncable/scoped_kernel_lock.h"
+#include "sync/syncable/syncable_util.h"
+#include "sync/syncable/syncable_write_transaction.h"
+
+using std::string;
+
+namespace syncer {
+
+namespace syncable {
+
+ModelNeutralMutableEntry::ModelNeutralMutableEntry(
+ WriteTransaction* trans, GetById, const Id& id)
+ : Entry(trans, GET_BY_ID, id), write_transaction_(trans) {
+}
+
+ModelNeutralMutableEntry::ModelNeutralMutableEntry(
+ WriteTransaction* trans, GetByHandle, int64 metahandle)
+ : Entry(trans, GET_BY_HANDLE, metahandle), write_transaction_(trans) {
+}
+
+ModelNeutralMutableEntry::ModelNeutralMutableEntry(
+ WriteTransaction* trans, GetByClientTag, const std::string& tag)
+ : Entry(trans, GET_BY_CLIENT_TAG, tag), write_transaction_(trans) {
+}
+
+ModelNeutralMutableEntry::ModelNeutralMutableEntry(
+ WriteTransaction* trans, GetByServerTag, const string& tag)
+ : Entry(trans, GET_BY_SERVER_TAG, tag), write_transaction_(trans) {
+}
+
+void ModelNeutralMutableEntry::PutBaseVersion(int64 value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ if (kernel_->ref(BASE_VERSION) != value) {
+ kernel_->put(BASE_VERSION, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+}
+
+void ModelNeutralMutableEntry::PutServerVersion(int64 value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ if (kernel_->ref(SERVER_VERSION) != value) {
+ ScopedKernelLock lock(dir());
+ kernel_->put(SERVER_VERSION, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+}
+
+void ModelNeutralMutableEntry::PutServerMtime(base::Time value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ if (kernel_->ref(SERVER_MTIME) != value) {
+ kernel_->put(SERVER_MTIME, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+}
+
+void ModelNeutralMutableEntry::PutServerCtime(base::Time value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ if (kernel_->ref(SERVER_CTIME) != value) {
+ kernel_->put(SERVER_CTIME, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+}
+
+bool ModelNeutralMutableEntry::PutId(const Id& value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ if (kernel_->ref(ID) != value) {
+ if (!dir()->ReindexId(write_transaction(), kernel_, value))
+ return false;
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+ return true;
+}
+
+void ModelNeutralMutableEntry::PutServerParentId(const Id& value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+
+ if (kernel_->ref(SERVER_PARENT_ID) != value) {
+ kernel_->put(SERVER_PARENT_ID, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+}
+
+bool ModelNeutralMutableEntry::PutIsUnsynced(bool value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ if (kernel_->ref(IS_UNSYNCED) != value) {
+ MetahandleSet* index = &dir()->kernel_->unsynced_metahandles;
+
+ ScopedKernelLock lock(dir());
+ if (value) {
+ if (!SyncAssert(index->insert(kernel_->ref(META_HANDLE)).second,
+ FROM_HERE,
+ "Could not insert",
+ write_transaction())) {
+ return false;
+ }
+ } else {
+ if (!SyncAssert(1U == index->erase(kernel_->ref(META_HANDLE)),
+ FROM_HERE,
+ "Entry Not succesfully erased",
+ write_transaction())) {
+ return false;
+ }
+ }
+ kernel_->put(IS_UNSYNCED, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+ return true;
+}
+
+bool ModelNeutralMutableEntry::PutIsUnappliedUpdate(bool value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ if (kernel_->ref(IS_UNAPPLIED_UPDATE) != value) {
+ // Use kernel_->GetServerModelType() instead of
+ // GetServerModelType() as we may trigger some DCHECKs in the
+ // latter.
+ MetahandleSet* index = &dir()->kernel_->unapplied_update_metahandles[
+ kernel_->GetServerModelType()];
+
+ ScopedKernelLock lock(dir());
+ if (value) {
+ if (!SyncAssert(index->insert(kernel_->ref(META_HANDLE)).second,
+ FROM_HERE,
+ "Could not insert",
+ write_transaction())) {
+ return false;
+ }
+ } else {
+ if (!SyncAssert(1U == index->erase(kernel_->ref(META_HANDLE)),
+ FROM_HERE,
+ "Entry Not succesfully erased",
+ write_transaction())) {
+ return false;
+ }
+ }
+ kernel_->put(IS_UNAPPLIED_UPDATE, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+ return true;
+}
+
+void ModelNeutralMutableEntry::PutServerIsDir(bool value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ bool old_value = kernel_->ref(SERVER_IS_DIR);
+ if (old_value != value) {
+ kernel_->put(SERVER_IS_DIR, value);
+ kernel_->mark_dirty(GetDirtyIndexHelper());
+ }
+}
+
+void ModelNeutralMutableEntry::PutServerIsDel(bool value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ bool old_value = kernel_->ref(SERVER_IS_DEL);
+ if (old_value != value) {
+ kernel_->put(SERVER_IS_DEL, value);
+ kernel_->mark_dirty(GetDirtyIndexHelper());
+ }
+
+ // Update delete journal for existence status change on server side here
+ // instead of in PutIsDel() because IS_DEL may not be updated due to
+ // early returns when processing updates. And because
+ // UpdateDeleteJournalForServerDelete() checks for SERVER_IS_DEL, it has
+ // to be called on sync thread.
+ dir()->delete_journal()->UpdateDeleteJournalForServerDelete(
+ write_transaction(), old_value, *kernel_);
+}
+
+void ModelNeutralMutableEntry::PutServerNonUniqueName(
+ const std::string& value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+
+ if (kernel_->ref(SERVER_NON_UNIQUE_NAME) != value) {
+ kernel_->put(SERVER_NON_UNIQUE_NAME, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+}
+
+bool ModelNeutralMutableEntry::PutUniqueServerTag(const string& new_tag) {
+ if (new_tag == kernel_->ref(UNIQUE_SERVER_TAG)) {
+ return true;
+ }
+
+ write_transaction_->SaveOriginal(kernel_);
+ ScopedKernelLock lock(dir());
+ // Make sure your new value is not in there already.
+ if (dir()->kernel_->server_tags_map.find(new_tag) !=
+ dir()->kernel_->server_tags_map.end()) {
+ DVLOG(1) << "Detected duplicate server tag";
+ return false;
+ }
+ dir()->kernel_->server_tags_map.erase(
+ kernel_->ref(UNIQUE_SERVER_TAG));
+ kernel_->put(UNIQUE_SERVER_TAG, new_tag);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ if (!new_tag.empty()) {
+ dir()->kernel_->server_tags_map[new_tag] = kernel_;
+ }
+
+ return true;
+}
+
+bool ModelNeutralMutableEntry::PutUniqueClientTag(const string& new_tag) {
+ if (new_tag == kernel_->ref(UNIQUE_CLIENT_TAG)) {
+ return true;
+ }
+
+ write_transaction_->SaveOriginal(kernel_);
+ ScopedKernelLock lock(dir());
+ // Make sure your new value is not in there already.
+ if (dir()->kernel_->client_tags_map.find(new_tag) !=
+ dir()->kernel_->client_tags_map.end()) {
+ DVLOG(1) << "Detected duplicate client tag";
+ return false;
+ }
+ dir()->kernel_->client_tags_map.erase(
+ kernel_->ref(UNIQUE_CLIENT_TAG));
+ kernel_->put(UNIQUE_CLIENT_TAG, new_tag);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ if (!new_tag.empty()) {
+ dir()->kernel_->client_tags_map[new_tag] = kernel_;
+ }
+
+ return true;
+}
+
+void ModelNeutralMutableEntry::PutUniqueBookmarkTag(const std::string& tag) {
+ // This unique tag will eventually be used as the unique suffix when adjusting
+ // this bookmark's position. Let's make sure it's a valid suffix.
+ if (!UniquePosition::IsValidSuffix(tag)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (!kernel_->ref(UNIQUE_BOOKMARK_TAG).empty() &&
+ tag != kernel_->ref(UNIQUE_BOOKMARK_TAG)) {
+ // There is only one scenario where our tag is expected to change. That
+ // scenario occurs when our current tag is a non-correct tag assigned during
+ // the UniquePosition migration.
+ std::string migration_generated_tag =
+ GenerateSyncableBookmarkHash(std::string(),
+ kernel_->ref(ID).GetServerId());
+ DCHECK_EQ(migration_generated_tag, kernel_->ref(UNIQUE_BOOKMARK_TAG));
+ }
+
+ kernel_->put(UNIQUE_BOOKMARK_TAG, tag);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+}
+
+void ModelNeutralMutableEntry::PutServerSpecifics(
+ const sync_pb::EntitySpecifics& value) {
+ DCHECK(kernel_);
+ CHECK(!value.password().has_client_only_encrypted_data());
+ write_transaction_->SaveOriginal(kernel_);
+ // TODO(ncarter): This is unfortunately heavyweight. Can we do
+ // better?
+ if (kernel_->ref(SERVER_SPECIFICS).SerializeAsString() !=
+ value.SerializeAsString()) {
+ if (kernel_->ref(IS_UNAPPLIED_UPDATE)) {
+ // Remove ourselves from unapplied_update_metahandles with our
+ // old server type.
+ const 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(SERVER_SPECIFICS, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+
+ if (kernel_->ref(IS_UNAPPLIED_UPDATE)) {
+ // Add ourselves back into unapplied_update_metahandles with our
+ // new server type.
+ const ModelType new_server_type = kernel_->GetServerModelType();
+ const int64 metahandle = kernel_->ref(META_HANDLE);
+ dir()->kernel_->unapplied_update_metahandles[new_server_type]
+ .insert(metahandle);
+ }
+ }
+}
+
+void ModelNeutralMutableEntry::PutBaseServerSpecifics(
+ const sync_pb::EntitySpecifics& value) {
+ DCHECK(kernel_);
+ CHECK(!value.password().has_client_only_encrypted_data());
+ write_transaction_->SaveOriginal(kernel_);
+ // TODO(ncarter): This is unfortunately heavyweight. Can we do
+ // better?
+ if (kernel_->ref(BASE_SERVER_SPECIFICS).SerializeAsString()
+ != value.SerializeAsString()) {
+ kernel_->put(BASE_SERVER_SPECIFICS, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+}
+
+void ModelNeutralMutableEntry::PutServerUniquePosition(
+ const UniquePosition& value) {
+ DCHECK(kernel_);
+ write_transaction_->SaveOriginal(kernel_);
+ if(!kernel_->ref(SERVER_UNIQUE_POSITION).Equals(value)) {
+ // We should never overwrite a valid position with an invalid one.
+ DCHECK(value.IsValid());
+ ScopedKernelLock lock(dir());
+ kernel_->put(SERVER_UNIQUE_POSITION, value);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+ }
+}
+
+void ModelNeutralMutableEntry::PutSyncing(bool value) {
+ kernel_->put(SYNCING, value);
+}
+
+void ModelNeutralMutableEntry::PutParentIdPropertyOnly(const Id& parent_id) {
+ write_transaction_->SaveOriginal(kernel_);
+ dir()->ReindexParentId(write_transaction(), kernel_, parent_id);
+ kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
+}
+
+void ModelNeutralMutableEntry::UpdateTransactionVersion(int64 value) {
+ ScopedKernelLock lock(dir());
+ kernel_->put(TRANSACTION_VERSION, value);
+ kernel_->mark_dirty(&(dir()->kernel_->dirty_metahandles));
+}
+
+ModelNeutralMutableEntry::ModelNeutralMutableEntry(WriteTransaction* trans)
+ : Entry(trans), write_transaction_(trans) {}
+
+MetahandleSet* ModelNeutralMutableEntry::GetDirtyIndexHelper() {
+ return &dir()->kernel_->dirty_metahandles;
+}
+
+} // namespace syncable
+
+} // namespace syncer