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

Side by Side Diff: sync/engine/worker_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
« no previous file with comments | « sync/engine/worker_entity_tracker.h ('k') | sync/engine/worker_entity_tracker_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/engine/worker_entity_tracker.h"
6
7 #include <stdint.h>
8
9 #include "base/logging.h"
10 #include "sync/internal_api/public/base/model_type.h"
11 #include "sync/internal_api/public/non_blocking_sync_common.h"
12 #include "sync/syncable/syncable_util.h"
13 #include "sync/util/time.h"
14
15 namespace syncer_v2 {
16
17 WorkerEntityTracker::WorkerEntityTracker(const std::string& id,
18 const std::string& client_tag_hash)
19 : id_(id),
20 client_tag_hash_(client_tag_hash),
21 highest_commit_response_version_(0),
22 highest_gu_response_version_(0),
23 sequence_number_(0),
24 base_version_(kUncommittedVersion) {
25 DCHECK(!client_tag_hash_.empty());
26 }
27
28 WorkerEntityTracker::~WorkerEntityTracker() {}
29
30 bool WorkerEntityTracker::HasPendingCommit() const {
31 return !!pending_commit_;
32 }
33
34 void WorkerEntityTracker::PopulateCommitProto(
35 sync_pb::SyncEntity* commit_entity) const {
36 DCHECK(HasPendingCommit());
37 DCHECK(!client_tag_hash_.empty());
38
39 if (!id_.empty()) {
40 commit_entity->set_id_string(id_);
41 }
42
43 const EntityData& entity = pending_commit_->entity.value();
44 DCHECK_EQ(client_tag_hash_, entity.client_tag_hash);
45
46 commit_entity->set_client_defined_unique_tag(client_tag_hash_);
47 commit_entity->set_version(base_version_);
48 commit_entity->set_deleted(entity.is_deleted());
49
50 // TODO(stanisc): This doesn't support bookmarks yet.
51 DCHECK(entity.parent_id.empty());
52 commit_entity->set_folder(false);
53
54 commit_entity->set_name(entity.non_unique_name);
55 if (!entity.is_deleted()) {
56 commit_entity->set_ctime(syncer::TimeToProtoTime(entity.creation_time));
57 commit_entity->set_mtime(syncer::TimeToProtoTime(entity.modification_time));
58 commit_entity->mutable_specifics()->CopyFrom(entity.specifics);
59 }
60 }
61
62 void WorkerEntityTracker::RequestCommit(const CommitRequestData& data) {
63 DCHECK_GE(data.base_version, base_version_)
64 << "Base version should never decrease";
65
66 DCHECK_GE(data.sequence_number, sequence_number_)
67 << "Sequence number should never decrease";
68
69 // Update our book-keeping counters.
70 base_version_ = data.base_version;
71 sequence_number_ = data.sequence_number;
72 pending_commit_specifics_hash_ = data.specifics_hash;
73
74 // Don't commit deletions of server-unknown items.
75 if (data.entity->is_deleted() && !IsServerKnown()) {
76 ClearPendingCommit();
77 return;
78 }
79
80 // We intentionally don't update the id_ here. Good ID values come from the
81 // server and always pass through the sync thread first. There's no way the
82 // model thread could have a better ID value than we do.
83
84 // This entity is identified by its client tag. That value can never change.
85 DCHECK_EQ(client_tag_hash_, data.entity->client_tag_hash);
86 // TODO(stanisc): consider simply copying CommitRequestData instead of
87 // allocating one dynamically.
88 pending_commit_.reset(new CommitRequestData(data));
89
90 // Do our counter values indicate a conflict? If so, don't commit.
91 //
92 // There's no need to inform the model thread of the conflict. The
93 // conflicting update has already been posted to its task runner; it will
94 // figure it out as soon as it runs that task.
95 //
96 // Note that this check must be after pending_commit_ is set.
97 if (IsInConflict()) {
98 ClearPendingCommit();
99 return;
100 }
101
102 // Otherwise, keep the data associated with this pending commit
103 // so it can be committed at the next possible opportunity.
104 }
105
106 void WorkerEntityTracker::ReceiveCommitResponse(CommitResponseData* ack) {
107 DCHECK_GT(ack->response_version, highest_commit_response_version_)
108 << "Had expected higher response version."
109 << " id: " << id_;
110
111 // Commit responses, especially after the first commit, can update our ID.
112 id_ = ack->id;
113 highest_commit_response_version_ = ack->response_version;
114
115 // Fill in some cached info for the response data. Since commits happen
116 // synchronously on the sync thread, our item's state is guaranteed to be
117 // the same at the end of the commit as it was at the start.
118 ack->sequence_number = sequence_number_;
119 ack->specifics_hash = pending_commit_specifics_hash_;
120
121 // Because an in-progress commit blocks the sync thread, we can assume that
122 // the item we just committed successfully is exactly the one we have now.
123 // Nothing changed it while the commit was happening. Since we're now in
124 // sync with the server, we can clear the pending commit.
125 ClearPendingCommit();
126 }
127
128 void WorkerEntityTracker::ReceiveUpdate(int64_t version) {
129 if (version <= highest_gu_response_version_)
130 return;
131
132 highest_gu_response_version_ = version;
133
134 // Got an applicable update newer than any pending updates. It must be safe
135 // to discard the old encrypted update, if there was one.
136 ClearEncryptedUpdate();
137
138 if (IsInConflict()) {
139 // Incoming update clobbers the pending commit on the sync thread.
140 // The model thread can re-request this commit later if it wants to.
141 ClearPendingCommit();
142 }
143 }
144
145 bool WorkerEntityTracker::ReceiveEncryptedUpdate(
146 const UpdateResponseData& data) {
147 if (data.response_version < highest_gu_response_version_)
148 return false;
149
150 highest_gu_response_version_ = data.response_version;
151 encrypted_update_.reset(new UpdateResponseData(data));
152 ClearPendingCommit();
153 return true;
154 }
155
156 bool WorkerEntityTracker::HasEncryptedUpdate() const {
157 return !!encrypted_update_;
158 }
159
160 UpdateResponseData WorkerEntityTracker::GetEncryptedUpdate() const {
161 return *encrypted_update_;
162 }
163
164 void WorkerEntityTracker::ClearEncryptedUpdate() {
165 encrypted_update_.reset();
166 }
167
168 bool WorkerEntityTracker::IsInConflict() const {
169 if (!HasPendingCommit())
170 return false;
171
172 if (HasEncryptedUpdate())
173 return true;
174
175 if (highest_gu_response_version_ <= highest_commit_response_version_) {
176 // The most recent server state was created in a commit made by this
177 // client. We're fully up to date, and therefore not in conflict.
178 return false;
179 } else {
180 // The most recent server state was written by someone else.
181 // Did the model thread have the most up to date version when it issued the
182 // commit request?
183 if (base_version_ >= highest_gu_response_version_) {
184 return false; // Yes.
185 } else {
186 return true; // No.
187 }
188 }
189 }
190
191 bool WorkerEntityTracker::IsServerKnown() const {
192 return base_version_ != kUncommittedVersion;
193 }
194
195 void WorkerEntityTracker::ClearPendingCommit() {
196 pending_commit_.reset();
197 pending_commit_specifics_hash_.clear();
198 }
199
200 } // namespace syncer_v2
OLDNEW
« no previous file with comments | « sync/engine/worker_entity_tracker.h ('k') | sync/engine/worker_entity_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698