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/internal_api/public/processor_entity_tracker.h" | 5 #include "sync/internal_api/public/processor_entity_tracker.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/sha1.h" | 10 #include "base/sha1.h" |
11 #include "base/time/time.h" | 11 #include "base/time/time.h" |
12 #include "sync/internal_api/public/non_blocking_sync_common.h" | 12 #include "sync/internal_api/public/non_blocking_sync_common.h" |
13 #include "sync/syncable/syncable_util.h" | 13 #include "sync/syncable/syncable_util.h" |
14 #include "sync/util/time.h" | 14 #include "sync/util/time.h" |
15 | 15 |
16 namespace syncer_v2 { | 16 namespace syncer_v2 { |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 void HashSpecifics(const sync_pb::EntitySpecifics& specifics, | 20 void HashSpecifics(const sync_pb::EntitySpecifics& specifics, |
21 std::string* hash) { | 21 std::string* hash) { |
| 22 DCHECK_GT(specifics.ByteSize(), 0); |
22 base::Base64Encode(base::SHA1HashString(specifics.SerializeAsString()), hash); | 23 base::Base64Encode(base::SHA1HashString(specifics.SerializeAsString()), hash); |
23 } | 24 } |
24 | 25 |
25 } // namespace | 26 } // namespace |
26 | 27 |
27 std::unique_ptr<ProcessorEntityTracker> ProcessorEntityTracker::CreateNew( | 28 std::unique_ptr<ProcessorEntityTracker> ProcessorEntityTracker::CreateNew( |
28 const std::string& client_tag, | 29 const std::string& client_tag, |
29 const std::string& client_tag_hash, | 30 const std::string& client_tag_hash, |
30 const std::string& id, | 31 const std::string& id, |
31 base::Time creation_time) { | 32 base::Time creation_time) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 void ProcessorEntityTracker::CacheCommitData(const EntityDataPtr& data_ptr) { | 74 void ProcessorEntityTracker::CacheCommitData(const EntityDataPtr& data_ptr) { |
74 DCHECK(RequiresCommitData()); | 75 DCHECK(RequiresCommitData()); |
75 commit_data_ = data_ptr; | 76 commit_data_ = data_ptr; |
76 DCHECK(HasCommitData()); | 77 DCHECK(HasCommitData()); |
77 } | 78 } |
78 | 79 |
79 bool ProcessorEntityTracker::HasCommitData() const { | 80 bool ProcessorEntityTracker::HasCommitData() const { |
80 return !commit_data_->client_tag_hash.empty(); | 81 return !commit_data_->client_tag_hash.empty(); |
81 } | 82 } |
82 | 83 |
83 bool ProcessorEntityTracker::MatchesSpecificsHash( | 84 bool ProcessorEntityTracker::MatchesData(const EntityData& data) const { |
84 const sync_pb::EntitySpecifics& specifics) const { | 85 return metadata_.is_deleted() ? data.is_deleted() : |
85 DCHECK_GT(specifics.ByteSize(), 0); | 86 MatchesSpecificsHash(data.specifics); |
86 std::string hash; | |
87 HashSpecifics(specifics, &hash); | |
88 return hash == metadata_.specifics_hash(); | |
89 } | 87 } |
90 | 88 |
91 bool ProcessorEntityTracker::MatchesData(const EntityData& data) const { | 89 bool ProcessorEntityTracker::MatchesBaseData(const EntityData& data) const { |
92 return (data.is_deleted() && metadata_.is_deleted()) || | 90 DCHECK(IsUnsynced()); |
93 MatchesSpecificsHash(data.specifics); | 91 if (data.is_deleted() || metadata_.base_specifics_hash().empty()) { |
| 92 return false; |
| 93 } |
| 94 std::string hash; |
| 95 HashSpecifics(data.specifics, &hash); |
| 96 return hash == metadata_.base_specifics_hash(); |
94 } | 97 } |
95 | 98 |
96 bool ProcessorEntityTracker::IsUnsynced() const { | 99 bool ProcessorEntityTracker::IsUnsynced() const { |
97 return metadata_.sequence_number() > metadata_.acked_sequence_number(); | 100 return metadata_.sequence_number() > metadata_.acked_sequence_number(); |
98 } | 101 } |
99 | 102 |
100 bool ProcessorEntityTracker::RequiresCommitRequest() const { | 103 bool ProcessorEntityTracker::RequiresCommitRequest() const { |
101 return metadata_.sequence_number() > commit_requested_sequence_number_; | 104 return metadata_.sequence_number() > commit_requested_sequence_number_; |
102 } | 105 } |
103 | 106 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 } | 145 } |
143 | 146 |
144 void ProcessorEntityTracker::MakeLocalChange(std::unique_ptr<EntityData> data) { | 147 void ProcessorEntityTracker::MakeLocalChange(std::unique_ptr<EntityData> data) { |
145 DCHECK(!metadata_.client_tag_hash().empty()); | 148 DCHECK(!metadata_.client_tag_hash().empty()); |
146 DCHECK_EQ(metadata_.client_tag_hash(), data->client_tag_hash); | 149 DCHECK_EQ(metadata_.client_tag_hash(), data->client_tag_hash); |
147 | 150 |
148 if (data->modification_time.is_null()) { | 151 if (data->modification_time.is_null()) { |
149 data->modification_time = base::Time::Now(); | 152 data->modification_time = base::Time::Now(); |
150 } | 153 } |
151 | 154 |
| 155 IncrementSequenceNumber(); |
| 156 UpdateSpecificsHash(data->specifics); |
152 metadata_.set_modification_time( | 157 metadata_.set_modification_time( |
153 syncer::TimeToProtoTime(data->modification_time)); | 158 syncer::TimeToProtoTime(data->modification_time)); |
154 metadata_.set_is_deleted(false); | 159 metadata_.set_is_deleted(false); |
155 IncrementSequenceNumber(); | |
156 UpdateSpecificsHash(data->specifics); | |
157 | 160 |
158 data->id = metadata_.server_id(); | 161 data->id = metadata_.server_id(); |
159 data->creation_time = syncer::ProtoTimeToTime(metadata_.creation_time()); | 162 data->creation_time = syncer::ProtoTimeToTime(metadata_.creation_time()); |
160 commit_data_.reset(); | 163 commit_data_.reset(); |
161 CacheCommitData(data.get()); | 164 CacheCommitData(data.get()); |
162 } | 165 } |
163 | 166 |
164 void ProcessorEntityTracker::Delete() { | 167 void ProcessorEntityTracker::Delete() { |
165 IncrementSequenceNumber(); | 168 IncrementSequenceNumber(); |
166 metadata_.set_is_deleted(true); | 169 metadata_.set_is_deleted(true); |
(...skipping 13 matching lines...) Expand all Loading... |
180 // done lazily here to simplify loading a pending deletion on startup. | 183 // done lazily here to simplify loading a pending deletion on startup. |
181 EntityData data; | 184 EntityData data; |
182 data.client_tag_hash = metadata_.client_tag_hash(); | 185 data.client_tag_hash = metadata_.client_tag_hash(); |
183 data.id = metadata_.server_id(); | 186 data.id = metadata_.server_id(); |
184 data.creation_time = syncer::ProtoTimeToTime(metadata_.creation_time()); | 187 data.creation_time = syncer::ProtoTimeToTime(metadata_.creation_time()); |
185 request->entity = data.PassToPtr(); | 188 request->entity = data.PassToPtr(); |
186 } | 189 } |
187 | 190 |
188 request->sequence_number = metadata_.sequence_number(); | 191 request->sequence_number = metadata_.sequence_number(); |
189 request->base_version = metadata_.server_version(); | 192 request->base_version = metadata_.server_version(); |
| 193 request->specifics_hash = metadata_.specifics_hash(); |
190 commit_requested_sequence_number_ = metadata_.sequence_number(); | 194 commit_requested_sequence_number_ = metadata_.sequence_number(); |
191 } | 195 } |
192 | 196 |
193 void ProcessorEntityTracker::ReceiveCommitResponse( | 197 void ProcessorEntityTracker::ReceiveCommitResponse( |
194 const std::string& id, | 198 const CommitResponseData& data) { |
195 int64_t sequence_number, | 199 DCHECK_EQ(metadata_.client_tag_hash(), data.client_tag_hash); |
196 int64_t response_version) { | 200 DCHECK_GT(data.sequence_number, metadata_.acked_sequence_number()); |
197 DCHECK(sequence_number > metadata_.acked_sequence_number()); | 201 DCHECK_GT(data.response_version, metadata_.server_version()); |
198 | 202 |
199 // The server can assign us a new ID in a commit response. | 203 // The server can assign us a new ID in a commit response. |
200 metadata_.set_server_id(id); | 204 metadata_.set_server_id(data.id); |
201 metadata_.set_acked_sequence_number(sequence_number); | 205 metadata_.set_acked_sequence_number(data.sequence_number); |
202 metadata_.set_server_version(response_version); | 206 metadata_.set_server_version(data.response_version); |
203 if (!IsUnsynced()) { | 207 if (!IsUnsynced()) { |
204 // Clear pending commit data if there hasn't been another commit request | 208 // Clear pending commit data if there hasn't been another commit request |
205 // since the one that is currently getting acked. | 209 // since the one that is currently getting acked. |
206 commit_data_.reset(); | 210 commit_data_.reset(); |
| 211 metadata_.clear_base_specifics_hash(); |
| 212 } else { |
| 213 metadata_.set_base_specifics_hash(data.specifics_hash); |
207 } | 214 } |
208 } | 215 } |
209 | 216 |
210 void ProcessorEntityTracker::ClearTransientSyncState() { | 217 void ProcessorEntityTracker::ClearTransientSyncState() { |
211 // If we have any unacknowledged commit requests outstanding, they've been | 218 // If we have any unacknowledged commit requests outstanding, they've been |
212 // dropped and we should forget about them. | 219 // dropped and we should forget about them. |
213 commit_requested_sequence_number_ = metadata_.acked_sequence_number(); | 220 commit_requested_sequence_number_ = metadata_.acked_sequence_number(); |
214 } | 221 } |
215 | 222 |
216 void ProcessorEntityTracker::IncrementSequenceNumber() { | 223 void ProcessorEntityTracker::IncrementSequenceNumber() { |
217 DCHECK(metadata_.has_sequence_number()); | 224 DCHECK(metadata_.has_sequence_number()); |
| 225 if (!IsUnsynced()) { |
| 226 // Update the base specifics hash if this entity wasn't already out of sync. |
| 227 metadata_.set_base_specifics_hash(metadata_.specifics_hash()); |
| 228 } |
218 metadata_.set_sequence_number(metadata_.sequence_number() + 1); | 229 metadata_.set_sequence_number(metadata_.sequence_number() + 1); |
219 } | 230 } |
220 | 231 |
221 // Update hash string for EntitySpecifics. | 232 bool ProcessorEntityTracker::MatchesSpecificsHash( |
| 233 const sync_pb::EntitySpecifics& specifics) const { |
| 234 DCHECK(!metadata_.is_deleted()); |
| 235 std::string hash; |
| 236 HashSpecifics(specifics, &hash); |
| 237 return hash == metadata_.specifics_hash(); |
| 238 } |
| 239 |
222 void ProcessorEntityTracker::UpdateSpecificsHash( | 240 void ProcessorEntityTracker::UpdateSpecificsHash( |
223 const sync_pb::EntitySpecifics& specifics) { | 241 const sync_pb::EntitySpecifics& specifics) { |
224 if (specifics.ByteSize() > 0) { | 242 if (specifics.ByteSize() > 0) { |
225 HashSpecifics(specifics, metadata_.mutable_specifics_hash()); | 243 HashSpecifics(specifics, metadata_.mutable_specifics_hash()); |
226 } else { | 244 } else { |
227 metadata_.clear_specifics_hash(); | 245 metadata_.clear_specifics_hash(); |
228 } | 246 } |
229 } | 247 } |
230 | 248 |
231 } // namespace syncer_v2 | 249 } // namespace syncer_v2 |
OLD | NEW |