14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/engine/commit_util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <limits> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/strings/string_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/engine/syncer_proto_util.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "sync/internal_api/public/base/attachment_id_proto.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sync/internal_api/public/base/unique_position.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/protocol/bookmark_specifics.pb.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/protocol/sync.pb.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/sessions/sync_session.h" 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/syncable/directory.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/entry.h" 214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/syncable/model_neutral_mutable_entry.h" 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/syncable/syncable_base_transaction.h" 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/syncable/syncable_base_write_transaction.h" 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sync/syncable/syncable_changes_version.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable_proto_util.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable_util.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/util/time.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::set; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using sessions::SyncSession; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::Entry; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::IS_DEL; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::IS_UNAPPLIED_UPDATE; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::IS_UNSYNCED; 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncable::Id; 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncable::SPECIFICS; 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using syncable::UNIQUE_POSITION; 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace commit_util { 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AddExtensionsActivityToMessage( 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ExtensionsActivity* activity, 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ExtensionsActivity::Records* extensions_activity_buffer, 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_pb::CommitMessage* message) { 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // This isn't perfect, since the set of extensions activity may not correlate 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // exactly with the items being committed. That's OK as long as we're looking 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // for a rough estimate of extensions activity, not an precise mapping of 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // which commits were triggered by which extension. 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // We will push this list of extensions activity back into the 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // ExtensionsActivityMonitor if this commit fails. That's why we must keep a 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // copy of these records in the session. 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) activity->GetAndClearRecords(extensions_activity_buffer); 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const ExtensionsActivity::Records& records = *extensions_activity_buffer; 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (ExtensionsActivity::Records::const_iterator it = 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) records.begin(); 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) it != records.end(); ++it) { 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_pb::ChromiumExtensionsActivity* activity_message = 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) message->add_extensions_activity(); 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) activity_message->set_extension_id(it->second.extension_id); 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) activity_message->set_bookmark_writes_since_last_commit( 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) it->second.bookmark_write_count); 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void AddClientConfigParamsToMessage( 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ModelTypeSet enabled_types, 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_pb::CommitMessage* message) { 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_pb::ClientConfigParams* config_params = message->mutable_config_params(); 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (ModelTypeSet::Iterator it = enabled_types.First(); it.Good(); it.Inc()) { 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (ProxyTypes().Has(it.Get())) 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) continue; 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int field_number = GetSpecificsFieldNumberFromModelType(it.Get()); 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) config_params->mutable_enabled_type_ids()->Add(field_number); 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) config_params->set_tabs_datatype_enabled( 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) enabled_types.Has(syncer::PROXY_TABS)); 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace { 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void SetEntrySpecifics(const Entry& meta_entry, 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_pb::SyncEntity* sync_entry) { 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Add the new style extension and the folder bit. 914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->mutable_specifics()->CopyFrom(meta_entry.GetSpecifics()); 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_folder(meta_entry.GetIsDir()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CHECK(!sync_entry->specifics().password().has_client_only_encrypted_data()); 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(meta_entry.GetModelType(), GetModelType(*sync_entry)); 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SetAttachmentIds(const Entry& meta_entry, 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_pb::SyncEntity* sync_entry) { 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const sync_pb::AttachmentMetadata& attachment_metadata = 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch meta_entry.GetAttachmentMetadata(); 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < attachment_metadata.record_size(); ++i) { 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *sync_entry->add_attachment_id() = attachment_metadata.record(i).id(); 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void BuildCommitItem( 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const syncable::Entry& meta_entry, 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_pb::SyncEntity* sync_entry) { 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::Id id = meta_entry.GetId(); 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_id_string(SyncableIdToProto(id)); 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) string name = meta_entry.GetNonUniqueName(); 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CHECK(!name.empty()); // Make sure this isn't an update. 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Note: Truncation is also performed in WriteNode::SetTitle(..). But this 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // call is still necessary to handle any title changes that might originate 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // elsewhere, or already be persisted in the directory. 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TruncateUTF8ToByteSize(name, 255, &name); 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_name(name); 1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Set the non_unique_name. If we do, the server ignores 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the |name| value (using |non_unique_name| instead), and will return 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // in the CommitResponse a unique name if one is generated. 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // We send both because it may aid in logging. 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_non_unique_name(name); 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!meta_entry.GetUniqueClientTag().empty()) { 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_client_defined_unique_tag( 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) meta_entry.GetUniqueClientTag()); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Deleted items with server-unknown parent ids can be a problem so we set 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the parent to 0. (TODO(sync): Still true in protocol?). 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Id new_parent_id; 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (meta_entry.GetIsDel() && 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) !meta_entry.GetParentId().ServerKnows()) { 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new_parent_id = syncable::BaseTransaction::root_id(); 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new_parent_id = meta_entry.GetParentId(); 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (meta_entry.ShouldMaintainHierarchy()) { 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sync_entry->set_parent_id_string(SyncableIdToProto(new_parent_id)); 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If our parent has changed, send up the old one so the server 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // can correctly deal with multiple parents. 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // TODO(nick): With the server keeping track of the primary sync parent, 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // it should not be necessary to provide the old_parent_id: the version 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // number should suffice. 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (new_parent_id != meta_entry.GetServerParentId() && 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 0 != meta_entry.GetBaseVersion() && 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::CHANGES_VERSION != meta_entry.GetBaseVersion()) { 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_old_parent_id( 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SyncableIdToProto(meta_entry.GetServerParentId())); 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int64 version = meta_entry.GetBaseVersion(); 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (syncable::CHANGES_VERSION == version || 0 == version) { 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Undeletions are only supported for items that have a client tag. 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(!id.ServerKnows() || 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) !meta_entry.GetUniqueClientTag().empty()) 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << meta_entry; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Version 0 means to create or undelete an object. 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_version(0); 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(id.ServerKnows()) << meta_entry; 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_version(meta_entry.GetBaseVersion()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_ctime(TimeToProtoTime(meta_entry.GetCtime())); 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_mtime(TimeToProtoTime(meta_entry.GetMtime())); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetAttachmentIds(meta_entry, sync_entry); 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Handle bookmarks separately. 1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (meta_entry.GetSpecifics().has_bookmark()) { 1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (meta_entry.GetIsDel()) { 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_entry->set_deleted(true); 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Both insert_after_item_id and position_in_parent fields are set only 1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // for legacy reasons. See comments in sync.proto for more information. 1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const Id& prev_id = meta_entry.GetPredecessorId(); 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) string prev_id_string = 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) prev_id.IsRoot() ? string() : prev_id.GetServerId(); 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_insert_after_item_id(prev_id_string); 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->set_position_in_parent( 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) meta_entry.GetUniquePosition().ToInt64()); 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) meta_entry.GetUniquePosition().ToProto( 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_entry->mutable_unique_position()); 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Always send specifics for bookmarks. 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SetEntrySpecifics(meta_entry, sync_entry); 1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Deletion is final on the server, let's move things and then delete them. 2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (meta_entry.GetIsDel()) { 2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sync_entry->set_deleted(true); 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sync_pb::EntitySpecifics type_only_specifics; 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AddDefaultFieldValue(meta_entry.GetModelType(), 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sync_entry->mutable_specifics()); 2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } else { 2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SetEntrySpecifics(meta_entry, sync_entry); 2080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Helpers for ProcessSingleCommitResponse. 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace { 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LogServerError(const sync_pb::CommitResponse_EntryResponse& res) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res.has_error_message()) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << " " << res.error_message(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << " No detailed error message returned from server"; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const string& GetResultingPostCommitName( 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::SyncEntity& committed_entry, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::CommitResponse_EntryResponse& entry_response) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& response_name = 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncerProtoUtil::NameFromCommitEntryResponse(entry_response); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response_name.empty()) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return response_name; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SyncerProtoUtil::NameFromSyncEntity(committed_entry); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool UpdateVersionAfterCommit( 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::SyncEntity& committed_entry, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::CommitResponse_EntryResponse& entry_response, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const syncable::Id& pre_commit_id, 2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::ModelNeutralMutableEntry* local_entry) { 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int64 old_version = local_entry->GetBaseVersion(); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 new_version = entry_response.version(); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool bad_commit_version = false; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (committed_entry.deleted() && 240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) !local_entry->GetUniqueClientTag().empty()) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the item was deleted, and it's undeletable (uses the client tag), 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change the version back to zero. We must set the version to zero so 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the server knows to re-create the item if it gets committed 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // later for undeletion. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_version = 0; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!pre_commit_id.ServerKnows()) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bad_commit_version = 0 == new_version; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bad_commit_version = old_version > new_version; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bad_commit_version) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Bad version in commit return for " << *local_entry 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " new_id:" << SyncableIdFromProto(entry_response.id_string()) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " new_version:" << entry_response.version(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the base version and server version. The base version must change 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // here, even if syncing_was_set is false; that's because local changes were 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on top of the successfully committed version. 261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutBaseVersion(new_version); 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DVLOG(1) << "Commit is changing base version of " << local_entry->GetId() 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " to: " << new_version; 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerVersion(new_version); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool ChangeIdAfterCommit( 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::CommitResponse_EntryResponse& entry_response, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const syncable::Id& pre_commit_id, 2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::ModelNeutralMutableEntry* local_entry) { 2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::BaseWriteTransaction* trans = local_entry->base_write_transaction(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const syncable::Id& entry_response_id = 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncableIdFromProto(entry_response.id_string()); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry_response_id != pre_commit_id) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pre_commit_id.ServerKnows()) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The server can sometimes generate a new ID on commit; for example, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when committing an undeletion. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << " ID changed while committing an old entry. " 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << pre_commit_id << " became " << entry_response_id << "."; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::ModelNeutralMutableEntry same_id( 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) trans, 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::GET_BY_ID, 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) entry_response_id); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should trap this before this function. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (same_id.good()) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "ID clash with id " << entry_response_id 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " during commit " << same_id; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChangeEntryIDAndUpdateChildren(trans, local_entry, entry_response_id); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Changing ID to " << entry_response_id; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void UpdateServerFieldsAfterCommit( 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::SyncEntity& committed_entry, 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::CommitResponse_EntryResponse& entry_response, 3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::ModelNeutralMutableEntry* local_entry) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We just committed an entry successfully, and now we want to make our view 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the server state consistent with the server state. We must be careful; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |entry_response| and |committed_entry| have some identically named 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fields. We only want to consider fields from |committed_entry| when there 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is not an overriding field in the |entry_response|. We do not want to 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // update the server data from the local data in the entry -- it's possible 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the local data changed during the commit, and even if not, the server 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has the last word on the values of several properties. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerIsDel(committed_entry.deleted()); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (committed_entry.deleted()) { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't clobber any other fields of deleted objects. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerIsDir( 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (committed_entry.folder() || 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) committed_entry.bookmarkdata().bookmark_folder())); 321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerSpecifics(committed_entry.specifics()); 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch local_entry->PutServerAttachmentMetadata( 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateAttachmentMetadata(committed_entry.attachment_id())); 324d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerMtime(ProtoTimeToTime(committed_entry.mtime())); 325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerCtime(ProtoTimeToTime(committed_entry.ctime())); 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (committed_entry.has_unique_position()) { 327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerUniquePosition( 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition::FromProto( 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) committed_entry.unique_position())); 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(nick): The server doesn't set entry_response.server_parent_id in 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // practice; to update SERVER_PARENT_ID appropriately here we'd need to 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get the post-commit ID of the parent indicated by 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // committed_entry.parent_id_string(). That should be inferrable from the 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // information we have, but it's a bit convoluted to pull it out directly. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Getting this right is important: SERVER_PARENT_ID gets fed back into 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // old_parent_id during the next commit. 339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerParentId(local_entry->GetParentId()); 340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutServerNonUniqueName( 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetResultingPostCommitName(committed_entry, entry_response)); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (local_entry->GetIsUnappliedUpdate()) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This shouldn't happen; an unapplied update shouldn't be committed, and 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if it were, the commit should have failed. But if it does happen: we've 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just overwritten the update info, so clear the flag. 347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutIsUnappliedUpdate(false); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ProcessSuccessfulCommitResponse( 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::SyncEntity& committed_entry, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::CommitResponse_EntryResponse& entry_response, 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const syncable::Id& pre_commit_id, 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::ModelNeutralMutableEntry* local_entry, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool syncing_was_set, set<syncable::Id>* deleted_folders) { 357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK(local_entry->GetIsUnsynced()); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update SERVER_VERSION and BASE_VERSION. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!UpdateVersionAfterCommit(committed_entry, entry_response, pre_commit_id, 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_entry)) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Bad version in commit return for " << *local_entry 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " new_id:" << SyncableIdFromProto(entry_response.id_string()) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " new_version:" << entry_response.version(); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the server gave us a new ID, apply it. 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ChangeIdAfterCommit(entry_response, pre_commit_id, local_entry)) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update our stored copy of the server state. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateServerFieldsAfterCommit(committed_entry, entry_response, local_entry); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the item doesn't need to be committed again (an item might need to be 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // committed again if it changed locally during the commit), we can remove 37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // it from the unsynced list. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (syncing_was_set) { 380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) local_entry->PutIsUnsynced(false); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make a note of any deleted folders, whose children would have 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // been recursively deleted. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(nick): Here, commit_message.deleted() would be more correct than 386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // local_entry->GetIsDel(). For example, an item could be renamed, and then 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // deleted during the commit of the rename. Unit test & fix. 388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (local_entry->GetIsDir() && local_entry->GetIsDel()) { 389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) deleted_folders->insert(local_entry->GetId()); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace 3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)sync_pb::CommitResponse::ResponseType 3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ProcessSingleCommitResponse( 3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::BaseWriteTransaction* trans, 3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const sync_pb::CommitResponse_EntryResponse& server_entry, 3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const sync_pb::SyncEntity& commit_request_entry, 4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int64 metahandle, 4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) set<syncable::Id>* deleted_folders) { 4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::ModelNeutralMutableEntry local_entry( 4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) trans, 4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) syncable::GET_BY_HANDLE, 4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) metahandle); 4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CHECK(local_entry.good()); 4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool syncing_was_set = local_entry.GetSyncing(); 4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) local_entry.PutSyncing(false); 4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sync_pb::CommitResponse::ResponseType response = server_entry.response_type(); 4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!sync_pb::CommitResponse::ResponseType_IsValid(response)) { 4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "Commit response has unknown response type! Possibly out " 4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "of date client?"; 4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return sync_pb::CommitResponse::INVALID_MESSAGE; 4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sync_pb::CommitResponse::TRANSIENT_ERROR == response) { 4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DVLOG(1) << "Transient Error Committing: " << local_entry; 4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LogServerError(server_entry); 4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return sync_pb::CommitResponse::TRANSIENT_ERROR; 4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sync_pb::CommitResponse::INVALID_MESSAGE == response) { 4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "Error Commiting: " << local_entry; 4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LogServerError(server_entry); 4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return response; 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sync_pb::CommitResponse::CONFLICT == response) { 4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DVLOG(1) << "Conflict Committing: " << local_entry; 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return response; 4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sync_pb::CommitResponse::RETRY == response) { 4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DVLOG(1) << "Retry Committing: " << local_entry; 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return response; 4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sync_pb::CommitResponse::OVER_QUOTA == response) { 4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(WARNING) << "Hit deprecated OVER_QUOTA Committing: " << local_entry; 4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return response; 4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!server_entry.has_id_string()) { 4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "Commit response has no id"; 4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return sync_pb::CommitResponse::INVALID_MESSAGE; 4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Implied by the IsValid call above, but here for clarity. 4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(sync_pb::CommitResponse::SUCCESS, response) << response; 4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Check to see if we've been given the ID of an existing entry. If so treat 4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // it as an error response and retry later. 4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const syncable::Id& server_entry_id = 4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SyncableIdFromProto(server_entry.id_string()); 4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (local_entry.GetId() != server_entry_id) { 4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Entry e(trans, syncable::GET_BY_ID, server_entry_id); 4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (e.good()) { 4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) 4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << "Got duplicate id when commiting id: " 4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << local_entry.GetId() 4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << ". Treating as an error return"; 4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return sync_pb::CommitResponse::INVALID_MESSAGE; 4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (server_entry.version() == 0) { 4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(WARNING) << "Server returned a zero version on a commit response."; 4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ProcessSuccessfulCommitResponse(commit_request_entry, server_entry, 4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) local_entry.GetId(), &local_entry, syncing_was_set, deleted_folders); 4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return response; 4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace commit_util 4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncer 472