| Index: sync/engine/verify_updates_command.cc
|
| diff --git a/sync/engine/verify_updates_command.cc b/sync/engine/verify_updates_command.cc
|
| deleted file mode 100644
|
| index b8bc043987ee985ffd8555882b55bc37b73d418a..0000000000000000000000000000000000000000
|
| --- a/sync/engine/verify_updates_command.cc
|
| +++ /dev/null
|
| @@ -1,210 +0,0 @@
|
| -// Copyright (c) 2012 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/verify_updates_command.h"
|
| -
|
| -#include <string>
|
| -
|
| -#include "base/location.h"
|
| -#include "sync/engine/syncer.h"
|
| -#include "sync/engine/syncer_proto_util.h"
|
| -#include "sync/engine/syncer_types.h"
|
| -#include "sync/engine/syncer_util.h"
|
| -#include "sync/internal_api/public/engine/model_safe_worker.h"
|
| -#include "sync/protocol/bookmark_specifics.pb.h"
|
| -#include "sync/protocol/sync.pb.h"
|
| -#include "sync/syncable/entry.h"
|
| -#include "sync/syncable/mutable_entry.h"
|
| -#include "sync/syncable/syncable_proto_util.h"
|
| -#include "sync/syncable/write_transaction.h"
|
| -
|
| -namespace syncer {
|
| -
|
| -using syncable::GET_BY_ID;
|
| -using syncable::SYNCER;
|
| -using syncable::WriteTransaction;
|
| -
|
| -namespace {
|
| -
|
| -// This function attempts to determine whether or not this update is genuinely
|
| -// new, or if it is a reflection of one of our own commits.
|
| -//
|
| -// There is a known inaccuracy in its implementation. If this update ends up
|
| -// being applied to a local item with a different ID, we will count the change
|
| -// as being a non-reflection update. Fortunately, the server usually updates
|
| -// our IDs correctly in its commit response, so a new ID during GetUpdate should
|
| -// be rare.
|
| -//
|
| -// The only secnarios I can think of where this might happen are:
|
| -// - We commit a new item to the server, but we don't persist the
|
| -// server-returned new ID to the database before we shut down. On the GetUpdate
|
| -// following the next restart, we will receive an update from the server that
|
| -// updates its local ID.
|
| -// - When two attempts to create an item with identical UNIQUE_CLIENT_TAG values
|
| -// collide at the server. I have seen this in testing. When it happens, the
|
| -// test server will send one of the clients a response to upate its local ID so
|
| -// that both clients will refer to the item using the same ID going forward. In
|
| -// this case, we're right to assume that the update is not a reflection.
|
| -//
|
| -// For more information, see FindLocalIdToUpdate().
|
| -bool UpdateContainsNewVersion(syncable::BaseTransaction *trans,
|
| - const sync_pb::SyncEntity &update) {
|
| - int64 existing_version = -1; // The server always sends positive versions.
|
| - syncable::Entry existing_entry(trans, GET_BY_ID,
|
| - SyncableIdFromProto(update.id_string()));
|
| - if (existing_entry.good())
|
| - existing_version = existing_entry.Get(syncable::BASE_VERSION);
|
| -
|
| - if (!existing_entry.good() && update.deleted()) {
|
| - // There are several possible explanations for this. The most common cases
|
| - // will be first time sync and the redelivery of deletions we've already
|
| - // synced, accepted, and purged from our database. In either case, the
|
| - // update is useless to us. Let's count them all as "not new", even though
|
| - // that may not always be entirely accurate.
|
| - return false;
|
| - }
|
| -
|
| - if (existing_entry.good() &&
|
| - !existing_entry.Get(syncable::UNIQUE_CLIENT_TAG).empty() &&
|
| - existing_entry.Get(syncable::IS_DEL) &&
|
| - update.deleted()) {
|
| - // Unique client tags will have their version set to zero when they're
|
| - // deleted. The usual version comparison logic won't be able to detect
|
| - // reflections of these items. Instead, we assume any received tombstones
|
| - // are reflections. That should be correct most of the time.
|
| - return false;
|
| - }
|
| -
|
| - return existing_version < update.version();
|
| -}
|
| -
|
| -// In the event that IDs match, but tags differ AttemptReuniteClient tag
|
| -// will have refused to unify the update.
|
| -// We should not attempt to apply it at all since it violates consistency
|
| -// rules.
|
| -VerifyResult VerifyTagConsistency(const sync_pb::SyncEntity& entry,
|
| - const syncable::MutableEntry& same_id) {
|
| - if (entry.has_client_defined_unique_tag() &&
|
| - entry.client_defined_unique_tag() !=
|
| - same_id.Get(syncable::UNIQUE_CLIENT_TAG)) {
|
| - return VERIFY_FAIL;
|
| - }
|
| - return VERIFY_UNDECIDED;
|
| -}
|
| -} // namespace
|
| -
|
| -VerifyUpdatesCommand::VerifyUpdatesCommand() {}
|
| -VerifyUpdatesCommand::~VerifyUpdatesCommand() {}
|
| -
|
| -std::set<ModelSafeGroup> VerifyUpdatesCommand::GetGroupsToChange(
|
| - const sessions::SyncSession& session) const {
|
| - std::set<ModelSafeGroup> groups_with_updates;
|
| -
|
| - const sync_pb::GetUpdatesResponse& updates =
|
| - session.status_controller().updates_response().get_updates();
|
| - for (int i = 0; i < updates.entries().size(); i++) {
|
| - groups_with_updates.insert(
|
| - GetGroupForModelType(GetModelType(updates.entries(i)),
|
| - session.routing_info()));
|
| - }
|
| -
|
| - return groups_with_updates;
|
| -}
|
| -
|
| -SyncerError VerifyUpdatesCommand::ModelChangingExecuteImpl(
|
| - sessions::SyncSession* session) {
|
| - DVLOG(1) << "Beginning Update Verification";
|
| - syncable::Directory* dir = session->context()->directory();
|
| - WriteTransaction trans(FROM_HERE, SYNCER, dir);
|
| - sessions::StatusController* status = session->mutable_status_controller();
|
| - const sync_pb::GetUpdatesResponse& updates =
|
| - status->updates_response().get_updates();
|
| - int update_count = updates.entries().size();
|
| -
|
| - ModelTypeSet requested_types = GetRoutingInfoTypes(
|
| - session->routing_info());
|
| -
|
| - DVLOG(1) << update_count << " entries to verify";
|
| - for (int i = 0; i < update_count; i++) {
|
| - const sync_pb::SyncEntity& update = updates.entries(i);
|
| - ModelSafeGroup g = GetGroupForModelType(GetModelType(update),
|
| - session->routing_info());
|
| - if (g != status->group_restriction())
|
| - continue;
|
| -
|
| - VerifyUpdateResult result = VerifyUpdate(&trans, update,
|
| - requested_types,
|
| - session->routing_info());
|
| - status->mutable_update_progress()->AddVerifyResult(result.value, update);
|
| - status->increment_num_updates_downloaded_by(1);
|
| - if (!UpdateContainsNewVersion(&trans, update))
|
| - status->increment_num_reflected_updates_downloaded_by(1);
|
| - if (update.deleted())
|
| - status->increment_num_tombstone_updates_downloaded_by(1);
|
| - }
|
| -
|
| - return SYNCER_OK;
|
| -}
|
| -
|
| -VerifyUpdatesCommand::VerifyUpdateResult VerifyUpdatesCommand::VerifyUpdate(
|
| - syncable::WriteTransaction* trans, const sync_pb::SyncEntity& entry,
|
| - ModelTypeSet requested_types,
|
| - const ModelSafeRoutingInfo& routes) {
|
| - syncable::Id id = SyncableIdFromProto(entry.id_string());
|
| - VerifyUpdateResult result = {VERIFY_FAIL, GROUP_PASSIVE};
|
| -
|
| - const bool deleted = entry.has_deleted() && entry.deleted();
|
| - const bool is_directory = IsFolder(entry);
|
| - const ModelType model_type = GetModelType(entry);
|
| -
|
| - if (!id.ServerKnows()) {
|
| - LOG(ERROR) << "Illegal negative id in received updates";
|
| - return result;
|
| - }
|
| - {
|
| - const std::string name = SyncerProtoUtil::NameFromSyncEntity(entry);
|
| - if (name.empty() && !deleted) {
|
| - LOG(ERROR) << "Zero length name in non-deleted update";
|
| - return result;
|
| - }
|
| - }
|
| -
|
| - syncable::MutableEntry same_id(trans, GET_BY_ID, id);
|
| - result.value = VerifyNewEntry(entry, &same_id, deleted);
|
| -
|
| - ModelType placement_type = !deleted ? GetModelType(entry)
|
| - : same_id.good() ? same_id.GetModelType() : UNSPECIFIED;
|
| - result.placement = GetGroupForModelType(placement_type, routes);
|
| -
|
| - if (VERIFY_UNDECIDED == result.value) {
|
| - result.value = VerifyTagConsistency(entry, same_id);
|
| - }
|
| -
|
| - if (VERIFY_UNDECIDED == result.value) {
|
| - if (deleted) {
|
| - // For deletes the server could send tombostones for items that
|
| - // the client did not request. If so ignore those items.
|
| - if (IsRealDataType(placement_type) &&
|
| - !requested_types.Has(placement_type)) {
|
| - result.value = VERIFY_SKIP;
|
| - } else {
|
| - result.value = VERIFY_SUCCESS;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // If we have an existing entry, we check here for updates that break
|
| - // consistency rules.
|
| - if (VERIFY_UNDECIDED == result.value) {
|
| - result.value = VerifyUpdateConsistency(trans, entry, &same_id,
|
| - deleted, is_directory, model_type);
|
| - }
|
| -
|
| - if (VERIFY_UNDECIDED == result.value)
|
| - result.value = VERIFY_SUCCESS; // No news is good news.
|
| -
|
| - return result; // This might be VERIFY_SUCCESS as well
|
| -}
|
| -
|
| -} // namespace syncer
|
|
|