Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(609)

Unified Diff: sync/engine/commit_util.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sync/engine/commit_util.h ('k') | sync/engine/conflict_resolver.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sync/engine/commit_util.cc
diff --git a/sync/engine/commit_util.cc b/sync/engine/commit_util.cc
deleted file mode 100644
index 4d0eacc75cc7773d247547f6cb5e56025fda057c..0000000000000000000000000000000000000000
--- a/sync/engine/commit_util.cc
+++ /dev/null
@@ -1,474 +0,0 @@
-// 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/engine/commit_util.h"
-
-#include <stdint.h>
-
-#include <limits>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/debug/dump_without_crashing.h"
-#include "base/strings/string_util.h"
-#include "sync/engine/syncer_proto_util.h"
-#include "sync/internal_api/public/base/attachment_id_proto.h"
-#include "sync/internal_api/public/base/unique_position.h"
-#include "sync/protocol/bookmark_specifics.pb.h"
-#include "sync/protocol/sync.pb.h"
-#include "sync/sessions/sync_session.h"
-#include "sync/syncable/directory.h"
-#include "sync/syncable/entry.h"
-#include "sync/syncable/model_neutral_mutable_entry.h"
-#include "sync/syncable/syncable_base_transaction.h"
-#include "sync/syncable/syncable_base_write_transaction.h"
-#include "sync/syncable/syncable_changes_version.h"
-#include "sync/syncable/syncable_proto_util.h"
-#include "sync/syncable/syncable_util.h"
-#include "sync/util/time.h"
-
-using std::set;
-using std::string;
-using std::vector;
-
-namespace syncer {
-
-using syncable::Entry;
-using syncable::Id;
-
-namespace commit_util {
-
-void AddExtensionsActivityToMessage(
- ExtensionsActivity* activity,
- ExtensionsActivity::Records* extensions_activity_buffer,
- sync_pb::CommitMessage* message) {
- // This isn't perfect, since the set of extensions activity may not correlate
- // exactly with the items being committed. That's OK as long as we're looking
- // for a rough estimate of extensions activity, not an precise mapping of
- // which commits were triggered by which extension.
- //
- // We will push this list of extensions activity back into the
- // ExtensionsActivityMonitor if this commit fails. That's why we must keep a
- // copy of these records in the session.
- activity->GetAndClearRecords(extensions_activity_buffer);
-
- const ExtensionsActivity::Records& records = *extensions_activity_buffer;
- for (ExtensionsActivity::Records::const_iterator it =
- records.begin();
- it != records.end(); ++it) {
- sync_pb::ChromiumExtensionsActivity* activity_message =
- message->add_extensions_activity();
- activity_message->set_extension_id(it->second.extension_id);
- activity_message->set_bookmark_writes_since_last_commit(
- it->second.bookmark_write_count);
- }
-}
-
-void AddClientConfigParamsToMessage(
- ModelTypeSet enabled_types,
- bool cookie_jar_mismatch,
- sync_pb::CommitMessage* message) {
- sync_pb::ClientConfigParams* config_params = message->mutable_config_params();
- for (ModelTypeSet::Iterator it = enabled_types.First(); it.Good(); it.Inc()) {
- if (ProxyTypes().Has(it.Get()))
- continue;
- int field_number = GetSpecificsFieldNumberFromModelType(it.Get());
- config_params->mutable_enabled_type_ids()->Add(field_number);
- }
- config_params->set_tabs_datatype_enabled(
- enabled_types.Has(syncer::PROXY_TABS));
- config_params->set_cookie_jar_mismatch(cookie_jar_mismatch);
-}
-
-namespace {
-
-void SetEntrySpecifics(const Entry& meta_entry,
- sync_pb::SyncEntity* sync_entry) {
- // Add the new style extension and the folder bit.
- sync_entry->mutable_specifics()->CopyFrom(meta_entry.GetSpecifics());
- sync_entry->set_folder(meta_entry.GetIsDir());
-
- CHECK(!sync_entry->specifics().password().has_client_only_encrypted_data());
- DCHECK_EQ(meta_entry.GetModelType(), GetModelType(*sync_entry));
-}
-
-void SetAttachmentIds(const Entry& meta_entry,
- sync_pb::SyncEntity* sync_entry) {
- const sync_pb::AttachmentMetadata& attachment_metadata =
- meta_entry.GetAttachmentMetadata();
- for (int i = 0; i < attachment_metadata.record_size(); ++i) {
- *sync_entry->add_attachment_id() = attachment_metadata.record(i).id();
- }
-}
-
-} // namespace
-
-void BuildCommitItem(
- const syncable::Entry& meta_entry,
- sync_pb::SyncEntity* sync_entry) {
- syncable::Id id = meta_entry.GetId();
- sync_entry->set_id_string(SyncableIdToProto(id));
-
- string name = meta_entry.GetNonUniqueName();
- CHECK(!name.empty()); // Make sure this isn't an update.
- // Note: Truncation is also performed in WriteNode::SetTitle(..). But this
- // call is still necessary to handle any title changes that might originate
- // elsewhere, or already be persisted in the directory.
- base::TruncateUTF8ToByteSize(name, 255, &name);
- sync_entry->set_name(name);
-
- // Set the non_unique_name. If we do, the server ignores
- // the |name| value (using |non_unique_name| instead), and will return
- // in the CommitResponse a unique name if one is generated.
- // We send both because it may aid in logging.
- sync_entry->set_non_unique_name(name);
-
- if (!meta_entry.GetUniqueClientTag().empty()) {
- sync_entry->set_client_defined_unique_tag(
- meta_entry.GetUniqueClientTag());
- }
-
- // Deleted items with server-unknown parent ids can be a problem so we set
- // the parent to 0. (TODO(sync): Still true in protocol?).
- Id new_parent_id;
- if (meta_entry.GetIsDel() &&
- !meta_entry.GetParentId().ServerKnows()) {
- new_parent_id = syncable::BaseTransaction::root_id();
- } else {
- new_parent_id = meta_entry.GetParentId();
- }
-
- if (meta_entry.ShouldMaintainHierarchy()) {
- sync_entry->set_parent_id_string(SyncableIdToProto(new_parent_id));
- }
-
- // If our parent has changed, send up the old one so the server
- // can correctly deal with multiple parents.
- // TODO(nick): With the server keeping track of the primary sync parent,
- // it should not be necessary to provide the old_parent_id: the version
- // number should suffice.
- Id server_parent_id = meta_entry.GetServerParentId();
- if (new_parent_id != server_parent_id && !server_parent_id.IsNull() &&
- 0 != meta_entry.GetBaseVersion() &&
- syncable::CHANGES_VERSION != meta_entry.GetBaseVersion()) {
- sync_entry->set_old_parent_id(SyncableIdToProto(server_parent_id));
- }
-
- int64_t version = meta_entry.GetBaseVersion();
- if (syncable::CHANGES_VERSION == version || 0 == version) {
- // Undeletions are only supported for items that have a client tag.
- DCHECK(!id.ServerKnows() ||
- !meta_entry.GetUniqueClientTag().empty())
- << meta_entry;
-
- // Version 0 means to create or undelete an object.
- sync_entry->set_version(0);
- } else {
- DCHECK(id.ServerKnows()) << meta_entry;
- sync_entry->set_version(meta_entry.GetBaseVersion());
- }
- sync_entry->set_ctime(TimeToProtoTime(meta_entry.GetCtime()));
- sync_entry->set_mtime(TimeToProtoTime(meta_entry.GetMtime()));
-
- SetAttachmentIds(meta_entry, sync_entry);
-
- // Handle bookmarks separately.
- if (meta_entry.GetSpecifics().has_bookmark()) {
- if (meta_entry.GetIsDel()) {
- sync_entry->set_deleted(true);
- } else {
- // Both insert_after_item_id and position_in_parent fields are set only
- // for legacy reasons. See comments in sync.proto for more information.
- const Id& prev_id = meta_entry.GetPredecessorId();
- string prev_id_string =
- prev_id.IsNull() ? string() : prev_id.GetServerId();
- sync_entry->set_insert_after_item_id(prev_id_string);
- sync_entry->set_position_in_parent(
- meta_entry.GetUniquePosition().ToInt64());
- meta_entry.GetUniquePosition().ToProto(
- sync_entry->mutable_unique_position());
- if (!meta_entry.GetUniquePosition().IsValid()) {
- // Should never upload invalid unique position for bookmark to server.
- base::debug::DumpWithoutCrashing();
- }
- }
- // Always send specifics for bookmarks.
- SetEntrySpecifics(meta_entry, sync_entry);
- return;
- }
-
- // Deletion is final on the server, let's move things and then delete them.
- if (meta_entry.GetIsDel()) {
- sync_entry->set_deleted(true);
-
- sync_pb::EntitySpecifics type_only_specifics;
- AddDefaultFieldValue(meta_entry.GetModelType(),
- sync_entry->mutable_specifics());
- } else {
- SetEntrySpecifics(meta_entry, sync_entry);
- }
-}
-
-// Helpers for ProcessSingleCommitResponse.
-namespace {
-
-void LogServerError(const sync_pb::CommitResponse_EntryResponse& res) {
- if (res.has_error_message())
- LOG(WARNING) << " " << res.error_message();
- else
- LOG(WARNING) << " No detailed error message returned from server";
-}
-
-const string& GetResultingPostCommitName(
- const sync_pb::SyncEntity& committed_entry,
- const sync_pb::CommitResponse_EntryResponse& entry_response) {
- const string& response_name =
- SyncerProtoUtil::NameFromCommitEntryResponse(entry_response);
- if (!response_name.empty())
- return response_name;
- return SyncerProtoUtil::NameFromSyncEntity(committed_entry);
-}
-
-bool UpdateVersionAfterCommit(
- const sync_pb::SyncEntity& committed_entry,
- const sync_pb::CommitResponse_EntryResponse& entry_response,
- const syncable::Id& pre_commit_id,
- syncable::ModelNeutralMutableEntry* local_entry) {
- int64_t old_version = local_entry->GetBaseVersion();
- int64_t new_version = entry_response.version();
- bool bad_commit_version = false;
- if (committed_entry.deleted() &&
- !local_entry->GetUniqueClientTag().empty()) {
- // If the item was deleted, and it's undeletable (uses the client tag),
- // change the version back to zero. We must set the version to zero so
- // that the server knows to re-create the item if it gets committed
- // later for undeletion.
- new_version = 0;
- } else if (!pre_commit_id.ServerKnows()) {
- bad_commit_version = 0 == new_version;
- } else {
- bad_commit_version = old_version > new_version;
- }
- if (bad_commit_version) {
- LOG(ERROR) << "Bad version in commit return for " << *local_entry
- << " new_id:" << SyncableIdFromProto(entry_response.id_string())
- << " new_version:" << entry_response.version();
- return false;
- }
-
- // Update the base version and server version. The base version must change
- // here, even if syncing_was_set is false; that's because local changes were
- // on top of the successfully committed version.
- local_entry->PutBaseVersion(new_version);
- DVLOG(1) << "Commit is changing base version of " << local_entry->GetId()
- << " to: " << new_version;
- local_entry->PutServerVersion(new_version);
- return true;
-}
-
-bool ChangeIdAfterCommit(
- const sync_pb::CommitResponse_EntryResponse& entry_response,
- const syncable::Id& pre_commit_id,
- syncable::ModelNeutralMutableEntry* local_entry) {
- syncable::BaseWriteTransaction* trans = local_entry->base_write_transaction();
- const syncable::Id& entry_response_id =
- SyncableIdFromProto(entry_response.id_string());
- if (entry_response_id != pre_commit_id) {
- if (pre_commit_id.ServerKnows()) {
- // The server can sometimes generate a new ID on commit; for example,
- // when committing an undeletion.
- DVLOG(1) << " ID changed while committing an old entry. "
- << pre_commit_id << " became " << entry_response_id << ".";
- }
- syncable::ModelNeutralMutableEntry same_id(
- trans,
- syncable::GET_BY_ID,
- entry_response_id);
- // We should trap this before this function.
- if (same_id.good()) {
- LOG(ERROR) << "ID clash with id " << entry_response_id
- << " during commit " << same_id;
- return false;
- }
- ChangeEntryIDAndUpdateChildren(trans, local_entry, entry_response_id);
- DVLOG(1) << "Changing ID to " << entry_response_id;
- }
- return true;
-}
-
-void UpdateServerFieldsAfterCommit(
- const sync_pb::SyncEntity& committed_entry,
- const sync_pb::CommitResponse_EntryResponse& entry_response,
- syncable::ModelNeutralMutableEntry* local_entry) {
-
- // We just committed an entry successfully, and now we want to make our view
- // of the server state consistent with the server state. We must be careful;
- // |entry_response| and |committed_entry| have some identically named
- // fields. We only want to consider fields from |committed_entry| when there
- // is not an overriding field in the |entry_response|. We do not want to
- // update the server data from the local data in the entry -- it's possible
- // that the local data changed during the commit, and even if not, the server
- // has the last word on the values of several properties.
-
- local_entry->PutServerIsDel(committed_entry.deleted());
- if (committed_entry.deleted()) {
- // Don't clobber any other fields of deleted objects.
- return;
- }
-
- local_entry->PutServerIsDir(
- (committed_entry.folder() ||
- committed_entry.bookmarkdata().bookmark_folder()));
- local_entry->PutServerSpecifics(committed_entry.specifics());
- local_entry->PutServerAttachmentMetadata(
- CreateAttachmentMetadata(committed_entry.attachment_id()));
- local_entry->PutServerMtime(ProtoTimeToTime(committed_entry.mtime()));
- local_entry->PutServerCtime(ProtoTimeToTime(committed_entry.ctime()));
- if (committed_entry.has_unique_position()) {
- local_entry->PutServerUniquePosition(
- UniquePosition::FromProto(
- committed_entry.unique_position()));
- }
-
- // TODO(nick): The server doesn't set entry_response.server_parent_id in
- // practice; to update SERVER_PARENT_ID appropriately here we'd need to
- // get the post-commit ID of the parent indicated by
- // committed_entry.parent_id_string(). That should be inferrable from the
- // information we have, but it's a bit convoluted to pull it out directly.
- // Getting this right is important: SERVER_PARENT_ID gets fed back into
- // old_parent_id during the next commit.
- local_entry->PutServerParentId(local_entry->GetParentId());
- local_entry->PutServerNonUniqueName(
- GetResultingPostCommitName(committed_entry, entry_response));
-
- if (local_entry->GetIsUnappliedUpdate()) {
- // This shouldn't happen; an unapplied update shouldn't be committed, and
- // if it were, the commit should have failed. But if it does happen: we've
- // just overwritten the update info, so clear the flag.
- local_entry->PutIsUnappliedUpdate(false);
- }
-}
-
-void ProcessSuccessfulCommitResponse(
- const sync_pb::SyncEntity& committed_entry,
- const sync_pb::CommitResponse_EntryResponse& entry_response,
- const syncable::Id& pre_commit_id,
- syncable::ModelNeutralMutableEntry* local_entry,
- bool dirty_sync_was_set, set<syncable::Id>* deleted_folders) {
- DCHECK(local_entry->GetIsUnsynced());
-
- // Update SERVER_VERSION and BASE_VERSION.
- if (!UpdateVersionAfterCommit(committed_entry, entry_response, pre_commit_id,
- local_entry)) {
- LOG(ERROR) << "Bad version in commit return for " << *local_entry
- << " new_id:" << SyncableIdFromProto(entry_response.id_string())
- << " new_version:" << entry_response.version();
- return;
- }
-
- // If the server gave us a new ID, apply it.
- if (!ChangeIdAfterCommit(entry_response, pre_commit_id, local_entry)) {
- return;
- }
-
- // Update our stored copy of the server state.
- UpdateServerFieldsAfterCommit(committed_entry, entry_response, local_entry);
-
- // If the item doesn't need to be committed again (an item might need to be
- // committed again if it changed locally during the commit), we can remove
- // it from the unsynced list.
- if (!dirty_sync_was_set) {
- local_entry->PutIsUnsynced(false);
- }
-
- // Make a note of any deleted folders, whose children would have
- // been recursively deleted.
- // TODO(nick): Here, commit_message.deleted() would be more correct than
- // local_entry->GetIsDel(). For example, an item could be renamed, and then
- // deleted during the commit of the rename. Unit test & fix.
- if (local_entry->GetIsDir() && local_entry->GetIsDel()) {
- deleted_folders->insert(local_entry->GetId());
- }
-}
-
-} // namespace
-
-sync_pb::CommitResponse::ResponseType ProcessSingleCommitResponse(
- syncable::BaseWriteTransaction* trans,
- const sync_pb::CommitResponse_EntryResponse& server_entry,
- const sync_pb::SyncEntity& commit_request_entry,
- int64_t metahandle,
- set<syncable::Id>* deleted_folders) {
- syncable::ModelNeutralMutableEntry local_entry(
- trans,
- syncable::GET_BY_HANDLE,
- metahandle);
- CHECK(local_entry.good());
- bool dirty_sync_was_set = local_entry.GetDirtySync();
- local_entry.PutDirtySync(false);
- local_entry.PutSyncing(false);
-
- sync_pb::CommitResponse::ResponseType response = server_entry.response_type();
- if (!sync_pb::CommitResponse::ResponseType_IsValid(response)) {
- LOG(ERROR) << "Commit response has unknown response type! Possibly out "
- "of date client?";
- return sync_pb::CommitResponse::INVALID_MESSAGE;
- }
- if (sync_pb::CommitResponse::TRANSIENT_ERROR == response) {
- DVLOG(1) << "Transient Error Committing: " << local_entry;
- LogServerError(server_entry);
- return sync_pb::CommitResponse::TRANSIENT_ERROR;
- }
- if (sync_pb::CommitResponse::INVALID_MESSAGE == response) {
- LOG(ERROR) << "Error Commiting: " << local_entry;
- LogServerError(server_entry);
- return response;
- }
- if (sync_pb::CommitResponse::CONFLICT == response) {
- DVLOG(1) << "Conflict Committing: " << local_entry;
- return response;
- }
- if (sync_pb::CommitResponse::RETRY == response) {
- DVLOG(1) << "Retry Committing: " << local_entry;
- return response;
- }
- if (sync_pb::CommitResponse::OVER_QUOTA == response) {
- LOG(WARNING) << "Hit deprecated OVER_QUOTA Committing: " << local_entry;
- return response;
- }
- if (!server_entry.has_id_string()) {
- LOG(ERROR) << "Commit response has no id";
- return sync_pb::CommitResponse::INVALID_MESSAGE;
- }
-
- // Implied by the IsValid call above, but here for clarity.
- DCHECK_EQ(sync_pb::CommitResponse::SUCCESS, response) << response;
- // Check to see if we've been given the ID of an existing entry. If so treat
- // it as an error response and retry later.
- const syncable::Id& server_entry_id =
- SyncableIdFromProto(server_entry.id_string());
- if (local_entry.GetId() != server_entry_id) {
- Entry e(trans, syncable::GET_BY_ID, server_entry_id);
- if (e.good()) {
- LOG(ERROR)
- << "Got duplicate id when commiting id: "
- << local_entry.GetId()
- << ". Treating as an error return";
- return sync_pb::CommitResponse::INVALID_MESSAGE;
- }
- }
-
- if (server_entry.version() == 0) {
- LOG(WARNING) << "Server returned a zero version on a commit response.";
- }
-
- ProcessSuccessfulCommitResponse(commit_request_entry, server_entry,
- local_entry.GetId(), &local_entry, dirty_sync_was_set, deleted_folders);
- return response;
-}
-
-} // namespace commit_util
-
-} // namespace syncer
« no previous file with comments | « sync/engine/commit_util.h ('k') | sync/engine/conflict_resolver.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698