Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: sync/internal_api/processor_entity_tracker.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "sync/internal_api/public/processor_entity_tracker.h"
6
7 #include <stdint.h>
8
9 #include "base/base64.h"
10 #include "base/sha1.h"
11 #include "base/time/time.h"
12 #include "sync/internal_api/public/non_blocking_sync_common.h"
13 #include "sync/syncable/syncable_util.h"
14 #include "sync/util/time.h"
15
16 namespace syncer_v2 {
17
18 namespace {
19
20 void HashSpecifics(const sync_pb::EntitySpecifics& specifics,
21 std::string* hash) {
22 DCHECK_GT(specifics.ByteSize(), 0);
23 base::Base64Encode(base::SHA1HashString(specifics.SerializeAsString()), hash);
24 }
25
26 } // namespace
27
28 std::unique_ptr<ProcessorEntityTracker> ProcessorEntityTracker::CreateNew(
29 const std::string& client_tag,
30 const std::string& client_tag_hash,
31 const std::string& id,
32 base::Time creation_time) {
33 // Initialize metadata
34 sync_pb::EntityMetadata metadata;
35 metadata.set_client_tag_hash(client_tag_hash);
36 if (!id.empty())
37 metadata.set_server_id(id);
38 metadata.set_sequence_number(0);
39 metadata.set_acked_sequence_number(0);
40 metadata.set_server_version(kUncommittedVersion);
41 metadata.set_creation_time(syncer::TimeToProtoTime(creation_time));
42
43 return std::unique_ptr<ProcessorEntityTracker>(
44 new ProcessorEntityTracker(client_tag, &metadata));
45 }
46
47 std::unique_ptr<ProcessorEntityTracker>
48 ProcessorEntityTracker::CreateFromMetadata(const std::string& client_tag,
49 sync_pb::EntityMetadata* metadata) {
50 return std::unique_ptr<ProcessorEntityTracker>(
51 new ProcessorEntityTracker(client_tag, metadata));
52 }
53
54 ProcessorEntityTracker::ProcessorEntityTracker(
55 const std::string& client_tag,
56 sync_pb::EntityMetadata* metadata)
57 : client_tag_(client_tag),
58 commit_requested_sequence_number_(metadata->acked_sequence_number()) {
59 DCHECK(metadata->has_client_tag_hash());
60 DCHECK(metadata->has_creation_time());
61 metadata_.Swap(metadata);
62 }
63
64 ProcessorEntityTracker::~ProcessorEntityTracker() {}
65
66 void ProcessorEntityTracker::CacheCommitData(EntityData* data) {
67 DCHECK(data);
68 if (data->client_tag_hash.empty()) {
69 data->client_tag_hash = metadata_.client_tag_hash();
70 }
71 CacheCommitData(data->PassToPtr());
72 }
73
74 void ProcessorEntityTracker::CacheCommitData(const EntityDataPtr& data_ptr) {
75 DCHECK(RequiresCommitData());
76 commit_data_ = data_ptr;
77 DCHECK(HasCommitData());
78 }
79
80 bool ProcessorEntityTracker::HasCommitData() const {
81 return !commit_data_->client_tag_hash.empty();
82 }
83
84 bool ProcessorEntityTracker::MatchesData(const EntityData& data) const {
85 return metadata_.is_deleted() ? data.is_deleted() :
86 MatchesSpecificsHash(data.specifics);
87 }
88
89 bool ProcessorEntityTracker::MatchesBaseData(const EntityData& data) const {
90 DCHECK(IsUnsynced());
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();
97 }
98
99 bool ProcessorEntityTracker::IsUnsynced() const {
100 return metadata_.sequence_number() > metadata_.acked_sequence_number();
101 }
102
103 bool ProcessorEntityTracker::RequiresCommitRequest() const {
104 return metadata_.sequence_number() > commit_requested_sequence_number_;
105 }
106
107 bool ProcessorEntityTracker::RequiresCommitData() const {
108 return RequiresCommitRequest() && !HasCommitData() && !metadata_.is_deleted();
109 }
110
111 bool ProcessorEntityTracker::CanClearMetadata() const {
112 return metadata_.is_deleted() && !IsUnsynced();
113 }
114
115 bool ProcessorEntityTracker::UpdateIsReflection(int64_t update_version) const {
116 return metadata_.server_version() >= update_version;
117 }
118
119 void ProcessorEntityTracker::RecordIgnoredUpdate(
120 const UpdateResponseData& update) {
121 DCHECK(metadata_.server_id().empty() ||
122 metadata_.server_id() == update.entity->id);
123 metadata_.set_server_id(update.entity->id);
124 metadata_.set_server_version(update.response_version);
125 // Either these already matched, acked was just bumped to squash a pending
126 // commit and this should follow, or the pending commit needs to be requeued.
127 commit_requested_sequence_number_ = metadata_.acked_sequence_number();
128 }
129
130 void ProcessorEntityTracker::RecordAcceptedUpdate(
131 const UpdateResponseData& update) {
132 DCHECK(!IsUnsynced());
133 RecordIgnoredUpdate(update);
134 metadata_.set_is_deleted(update.entity->is_deleted());
135 metadata_.set_modification_time(
136 syncer::TimeToProtoTime(update.entity->modification_time));
137 UpdateSpecificsHash(update.entity->specifics);
138 }
139
140 void ProcessorEntityTracker::RecordForcedUpdate(
141 const UpdateResponseData& update) {
142 DCHECK(IsUnsynced());
143 // There was a conflict and the server just won it. Explicitly ack all
144 // pending commits so they are never enqueued again.
145 metadata_.set_acked_sequence_number(metadata_.sequence_number());
146 commit_data_.reset();
147 RecordAcceptedUpdate(update);
148 }
149
150 void ProcessorEntityTracker::MakeLocalChange(std::unique_ptr<EntityData> data) {
151 DCHECK(!metadata_.client_tag_hash().empty());
152 DCHECK_EQ(metadata_.client_tag_hash(), data->client_tag_hash);
153
154 if (data->modification_time.is_null()) {
155 data->modification_time = base::Time::Now();
156 }
157
158 IncrementSequenceNumber();
159 UpdateSpecificsHash(data->specifics);
160 metadata_.set_modification_time(
161 syncer::TimeToProtoTime(data->modification_time));
162 metadata_.set_is_deleted(false);
163
164 data->id = metadata_.server_id();
165 data->creation_time = syncer::ProtoTimeToTime(metadata_.creation_time());
166 commit_data_.reset();
167 CacheCommitData(data.get());
168 }
169
170 void ProcessorEntityTracker::Delete() {
171 IncrementSequenceNumber();
172 metadata_.set_modification_time(syncer::TimeToProtoTime(base::Time::Now()));
173 metadata_.set_is_deleted(true);
174 metadata_.clear_specifics_hash();
175 // Clear any cached pending commit data.
176 commit_data_.reset();
177 }
178
179 void ProcessorEntityTracker::InitializeCommitRequestData(
180 CommitRequestData* request) {
181 if (!metadata_.is_deleted()) {
182 DCHECK(HasCommitData());
183 DCHECK_EQ(commit_data_->client_tag_hash, metadata_.client_tag_hash());
184 request->entity = commit_data_;
185 } else {
186 // Make an EntityData with empty specifics to indicate deletion. This is
187 // done lazily here to simplify loading a pending deletion on startup.
188 EntityData data;
189 data.client_tag_hash = metadata_.client_tag_hash();
190 data.id = metadata_.server_id();
191 data.creation_time = syncer::ProtoTimeToTime(metadata_.creation_time());
192 data.modification_time =
193 syncer::ProtoTimeToTime(metadata_.modification_time());
194 request->entity = data.PassToPtr();
195 }
196
197 request->sequence_number = metadata_.sequence_number();
198 request->base_version = metadata_.server_version();
199 request->specifics_hash = metadata_.specifics_hash();
200 commit_requested_sequence_number_ = metadata_.sequence_number();
201 }
202
203 void ProcessorEntityTracker::ReceiveCommitResponse(
204 const CommitResponseData& data) {
205 DCHECK_EQ(metadata_.client_tag_hash(), data.client_tag_hash);
206 DCHECK_GT(data.sequence_number, metadata_.acked_sequence_number());
207 DCHECK_GT(data.response_version, metadata_.server_version());
208
209 // The server can assign us a new ID in a commit response.
210 metadata_.set_server_id(data.id);
211 metadata_.set_acked_sequence_number(data.sequence_number);
212 metadata_.set_server_version(data.response_version);
213 if (!IsUnsynced()) {
214 // Clear pending commit data if there hasn't been another commit request
215 // since the one that is currently getting acked.
216 commit_data_.reset();
217 metadata_.clear_base_specifics_hash();
218 } else {
219 metadata_.set_base_specifics_hash(data.specifics_hash);
220 }
221 }
222
223 void ProcessorEntityTracker::ClearTransientSyncState() {
224 // If we have any unacknowledged commit requests outstanding, they've been
225 // dropped and we should forget about them.
226 commit_requested_sequence_number_ = metadata_.acked_sequence_number();
227 }
228
229 void ProcessorEntityTracker::IncrementSequenceNumber() {
230 DCHECK(metadata_.has_sequence_number());
231 if (!IsUnsynced()) {
232 // Update the base specifics hash if this entity wasn't already out of sync.
233 metadata_.set_base_specifics_hash(metadata_.specifics_hash());
234 }
235 metadata_.set_sequence_number(metadata_.sequence_number() + 1);
236 }
237
238 bool ProcessorEntityTracker::MatchesSpecificsHash(
239 const sync_pb::EntitySpecifics& specifics) const {
240 DCHECK(!metadata_.is_deleted());
241 std::string hash;
242 HashSpecifics(specifics, &hash);
243 return hash == metadata_.specifics_hash();
244 }
245
246 void ProcessorEntityTracker::UpdateSpecificsHash(
247 const sync_pb::EntitySpecifics& specifics) {
248 if (specifics.ByteSize() > 0) {
249 HashSpecifics(specifics, metadata_.mutable_specifics_hash());
250 } else {
251 metadata_.clear_specifics_hash();
252 }
253 }
254
255 } // namespace syncer_v2
OLDNEW
« no previous file with comments | « sync/internal_api/model_type_store_impl_unittest.cc ('k') | sync/internal_api/processor_entity_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698