This source file includes following definitions.
- ProcessSimpleConflict
- ResolveConflicts
#include "sync/engine/conflict_resolver.h"
#include <list>
#include <set>
#include <string>
#include "base/metrics/histogram.h"
#include "sync/engine/conflict_util.h"
#include "sync/engine/syncer_util.h"
#include "sync/sessions/status_controller.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/mutable_entry.h"
#include "sync/syncable/syncable_write_transaction.h"
#include "sync/util/cryptographer.h"
using std::list;
using std::set;
namespace syncer {
using sessions::StatusController;
using syncable::Directory;
using syncable::Entry;
using syncable::Id;
using syncable::MutableEntry;
using syncable::WriteTransaction;
ConflictResolver::ConflictResolver() {
}
ConflictResolver::~ConflictResolver() {
}
void ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans,
const Id& id,
const Cryptographer* cryptographer,
StatusController* status) {
MutableEntry entry(trans, syncable::GET_BY_ID, id);
CHECK(entry.good());
if (!entry.GetIsUnappliedUpdate() || !entry.GetIsUnsynced()) {
return;
}
if (entry.GetIsDel() && entry.GetServerIsDel()) {
entry.PutIsUnsynced(false);
entry.PutIsUnappliedUpdate(false);
return;
}
if (!entry.GetServerIsDel()) {
bool name_matches = entry.GetNonUniqueName() ==
entry.GetServerNonUniqueName();
bool parent_matches = entry.GetParentId() == entry.GetServerParentId();
bool entry_deleted = entry.GetIsDel();
bool position_matches = parent_matches &&
entry.GetServerUniquePosition().Equals(entry.GetUniquePosition());
const sync_pb::EntitySpecifics& specifics = entry.GetSpecifics();
const sync_pb::EntitySpecifics& server_specifics =
entry.GetServerSpecifics();
const sync_pb::EntitySpecifics& base_server_specifics =
entry.GetBaseServerSpecifics();
std::string decrypted_specifics, decrypted_server_specifics;
bool specifics_match = false;
bool server_encrypted_with_default_key = false;
if (specifics.has_encrypted()) {
DCHECK(cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted()));
decrypted_specifics = cryptographer->DecryptToString(
specifics.encrypted());
} else {
decrypted_specifics = specifics.SerializeAsString();
}
if (server_specifics.has_encrypted()) {
server_encrypted_with_default_key =
cryptographer->CanDecryptUsingDefaultKey(
server_specifics.encrypted());
decrypted_server_specifics = cryptographer->DecryptToString(
server_specifics.encrypted());
} else {
decrypted_server_specifics = server_specifics.SerializeAsString();
}
if (decrypted_server_specifics == decrypted_specifics &&
server_encrypted_with_default_key == specifics.has_encrypted()) {
specifics_match = true;
}
bool base_server_specifics_match = false;
if (server_specifics.has_encrypted() &&
IsRealDataType(GetModelTypeFromSpecifics(base_server_specifics))) {
std::string decrypted_base_server_specifics;
if (!base_server_specifics.has_encrypted()) {
decrypted_base_server_specifics =
base_server_specifics.SerializeAsString();
} else {
decrypted_base_server_specifics = cryptographer->DecryptToString(
base_server_specifics.encrypted());
}
if (decrypted_server_specifics == decrypted_base_server_specifics)
base_server_specifics_match = true;
}
if (!entry_deleted && name_matches && parent_matches && specifics_match &&
position_matches) {
DVLOG(1) << "Resolving simple conflict, everything matches, ignoring "
<< "changes for: " << entry;
conflict_util::IgnoreConflict(&entry);
UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
CHANGES_MATCH,
CONFLICT_RESOLUTION_SIZE);
} else if (base_server_specifics_match) {
DVLOG(1) << "Resolving simple conflict, ignoring server encryption "
<< " changes for: " << entry;
status->increment_num_server_overwrites();
conflict_util::OverwriteServerChanges(&entry);
UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
IGNORE_ENCRYPTION,
CONFLICT_RESOLUTION_SIZE);
} else if (entry_deleted || !name_matches || !parent_matches) {
conflict_util::OverwriteServerChanges(&entry);
status->increment_num_server_overwrites();
DVLOG(1) << "Resolving simple conflict, overwriting server changes "
<< "for: " << entry;
UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
OVERWRITE_SERVER,
CONFLICT_RESOLUTION_SIZE);
} else {
DVLOG(1) << "Resolving simple conflict, ignoring local changes for: "
<< entry;
conflict_util::IgnoreLocalChanges(&entry);
status->increment_num_local_overwrites();
UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
OVERWRITE_LOCAL,
CONFLICT_RESOLUTION_SIZE);
}
entry.PutBaseServerSpecifics(sync_pb::EntitySpecifics());
} else {
if (entry.GetIsDir()) {
Directory::Metahandles children;
trans->directory()->GetChildHandlesById(trans,
entry.GetId(),
&children);
DCHECK(children.empty());
}
conflict_util::OverwriteServerChanges(&entry);
status->increment_num_server_overwrites();
DVLOG(1) << "Resolving simple conflict, undeleting server entry: "
<< entry;
UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
UNDELETE,
CONFLICT_RESOLUTION_SIZE);
}
}
void ConflictResolver::ResolveConflicts(
syncable::WriteTransaction* trans,
const Cryptographer* cryptographer,
const std::set<syncable::Id>& simple_conflict_ids,
sessions::StatusController* status) {
set<Id>::const_iterator it;
for (it = simple_conflict_ids.begin();
it != simple_conflict_ids.end();
++it) {
Entry conflicting_node(trans, syncable::GET_BY_ID, *it);
CHECK(conflicting_node.good());
if (IsControlType(
GetModelTypeFromSpecifics(conflicting_node.GetSpecifics()))) {
continue;
}
ProcessSimpleConflict(trans, *it, cryptographer, status);
}
return;
}
}