| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "sync/engine/sync_thread_sync_entity.h" | 5 #include "sync/engine/entity_tracker.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "sync/engine/non_blocking_sync_common.h" | 8 #include "sync/engine/non_blocking_sync_common.h" |
| 9 #include "sync/internal_api/public/base/model_type.h" | 9 #include "sync/internal_api/public/base/model_type.h" |
| 10 #include "sync/syncable/syncable_util.h" | 10 #include "sync/syncable/syncable_util.h" |
| 11 #include "sync/util/time.h" | 11 #include "sync/util/time.h" |
| 12 | 12 |
| 13 namespace syncer { | 13 namespace syncer { |
| 14 | 14 |
| 15 SyncThreadSyncEntity* SyncThreadSyncEntity::FromServerUpdate( | 15 EntityTracker* EntityTracker::FromServerUpdate( |
| 16 const std::string& id_string, | 16 const std::string& id_string, |
| 17 const std::string& client_tag_hash, | 17 const std::string& client_tag_hash, |
| 18 int64 received_version) { | 18 int64 received_version) { |
| 19 return new SyncThreadSyncEntity( | 19 return new EntityTracker(id_string, client_tag_hash, 0, received_version); |
| 20 id_string, client_tag_hash, 0, received_version); | |
| 21 } | 20 } |
| 22 | 21 |
| 23 SyncThreadSyncEntity* SyncThreadSyncEntity::FromCommitRequest( | 22 EntityTracker* EntityTracker::FromCommitRequest( |
| 24 const std::string& id_string, | 23 const std::string& id_string, |
| 25 const std::string& client_tag_hash, | 24 const std::string& client_tag_hash, |
| 26 int64 sequence_number, | 25 int64 sequence_number, |
| 27 int64 base_version, | 26 int64 base_version, |
| 28 base::Time ctime, | 27 base::Time ctime, |
| 29 base::Time mtime, | 28 base::Time mtime, |
| 30 const std::string& non_unique_name, | 29 const std::string& non_unique_name, |
| 31 bool deleted, | 30 bool deleted, |
| 32 const sync_pb::EntitySpecifics& specifics) { | 31 const sync_pb::EntitySpecifics& specifics) { |
| 33 return new SyncThreadSyncEntity(id_string, | 32 return new EntityTracker(id_string, |
| 34 client_tag_hash, | 33 client_tag_hash, |
| 35 0, | 34 0, |
| 36 0, | 35 0, |
| 37 true, | 36 true, |
| 38 sequence_number, | 37 sequence_number, |
| 39 base_version, | 38 base_version, |
| 40 ctime, | 39 ctime, |
| 41 mtime, | 40 mtime, |
| 42 non_unique_name, | 41 non_unique_name, |
| 43 deleted, | 42 deleted, |
| 44 specifics); | 43 specifics); |
| 45 } | 44 } |
| 46 | 45 |
| 47 // Constructor that does not set any pending commit fields. | 46 // Constructor that does not set any pending commit fields. |
| 48 SyncThreadSyncEntity::SyncThreadSyncEntity( | 47 EntityTracker::EntityTracker(const std::string& id, |
| 49 const std::string& id, | 48 const std::string& client_tag_hash, |
| 50 const std::string& client_tag_hash, | 49 int64 highest_commit_response_version, |
| 51 int64 highest_commit_response_version, | 50 int64 highest_gu_response_version) |
| 52 int64 highest_gu_response_version) | |
| 53 : id_(id), | 51 : id_(id), |
| 54 client_tag_hash_(client_tag_hash), | 52 client_tag_hash_(client_tag_hash), |
| 55 highest_commit_response_version_(highest_commit_response_version), | 53 highest_commit_response_version_(highest_commit_response_version), |
| 56 highest_gu_response_version_(highest_gu_response_version), | 54 highest_gu_response_version_(highest_gu_response_version), |
| 57 is_commit_pending_(false), | 55 is_commit_pending_(false), |
| 58 sequence_number_(0), | 56 sequence_number_(0), |
| 59 base_version_(0), | 57 base_version_(0), |
| 60 deleted_(false) { | 58 deleted_(false) { |
| 61 } | 59 } |
| 62 | 60 |
| 63 SyncThreadSyncEntity::SyncThreadSyncEntity( | 61 EntityTracker::EntityTracker(const std::string& id, |
| 64 const std::string& id, | 62 const std::string& client_tag_hash, |
| 65 const std::string& client_tag_hash, | 63 int64 highest_commit_response_version, |
| 66 int64 highest_commit_response_version, | 64 int64 highest_gu_response_version, |
| 67 int64 highest_gu_response_version, | 65 bool is_commit_pending, |
| 68 bool is_commit_pending, | 66 int64 sequence_number, |
| 69 int64 sequence_number, | 67 int64 base_version, |
| 70 int64 base_version, | 68 base::Time ctime, |
| 71 base::Time ctime, | 69 base::Time mtime, |
| 72 base::Time mtime, | 70 const std::string& non_unique_name, |
| 73 const std::string& non_unique_name, | 71 bool deleted, |
| 74 bool deleted, | 72 const sync_pb::EntitySpecifics& specifics) |
| 75 const sync_pb::EntitySpecifics& specifics) | |
| 76 : id_(id), | 73 : id_(id), |
| 77 client_tag_hash_(client_tag_hash), | 74 client_tag_hash_(client_tag_hash), |
| 78 highest_commit_response_version_(highest_commit_response_version), | 75 highest_commit_response_version_(highest_commit_response_version), |
| 79 highest_gu_response_version_(highest_gu_response_version), | 76 highest_gu_response_version_(highest_gu_response_version), |
| 80 is_commit_pending_(is_commit_pending), | 77 is_commit_pending_(is_commit_pending), |
| 81 sequence_number_(sequence_number), | 78 sequence_number_(sequence_number), |
| 82 base_version_(base_version), | 79 base_version_(base_version), |
| 83 ctime_(ctime), | 80 ctime_(ctime), |
| 84 mtime_(mtime), | 81 mtime_(mtime), |
| 85 non_unique_name_(non_unique_name), | 82 non_unique_name_(non_unique_name), |
| 86 deleted_(deleted), | 83 deleted_(deleted), |
| 87 specifics_(specifics) { | 84 specifics_(specifics) { |
| 88 } | 85 } |
| 89 | 86 |
| 90 SyncThreadSyncEntity::~SyncThreadSyncEntity() { | 87 EntityTracker::~EntityTracker() { |
| 91 } | 88 } |
| 92 | 89 |
| 93 bool SyncThreadSyncEntity::IsCommitPending() const { | 90 bool EntityTracker::IsCommitPending() const { |
| 94 return is_commit_pending_; | 91 return is_commit_pending_; |
| 95 } | 92 } |
| 96 | 93 |
| 97 void SyncThreadSyncEntity::PrepareCommitProto( | 94 void EntityTracker::PrepareCommitProto(sync_pb::SyncEntity* commit_entity, |
| 98 sync_pb::SyncEntity* commit_entity, | 95 int64* sequence_number) const { |
| 99 int64* sequence_number) const { | |
| 100 // Set ID if we have a server-assigned ID. Otherwise, it will be up to | 96 // Set ID if we have a server-assigned ID. Otherwise, it will be up to |
| 101 // our caller to assign a client-unique initial ID. | 97 // our caller to assign a client-unique initial ID. |
| 102 if (base_version_ != kUncommittedVersion) { | 98 if (base_version_ != kUncommittedVersion) { |
| 103 commit_entity->set_id_string(id_); | 99 commit_entity->set_id_string(id_); |
| 104 } | 100 } |
| 105 | 101 |
| 106 commit_entity->set_client_defined_unique_tag(client_tag_hash_); | 102 commit_entity->set_client_defined_unique_tag(client_tag_hash_); |
| 107 commit_entity->set_version(base_version_); | 103 commit_entity->set_version(base_version_); |
| 108 commit_entity->set_deleted(deleted_); | 104 commit_entity->set_deleted(deleted_); |
| 109 commit_entity->set_folder(false); | 105 commit_entity->set_folder(false); |
| 110 commit_entity->set_name(non_unique_name_); | 106 commit_entity->set_name(non_unique_name_); |
| 111 if (!deleted_) { | 107 if (!deleted_) { |
| 112 commit_entity->set_ctime(TimeToProtoTime(ctime_)); | 108 commit_entity->set_ctime(TimeToProtoTime(ctime_)); |
| 113 commit_entity->set_mtime(TimeToProtoTime(mtime_)); | 109 commit_entity->set_mtime(TimeToProtoTime(mtime_)); |
| 114 commit_entity->mutable_specifics()->CopyFrom(specifics_); | 110 commit_entity->mutable_specifics()->CopyFrom(specifics_); |
| 115 } | 111 } |
| 116 | 112 |
| 117 *sequence_number = sequence_number_; | 113 *sequence_number = sequence_number_; |
| 118 } | 114 } |
| 119 | 115 |
| 120 void SyncThreadSyncEntity::RequestCommit( | 116 void EntityTracker::RequestCommit(const std::string& id, |
| 121 const std::string& id, | 117 const std::string& client_tag_hash, |
| 122 const std::string& client_tag_hash, | 118 int64 sequence_number, |
| 123 int64 sequence_number, | 119 int64 base_version, |
| 124 int64 base_version, | 120 base::Time ctime, |
| 125 base::Time ctime, | 121 base::Time mtime, |
| 126 base::Time mtime, | 122 const std::string& non_unique_name, |
| 127 const std::string& non_unique_name, | 123 bool deleted, |
| 128 bool deleted, | 124 const sync_pb::EntitySpecifics& specifics) { |
| 129 const sync_pb::EntitySpecifics& specifics) { | |
| 130 DCHECK_GE(base_version, base_version_) | 125 DCHECK_GE(base_version, base_version_) |
| 131 << "Base version should never decrease"; | 126 << "Base version should never decrease"; |
| 132 | 127 |
| 133 DCHECK_GE(sequence_number, sequence_number_) | 128 DCHECK_GE(sequence_number, sequence_number_) |
| 134 << "Sequence number should never decrease"; | 129 << "Sequence number should never decrease"; |
| 135 | 130 |
| 136 // Update our book-keeping counters. | 131 // Update our book-keeping counters. |
| 137 base_version_ = base_version; | 132 base_version_ = base_version; |
| 138 sequence_number_ = sequence_number; | 133 sequence_number_ = sequence_number; |
| 139 | 134 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 165 DCHECK_EQ(client_tag_hash_, client_tag_hash); | 160 DCHECK_EQ(client_tag_hash_, client_tag_hash); |
| 166 | 161 |
| 167 // Set the fields for the pending commit. | 162 // Set the fields for the pending commit. |
| 168 ctime_ = ctime; | 163 ctime_ = ctime; |
| 169 mtime_ = mtime; | 164 mtime_ = mtime; |
| 170 non_unique_name_ = non_unique_name; | 165 non_unique_name_ = non_unique_name; |
| 171 deleted_ = deleted; | 166 deleted_ = deleted; |
| 172 specifics_ = specifics; | 167 specifics_ = specifics; |
| 173 } | 168 } |
| 174 | 169 |
| 175 void SyncThreadSyncEntity::ReceiveCommitResponse(const std::string& response_id, | 170 void EntityTracker::ReceiveCommitResponse(const std::string& response_id, |
| 176 int64 response_version, | 171 int64 response_version, |
| 177 int64 sequence_number) { | 172 int64 sequence_number) { |
| 178 // Commit responses, especially after the first commit, can update our ID. | 173 // Commit responses, especially after the first commit, can update our ID. |
| 179 id_ = response_id; | 174 id_ = response_id; |
| 180 | 175 |
| 181 DCHECK_GT(response_version, highest_commit_response_version_) | 176 DCHECK_GT(response_version, highest_commit_response_version_) |
| 182 << "Had expected higher response version." | 177 << "Had expected higher response version." |
| 183 << " id: " << id_; | 178 << " id: " << id_; |
| 184 | 179 |
| 185 // Commits are synchronous, so there's no reason why the sequence numbers | 180 // Commits are synchronous, so there's no reason why the sequence numbers |
| 186 // wouldn't match. | 181 // wouldn't match. |
| 187 DCHECK_EQ(sequence_number_, sequence_number) | 182 DCHECK_EQ(sequence_number_, sequence_number) |
| 188 << "Unexpected sequence number mismatch." | 183 << "Unexpected sequence number mismatch." |
| 189 << " id: " << id_; | 184 << " id: " << id_; |
| 190 | 185 |
| 191 highest_commit_response_version_ = response_version; | 186 highest_commit_response_version_ = response_version; |
| 192 | 187 |
| 193 // Because an in-progress commit blocks the sync thread, we can assume that | 188 // Because an in-progress commit blocks the sync thread, we can assume that |
| 194 // the item we just committed successfully is exactly the one we have now. | 189 // the item we just committed successfully is exactly the one we have now. |
| 195 // Nothing changed it while the commit was happening. Since we're now in | 190 // Nothing changed it while the commit was happening. Since we're now in |
| 196 // sync with the server, we can clear the pending commit. | 191 // sync with the server, we can clear the pending commit. |
| 197 ClearPendingCommit(); | 192 ClearPendingCommit(); |
| 198 } | 193 } |
| 199 | 194 |
| 200 void SyncThreadSyncEntity::ReceiveUpdate(int64 version) { | 195 void EntityTracker::ReceiveUpdate(int64 version) { |
| 201 highest_gu_response_version_ = | 196 highest_gu_response_version_ = |
| 202 std::max(highest_gu_response_version_, version); | 197 std::max(highest_gu_response_version_, version); |
| 203 | 198 |
| 204 if (IsInConflict()) { | 199 if (IsInConflict()) { |
| 205 // Incoming update clobbers the pending commit on the sync thread. | 200 // Incoming update clobbers the pending commit on the sync thread. |
| 206 // The model thread can re-request this commit later if it wants to. | 201 // The model thread can re-request this commit later if it wants to. |
| 207 ClearPendingCommit(); | 202 ClearPendingCommit(); |
| 208 } | 203 } |
| 209 } | 204 } |
| 210 | 205 |
| 211 bool SyncThreadSyncEntity::IsInConflict() const { | 206 bool EntityTracker::IsInConflict() const { |
| 212 if (!is_commit_pending_) | 207 if (!is_commit_pending_) |
| 213 return false; | 208 return false; |
| 214 | 209 |
| 215 if (highest_gu_response_version_ <= highest_commit_response_version_) { | 210 if (highest_gu_response_version_ <= highest_commit_response_version_) { |
| 216 // The most recent server state was created in a commit made by this | 211 // The most recent server state was created in a commit made by this |
| 217 // client. We're fully up to date, and therefore not in conflict. | 212 // client. We're fully up to date, and therefore not in conflict. |
| 218 return false; | 213 return false; |
| 219 } else { | 214 } else { |
| 220 // The most recent server state was written by someone else. | 215 // The most recent server state was written by someone else. |
| 221 // Did the model thread have the most up to date version when it issued the | 216 // Did the model thread have the most up to date version when it issued the |
| 222 // commit request? | 217 // commit request? |
| 223 if (base_version_ >= highest_gu_response_version_) { | 218 if (base_version_ >= highest_gu_response_version_) { |
| 224 return false; // Yes. | 219 return false; // Yes. |
| 225 } else { | 220 } else { |
| 226 return true; // No. | 221 return true; // No. |
| 227 } | 222 } |
| 228 } | 223 } |
| 229 } | 224 } |
| 230 | 225 |
| 231 bool SyncThreadSyncEntity::IsServerKnown() const { | 226 bool EntityTracker::IsServerKnown() const { |
| 232 return base_version_ != kUncommittedVersion; | 227 return base_version_ != kUncommittedVersion; |
| 233 } | 228 } |
| 234 | 229 |
| 235 void SyncThreadSyncEntity::ClearPendingCommit() { | 230 void EntityTracker::ClearPendingCommit() { |
| 236 is_commit_pending_ = false; | 231 is_commit_pending_ = false; |
| 237 | 232 |
| 238 // Clearing the specifics might free up some memory. It can't hurt to try. | 233 // Clearing the specifics might free up some memory. It can't hurt to try. |
| 239 specifics_.Clear(); | 234 specifics_.Clear(); |
| 240 } | 235 } |
| 241 | 236 |
| 242 } // namespace syncer | 237 } // namespace syncer |
| OLD | NEW |