| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/sync/engine/conflict_resolver.h" | 5 #include "chrome/browser/sync/engine/conflict_resolver.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "chrome/browser/sync/engine/syncer.h" | 10 #include "chrome/browser/sync/engine/syncer.h" |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 // we've both deleted it, so lets just drop the need to commit/update this | 88 // we've both deleted it, so lets just drop the need to commit/update this |
| 89 // entry. | 89 // entry. |
| 90 entry.Put(syncable::IS_UNSYNCED, false); | 90 entry.Put(syncable::IS_UNSYNCED, false); |
| 91 entry.Put(syncable::IS_UNAPPLIED_UPDATE, false); | 91 entry.Put(syncable::IS_UNAPPLIED_UPDATE, false); |
| 92 // we've made changes, but they won't help syncing progress. | 92 // we've made changes, but they won't help syncing progress. |
| 93 // METRIC simple conflict resolved by merge. | 93 // METRIC simple conflict resolved by merge. |
| 94 return NO_SYNC_PROGRESS; | 94 return NO_SYNC_PROGRESS; |
| 95 } | 95 } |
| 96 | 96 |
| 97 if (!entry.Get(syncable::SERVER_IS_DEL)) { | 97 if (!entry.Get(syncable::SERVER_IS_DEL)) { |
| 98 // TODO(chron): Should we check more fields? Since IS_UNSYNCED is | 98 // This logic determines "client wins" vs. "server wins" strategy picking. |
| 99 // turned on, this is really probably enough as fields will be overwritten. | 99 // TODO(nick): The current logic is arbitrary; instead, it ought to be made |
| 100 // Check if there's no changes. | 100 // consistent with the ModelAssociator behavior for a datatype. It would |
| 101 | 101 // be nice if we could route this back to ModelAssociator code to pick one |
| 102 // Verbose but easier to debug. | 102 // of three options: CLIENT, SERVER, or MERGE. Some datatypes (autofill) |
| 103 // are easily mergeable. |
| 103 bool name_matches = entry.Get(syncable::NON_UNIQUE_NAME) == | 104 bool name_matches = entry.Get(syncable::NON_UNIQUE_NAME) == |
| 104 entry.Get(syncable::SERVER_NON_UNIQUE_NAME); | 105 entry.Get(syncable::SERVER_NON_UNIQUE_NAME); |
| 105 bool parent_matches = entry.Get(syncable::PARENT_ID) == | 106 bool parent_matches = entry.Get(syncable::PARENT_ID) == |
| 106 entry.Get(syncable::SERVER_PARENT_ID); | 107 entry.Get(syncable::SERVER_PARENT_ID); |
| 107 bool entry_deleted = entry.Get(syncable::IS_DEL); | 108 bool entry_deleted = entry.Get(syncable::IS_DEL); |
| 108 | 109 |
| 109 if (!entry_deleted && name_matches && parent_matches) { | 110 if (!entry_deleted && name_matches && parent_matches) { |
| 110 LOG(INFO) << "Resolving simple conflict, ignoring local changes for:" | 111 LOG(INFO) << "Resolving simple conflict, ignoring local changes for:" |
| 111 << entry; | 112 << entry; |
| 112 IgnoreLocalChanges(&entry); | 113 IgnoreLocalChanges(&entry); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 123 trans->directory()->GetChildHandles(trans, | 124 trans->directory()->GetChildHandles(trans, |
| 124 entry.Get(syncable::ID), | 125 entry.Get(syncable::ID), |
| 125 &children); | 126 &children); |
| 126 if (0 != children.size()) { | 127 if (0 != children.size()) { |
| 127 LOG(INFO) << "Entry is a server deleted directory with local contents, " | 128 LOG(INFO) << "Entry is a server deleted directory with local contents, " |
| 128 "should be in a set. (race condition)."; | 129 "should be in a set. (race condition)."; |
| 129 return NO_SYNC_PROGRESS; | 130 return NO_SYNC_PROGRESS; |
| 130 } | 131 } |
| 131 } | 132 } |
| 132 | 133 |
| 133 // If the entry's deleted on the server, we can have a directory here. | 134 // The entry is deleted on the server but still exists locally. |
| 134 entry.Put(syncable::IS_UNSYNCED, true); | 135 if (!entry.Get(syncable::UNIQUE_CLIENT_TAG).empty()) { |
| 136 // If we've got a client-unique tag, we can undelete while retaining |
| 137 // our present ID. |
| 138 DCHECK_EQ(entry.Get(syncable::SERVER_VERSION), 0) |
| 139 << "For the server to know to re-create, client-tagged items should " |
| 140 << "revert to version 0 when server-deleted."; |
| 141 OverwriteServerChanges(trans, &entry); |
| 142 // Clobber the versions, just in case the above DCHECK is violated. |
| 143 entry.Put(syncable::SERVER_VERSION, 0); |
| 144 entry.Put(syncable::BASE_VERSION, 0); |
| 145 } else { |
| 146 // Otherwise, we've got to undelete by creating a new locally |
| 147 // uncommitted entry. |
| 148 SyncerUtil::SplitServerInformationIntoNewEntry(trans, &entry); |
| 135 | 149 |
| 136 SyncerUtil::SplitServerInformationIntoNewEntry(trans, &entry); | 150 MutableEntry server_update(trans, syncable::GET_BY_ID, id); |
| 137 | 151 CHECK(server_update.good()); |
| 138 MutableEntry server_update(trans, syncable::GET_BY_ID, id); | 152 CHECK(server_update.Get(syncable::META_HANDLE) != |
| 139 CHECK(server_update.good()); | 153 entry.Get(syncable::META_HANDLE)) |
| 140 CHECK(server_update.Get(syncable::META_HANDLE) != | 154 << server_update << entry; |
| 141 entry.Get(syncable::META_HANDLE)) | 155 } |
| 142 << server_update << entry; | |
| 143 | |
| 144 return SYNC_PROGRESS; | 156 return SYNC_PROGRESS; |
| 145 } | 157 } |
| 146 } | 158 } |
| 147 | 159 |
| 148 ConflictResolver::ConflictSetCountMapKey ConflictResolver::GetSetKey( | 160 ConflictResolver::ConflictSetCountMapKey ConflictResolver::GetSetKey( |
| 149 ConflictSet* set) { | 161 ConflictSet* set) { |
| 150 // TODO(sync): Come up with a better scheme for set hashing. This scheme | 162 // TODO(sync): Come up with a better scheme for set hashing. This scheme |
| 151 // will make debugging easy. | 163 // will make debugging easy. |
| 152 // If this call to sort is removed, we need to add one before we use | 164 // If this call to sort is removed, we need to add one before we use |
| 153 // binary_search in ProcessConflictSet. | 165 // binary_search in ProcessConflictSet. |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 SyncerUtil::ChangeEntryIDAndUpdateChildren(trans, &parent, | 250 SyncerUtil::ChangeEntryIDAndUpdateChildren(trans, &parent, |
| 239 trans->directory()->NextId()); | 251 trans->directory()->NextId()); |
| 240 parent.Put(syncable::BASE_VERSION, 0); | 252 parent.Put(syncable::BASE_VERSION, 0); |
| 241 parent.Put(syncable::IS_UNSYNCED, true); | 253 parent.Put(syncable::IS_UNSYNCED, true); |
| 242 id = parent.Get(syncable::PARENT_ID); | 254 id = parent.Get(syncable::PARENT_ID); |
| 243 // METRIC conflict resolved by recreating dir tree. | 255 // METRIC conflict resolved by recreating dir tree. |
| 244 } | 256 } |
| 245 return true; | 257 return true; |
| 246 } | 258 } |
| 247 | 259 |
| 248 | |
| 249 // TODO(chron): needs unit test badly | 260 // TODO(chron): needs unit test badly |
| 250 bool AttemptToFixUpdateEntryInDeletedLocalTree(WriteTransaction* trans, | 261 bool AttemptToFixUpdateEntryInDeletedLocalTree(WriteTransaction* trans, |
| 251 ConflictSet* conflict_set, | 262 ConflictSet* conflict_set, |
| 252 const Entry& entry) { | 263 const Entry& entry) { |
| 253 if (!entry.Get(syncable::IS_UNAPPLIED_UPDATE) || | 264 if (!entry.Get(syncable::IS_UNAPPLIED_UPDATE) || |
| 254 entry.Get(syncable::SERVER_IS_DEL)) | 265 entry.Get(syncable::SERVER_IS_DEL)) |
| 255 return false; | 266 return false; |
| 256 Id parent_id = entry.Get(syncable::SERVER_PARENT_ID); | 267 Id parent_id = entry.Get(syncable::SERVER_PARENT_ID); |
| 257 MutableEntry parent(trans, syncable::GET_BY_ID, parent_id); | 268 MutableEntry parent(trans, syncable::GET_BY_ID, parent_id); |
| 258 if (!parent.good() || !parent.Get(syncable::IS_DEL) || | 269 if (!parent.good() || !parent.Get(syncable::IS_DEL) || |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 conflict_set_count_map_.erase(i++); | 511 conflict_set_count_map_.erase(i++); |
| 501 // METRIC self resolved conflict sets ++. | 512 // METRIC self resolved conflict sets ++. |
| 502 } else { | 513 } else { |
| 503 ++i; | 514 ++i; |
| 504 } | 515 } |
| 505 } | 516 } |
| 506 return rv; | 517 return rv; |
| 507 } | 518 } |
| 508 | 519 |
| 509 } // namespace browser_sync | 520 } // namespace browser_sync |
| OLD | NEW |