summaryrefslogtreecommitdiffstats
path: root/sync
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
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')
-rw-r--r--sync/sync_core.gypi2
-rw-r--r--sync/syncable/directory.h1
-rw-r--r--sync/syncable/model_neutral_mutable_entry.cc355
-rw-r--r--sync/syncable/model_neutral_mutable_entry.h109
-rw-r--r--sync/syncable/mutable_entry.cc339
-rw-r--r--sync/syncable/mutable_entry.h79
6 files changed, 490 insertions, 395 deletions
diff --git a/sync/sync_core.gypi b/sync/sync_core.gypi
index 95b3ff8..9633f5e 100644
--- a/sync/sync_core.gypi
+++ b/sync/sync_core.gypi
@@ -128,6 +128,8 @@
'syncable/invalid_directory_backing_store.cc',
'syncable/invalid_directory_backing_store.h',
'syncable/metahandle_set.h',
+ 'syncable/model_neutral_mutable_entry.cc',
+ 'syncable/model_neutral_mutable_entry.h',
'syncable/model_type.cc',
'syncable/mutable_entry.cc',
'syncable/mutable_entry.h',
diff --git a/sync/syncable/directory.h b/sync/syncable/directory.h
index 2212a8c..6de3a47 100644
--- a/sync/syncable/directory.h
+++ b/sync/syncable/directory.h
@@ -48,6 +48,7 @@ enum InvariantCheckLevel {
class SYNC_EXPORT Directory {
friend class BaseTransaction;
friend class Entry;
+ friend class ModelNeutralMutableEntry;
friend class MutableEntry;
friend class ReadTransaction;
friend class ScopedKernelLock;
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
diff --git a/sync/syncable/model_neutral_mutable_entry.h b/sync/syncable/model_neutral_mutable_entry.h
new file mode 100644
index 0000000..0d15fc9
--- /dev/null
+++ b/sync/syncable/model_neutral_mutable_entry.h
@@ -0,0 +1,109 @@
+// 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.
+
+#ifndef SYNC_SYNCABLE_MODEL_NEUTRAL_MUTABLE_ENTRY_H_
+#define SYNC_SYNCABLE_MODEL_NEUTRAL_MUTABLE_ENTRY_H_
+
+#include "sync/base/sync_export.h"
+#include "sync/internal_api/public/base/model_type.h"
+#include "sync/syncable/entry.h"
+
+namespace syncer {
+class WriteNode;
+
+namespace syncable {
+
+class WriteTransaction;
+
+// This Entry includes all the operations one can safely perform on the sync
+// thread. In particular, it does not expose setters to make changes that need
+// to be communicated to the model (and the model's thread). It is not possible
+// to change an entry's SPECIFICS or UNIQUE_POSITION fields with this kind of
+// entry.
+class SYNC_EXPORT_PRIVATE ModelNeutralMutableEntry : public Entry {
+ public:
+ ModelNeutralMutableEntry(WriteTransaction* trans, GetByHandle, int64);
+ ModelNeutralMutableEntry(WriteTransaction* trans, GetById, const Id&);
+ ModelNeutralMutableEntry(
+ WriteTransaction* trans,
+ GetByClientTag,
+ const std::string& tag);
+ ModelNeutralMutableEntry(
+ WriteTransaction* trans,
+ GetByServerTag,
+ const std::string& tag);
+
+ inline WriteTransaction* write_transaction() const {
+ return write_transaction_;
+ }
+
+ // Non-model-changing setters. These setters will change properties internal
+ // to the node. These fields are important for bookkeeping in the sync
+ // internals, but it is not necessary to communicate changes in these fields
+ // to the local models.
+ //
+ // Some of them trigger the re-indexing of the entry. They return true on
+ // success and false on failure, which occurs when putting the value would
+ // have caused a duplicate in the index. The setters that never fail return
+ // void.
+ void PutBaseVersion(int64 value);
+ void PutServerVersion(int64 value);
+ void PutServerMtime(base::Time value);
+ void PutServerCtime(base::Time value);
+ bool PutId(const Id& value);
+ void PutServerParentId(const Id& value);
+ bool PutIsUnsynced(bool value);
+ bool PutIsUnappliedUpdate(bool value);
+ void PutServerIsDir(bool value);
+ void PutServerIsDel(bool value);
+ void PutServerNonUniqueName(const std::string& value);
+ bool PutUniqueServerTag(const std::string& value);
+ bool PutUniqueClientTag(const std::string& value);
+ void PutUniqueBookmarkTag(const std::string& tag);
+ void PutServerSpecifics(const sync_pb::EntitySpecifics& value);
+ void PutBaseServerSpecifics(const sync_pb::EntitySpecifics& value);
+ void PutServerUniquePosition(const UniquePosition& value);
+ void PutSyncing(bool value);
+
+ // Do a simple property-only update of the PARENT_ID field. Use with caution.
+ //
+ // The normal Put(IS_PARENT) call will move the item to the front of the
+ // sibling order to maintain the linked list invariants when the parent
+ // changes. That's usually what you want to do, but it's inappropriate
+ // when the caller is trying to change the parent ID of a the whole set
+ // of children (e.g. because the ID changed during a commit). For those
+ // cases, there's this function. It will corrupt the sibling ordering
+ // if you're not careful.
+ void PutParentIdPropertyOnly(const Id& parent_id);
+
+ // This is similar to what one would expect from Put(TRANSACTION_VERSION),
+ // except that it doesn't bother to invoke 'SaveOriginals'. Calling that
+ // function is at best unnecessary, since the transaction will have already
+ // used its list of mutations by the time this function is called.
+ void UpdateTransactionVersion(int64 version);
+
+ protected:
+ explicit ModelNeutralMutableEntry(WriteTransaction* trans);
+
+ syncable::MetahandleSet* GetDirtyIndexHelper();
+
+ private:
+ friend class syncer::WriteNode;
+ friend class Directory;
+
+ // Don't allow creation on heap, except by sync API wrappers.
+ void* operator new(size_t size) { return (::operator new)(size); }
+
+ // Kind of redundant. We should reduce the number of pointers
+ // floating around if at all possible. Could we store this in Directory?
+ // Scope: Set on construction, never changed after that.
+ WriteTransaction* const write_transaction_;
+
+ DISALLOW_COPY_AND_ASSIGN(ModelNeutralMutableEntry);
+};
+
+} // namespace syncable
+} // namespace syncer
+
+#endif // SYNC_SYNCABLE_MODEL_NEUTRAL_MUTABLE_ENTRY_H_
diff --git a/sync/syncable/mutable_entry.cc b/sync/syncable/mutable_entry.cc
index 0c160c2..6dcf484 100644
--- a/sync/syncable/mutable_entry.cc
+++ b/sync/syncable/mutable_entry.cc
@@ -59,8 +59,7 @@ MutableEntry::MutableEntry(WriteTransaction* trans,
ModelType model_type,
const Id& parent_id,
const string& name)
- : Entry(trans),
- write_transaction_(trans) {
+ : ModelNeutralMutableEntry(trans) {
Init(trans, model_type, parent_id, name);
// We need to have a valid position ready before we can index the item.
if (model_type == BOOKMARKS) {
@@ -79,7 +78,7 @@ MutableEntry::MutableEntry(WriteTransaction* trans,
MutableEntry::MutableEntry(WriteTransaction* trans, CreateNewUpdateItem,
const Id& id)
- : Entry(trans), write_transaction_(trans) {
+ : ModelNeutralMutableEntry(trans) {
Entry same_id(trans, GET_BY_ID, id);
kernel_ = NULL;
if (same_id.good()) {
@@ -102,46 +101,27 @@ MutableEntry::MutableEntry(WriteTransaction* trans, CreateNewUpdateItem,
}
MutableEntry::MutableEntry(WriteTransaction* trans, GetById, const Id& id)
- : Entry(trans, GET_BY_ID, id), write_transaction_(trans) {
+ : ModelNeutralMutableEntry(trans, GET_BY_ID, id) {
}
MutableEntry::MutableEntry(WriteTransaction* trans, GetByHandle,
int64 metahandle)
- : Entry(trans, GET_BY_HANDLE, metahandle), write_transaction_(trans) {
+ : ModelNeutralMutableEntry(trans, GET_BY_HANDLE, metahandle) {
}
MutableEntry::MutableEntry(WriteTransaction* trans, GetByClientTag,
const std::string& tag)
- : Entry(trans, GET_BY_CLIENT_TAG, tag), write_transaction_(trans) {
+ : ModelNeutralMutableEntry(trans, GET_BY_CLIENT_TAG, tag) {
}
MutableEntry::MutableEntry(WriteTransaction* trans, GetByServerTag,
const string& tag)
- : Entry(trans, GET_BY_SERVER_TAG, tag), write_transaction_(trans) {
-}
-
-void MutableEntry::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 MutableEntry::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);
- }
+ : ModelNeutralMutableEntry(trans, GET_BY_SERVER_TAG, tag) {
}
void MutableEntry::PutLocalExternalId(int64 value) {
DCHECK(kernel_);
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
if (kernel_->ref(LOCAL_EXTERNAL_ID) != value) {
ScopedKernelLock lock(dir());
kernel_->put(LOCAL_EXTERNAL_ID, value);
@@ -151,54 +131,25 @@ void MutableEntry::PutLocalExternalId(int64 value) {
void MutableEntry::PutMtime(base::Time value) {
DCHECK(kernel_);
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
if (kernel_->ref(MTIME) != value) {
kernel_->put(MTIME, value);
kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
}
}
-void MutableEntry::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 MutableEntry::PutCtime(base::Time value) {
DCHECK(kernel_);
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
if (kernel_->ref(CTIME) != value) {
kernel_->put(CTIME, value);
kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
}
}
-void MutableEntry::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 MutableEntry::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 MutableEntry::PutParentId(const Id& value) {
DCHECK(kernel_);
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
if (kernel_->ref(PARENT_ID) != value) {
PutParentIdPropertyOnly(value);
if (!GetIsDel()) {
@@ -210,79 +161,9 @@ void MutableEntry::PutParentId(const Id& value) {
}
}
-void MutableEntry::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 MutableEntry::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 MutableEntry::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 MutableEntry::PutIsDir(bool value) {
DCHECK(kernel_);
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
bool old_value = kernel_->ref(IS_DIR);
if (old_value != value) {
kernel_->put(IS_DIR, value);
@@ -290,19 +171,9 @@ void MutableEntry::PutIsDir(bool value) {
}
}
-void MutableEntry::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 MutableEntry::PutIsDel(bool value) {
DCHECK(kernel_);
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
if (value == kernel_->ref(IS_DEL)) {
return;
}
@@ -332,27 +203,9 @@ void MutableEntry::PutIsDel(bool value) {
}
}
-void MutableEntry::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 MutableEntry::PutNonUniqueName(const std::string& value) {
DCHECK(kernel_);
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
if (kernel_->ref(NON_UNIQUE_NAME) != value) {
kernel_->put(NON_UNIQUE_NAME, value);
@@ -360,91 +213,10 @@ void MutableEntry::PutNonUniqueName(const std::string& value) {
}
}
-void MutableEntry::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 MutableEntry::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 MutableEntry::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 MutableEntry::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 MutableEntry::PutSpecifics(const sync_pb::EntitySpecifics& value) {
DCHECK(kernel_);
CHECK(!value.password().has_client_only_encrypted_data());
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
// TODO(ncarter): This is unfortunately heavyweight. Can we do
// better?
if (kernel_->ref(SPECIFICS).SerializeAsString() !=
@@ -454,56 +226,9 @@ void MutableEntry::PutSpecifics(const sync_pb::EntitySpecifics& value) {
}
}
-void MutableEntry::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 MutableEntry::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 MutableEntry::PutUniquePosition(const UniquePosition& value) {
DCHECK(kernel_);
- write_transaction_->SaveOriginal(kernel_);
+ write_transaction()->SaveOriginal(kernel_);
if(!kernel_->ref(UNIQUE_POSITION).Equals(value)) {
// We should never overwrite a valid position with an invalid one.
DCHECK(value.IsValid());
@@ -515,46 +240,14 @@ void MutableEntry::PutUniquePosition(const UniquePosition& value) {
}
}
-void MutableEntry::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 MutableEntry::PutSyncing(bool value) {
- kernel_->put(SYNCING, value);
-}
-
-void MutableEntry::PutParentIdPropertyOnly(const Id& parent_id) {
- write_transaction_->SaveOriginal(kernel_);
- dir()->ReindexParentId(write_transaction(), kernel_, parent_id);
- kernel_->mark_dirty(&dir()->kernel_->dirty_metahandles);
-}
-
-MetahandleSet* MutableEntry::GetDirtyIndexHelper() {
- return &dir()->kernel_->dirty_metahandles;
-}
-
bool MutableEntry::PutPredecessor(const Id& predecessor_id) {
- MutableEntry predecessor(write_transaction_, GET_BY_ID, predecessor_id);
+ MutableEntry predecessor(write_transaction(), GET_BY_ID, predecessor_id);
if (!predecessor.good())
return false;
dir()->PutPredecessor(kernel_, predecessor.kernel_);
return true;
}
-void MutableEntry::UpdateTransactionVersion(int64 value) {
- ScopedKernelLock lock(dir());
- kernel_->put(TRANSACTION_VERSION, value);
- kernel_->mark_dirty(&(dir()->kernel_->dirty_metahandles));
-}
-
// This function sets only the flags needed to get this entry to sync.
bool MarkForSyncing(MutableEntry* e) {
DCHECK_NE(static_cast<MutableEntry*>(NULL), e);
diff --git a/sync/syncable/mutable_entry.h b/sync/syncable/mutable_entry.h
index 40079e1..f575c22 100644
--- a/sync/syncable/mutable_entry.h
+++ b/sync/syncable/mutable_entry.h
@@ -9,14 +9,13 @@
#include "sync/internal_api/public/base/model_type.h"
#include "sync/syncable/entry.h"
#include "sync/syncable/metahandle_set.h"
+#include "sync/syncable/model_neutral_mutable_entry.h"
namespace syncer {
class WriteNode;
namespace syncable {
-class WriteTransaction;
-
enum Create {
CREATE
};
@@ -25,104 +24,40 @@ enum CreateNewUpdateItem {
CREATE_NEW_UPDATE_ITEM
};
+class WriteTransaction;
+
// A mutable meta entry. Changes get committed to the database when the
// WriteTransaction is destroyed.
-class SYNC_EXPORT_PRIVATE MutableEntry : public Entry {
+class SYNC_EXPORT_PRIVATE MutableEntry : public ModelNeutralMutableEntry {
void Init(WriteTransaction* trans, ModelType model_type,
const Id& parent_id, const std::string& name);
public:
+ MutableEntry(WriteTransaction* trans, CreateNewUpdateItem, const Id& id);
MutableEntry(WriteTransaction* trans, Create, ModelType model_type,
const Id& parent_id, const std::string& name);
- MutableEntry(WriteTransaction* trans, CreateNewUpdateItem, const Id& id);
MutableEntry(WriteTransaction* trans, GetByHandle, int64);
MutableEntry(WriteTransaction* trans, GetById, const Id&);
MutableEntry(WriteTransaction* trans, GetByClientTag, const std::string& tag);
MutableEntry(WriteTransaction* trans, GetByServerTag, const std::string& tag);
- inline WriteTransaction* write_transaction() const {
- return write_transaction_;
- }
-
- // Field Accessors. Some of them trigger the re-indexing of the entry.
- // Return true on success, return false on failure, which means that putting
- // the value would have caused a duplicate in the index. The setters that
- // never fail return void.
- void PutBaseVersion(int64 value);
- void PutServerVersion(int64 value);
+ // Model-changing setters. These setters make user-visible changes that will
+ // need to be communicated either to the local model or the sync server.
void PutLocalExternalId(int64 value);
void PutMtime(base::Time value);
- void PutServerMtime(base::Time value);
void PutCtime(base::Time value);
- void PutServerCtime(base::Time value);
- bool PutId(const Id& value);
void PutParentId(const Id& value);
- void PutServerParentId(const Id& value);
- bool PutIsUnsynced(bool value);
- bool PutIsUnappliedUpdate(bool value);
void PutIsDir(bool value);
- void PutServerIsDir(bool value);
void PutIsDel(bool value);
- void PutServerIsDel(bool value);
void PutNonUniqueName(const std::string& value);
- void PutServerNonUniqueName(const std::string& value);
- bool PutUniqueServerTag(const std::string& value);
- bool PutUniqueClientTag(const std::string& value);
- void PutUniqueBookmarkTag(const std::string& tag);
void PutSpecifics(const sync_pb::EntitySpecifics& value);
- void PutServerSpecifics(const sync_pb::EntitySpecifics& value);
- void PutBaseServerSpecifics(const sync_pb::EntitySpecifics& value);
void PutUniquePosition(const UniquePosition& value);
- void PutServerUniquePosition(const UniquePosition& value);
- void PutSyncing(bool value);
-
- // Do a simple property-only update if the PARENT_ID field. Use with caution.
- //
- // The normal Put(IS_PARENT) call will move the item to the front of the
- // sibling order to maintain the linked list invariants when the parent
- // changes. That's usually what you want to do, but it's inappropriate
- // when the caller is trying to change the parent ID of a the whole set
- // of children (e.g. because the ID changed during a commit). For those
- // cases, there's this function. It will corrupt the sibling ordering
- // if you're not careful.
- void PutParentIdPropertyOnly(const Id& parent_id);
// Sets the position of this item, and updates the entry kernels of the
// adjacent siblings so that list invariants are maintained. Returns false
// and fails if |predecessor_id| does not identify a sibling. Pass the root
// ID to put the node in first position.
bool PutPredecessor(const Id& predecessor_id);
-
- // This is similar to what one would expect from Put(TRANSACTION_VERSION),
- // except that it doesn't bother to invoke 'SaveOriginals'. Calling that
- // function is at best unnecessary, since the transaction will have already
- // used its list of mutations by the time this function is called.
- void UpdateTransactionVersion(int64 version);
-
- protected:
- syncable::MetahandleSet* GetDirtyIndexHelper();
-
- private:
- friend class Directory;
- friend class WriteTransaction;
- friend class syncer::WriteNode;
-
- // Don't allow creation on heap, except by sync API wrappers.
- void* operator new(size_t size) { return (::operator new)(size); }
-
- // Adjusts the successor and predecessor entries so that they no longer
- // refer to this entry.
- bool UnlinkFromOrder();
-
- // Kind of redundant. We should reduce the number of pointers
- // floating around if at all possible. Could we store this in Directory?
- // Scope: Set on construction, never changed after that.
- WriteTransaction* const write_transaction_;
-
- protected:
- MutableEntry();
-
- DISALLOW_COPY_AND_ASSIGN(MutableEntry);
};
// This function sets only the flags needed to get this entry to sync.