Update V8 to version 4.7.58.
[chromium-blink-merge.git] / sync / engine / entity_tracker.cc
blobf8bfa8bd66bd1c8d32f05e2aa3dd46c658688639
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.
5 #include "sync/engine/entity_tracker.h"
7 #include "base/logging.h"
8 #include "sync/internal_api/public/base/model_type.h"
9 #include "sync/internal_api/public/non_blocking_sync_common.h"
10 #include "sync/syncable/syncable_util.h"
11 #include "sync/util/time.h"
13 namespace syncer_v2 {
15 scoped_ptr<EntityTracker> EntityTracker::FromUpdateResponse(
16 const UpdateResponseData& data) {
17 return make_scoped_ptr(new EntityTracker(data.id, data.client_tag_hash, 0,
18 data.response_version));
21 scoped_ptr<EntityTracker> EntityTracker::FromCommitRequest(
22 const CommitRequestData& data) {
23 return make_scoped_ptr(
24 new EntityTracker(data.id, data.client_tag_hash, 0, 0));
27 EntityTracker::EntityTracker(const std::string& id,
28 const std::string& client_tag_hash,
29 int64 highest_commit_response_version,
30 int64 highest_gu_response_version)
31 : id_(id),
32 client_tag_hash_(client_tag_hash),
33 highest_commit_response_version_(highest_commit_response_version),
34 highest_gu_response_version_(highest_gu_response_version),
35 sequence_number_(0),
36 base_version_(kUncommittedVersion) {}
38 EntityTracker::~EntityTracker() {}
40 bool EntityTracker::HasPendingCommit() const {
41 return !!pending_commit_;
44 void EntityTracker::PrepareCommitProto(sync_pb::SyncEntity* commit_entity,
45 int64* sequence_number) const {
46 DCHECK(HasPendingCommit());
48 // Set ID if we have a server-assigned ID. Otherwise, it will be up to
49 // our caller to assign a client-unique initial ID.
50 if (base_version_ != kUncommittedVersion) {
51 commit_entity->set_id_string(id_);
54 commit_entity->set_client_defined_unique_tag(client_tag_hash_);
55 commit_entity->set_version(base_version_);
56 commit_entity->set_deleted(pending_commit_->deleted);
57 commit_entity->set_folder(false);
58 commit_entity->set_name(pending_commit_->non_unique_name);
59 if (!pending_commit_->deleted) {
60 commit_entity->set_ctime(syncer::TimeToProtoTime(pending_commit_->ctime));
61 commit_entity->set_mtime(syncer::TimeToProtoTime(pending_commit_->mtime));
62 commit_entity->mutable_specifics()->CopyFrom(pending_commit_->specifics);
65 *sequence_number = sequence_number_;
68 void EntityTracker::RequestCommit(const CommitRequestData& data) {
69 DCHECK_GE(data.base_version, base_version_)
70 << "Base version should never decrease";
72 DCHECK_GE(data.sequence_number, sequence_number_)
73 << "Sequence number should never decrease";
75 // Update our book-keeping counters.
76 base_version_ = data.base_version;
77 sequence_number_ = data.sequence_number;
79 // Don't commit deletions of server-unknown items.
80 if (data.deleted && !IsServerKnown()) {
81 ClearPendingCommit();
82 return;
85 // We intentionally don't update the id_ here. Good ID values come from the
86 // server and always pass through the sync thread first. There's no way the
87 // model thread could have a better ID value than we do.
89 // This entity is identified by its client tag. That value can never change.
90 DCHECK_EQ(client_tag_hash_, data.client_tag_hash);
91 pending_commit_.reset(new CommitRequestData(data));
93 // Do our counter values indicate a conflict? If so, don't commit.
95 // There's no need to inform the model thread of the conflict. The
96 // conflicting update has already been posted to its task runner; it will
97 // figure it out as soon as it runs that task.
99 // Note that this check must be after pending_commit_ is set.
100 if (IsInConflict()) {
101 ClearPendingCommit();
102 return;
105 // Otherwise, keep the data associated with this pending commit
106 // so it can be committed at the next possible opportunity.
109 void EntityTracker::ReceiveCommitResponse(const std::string& response_id,
110 int64 response_version,
111 int64 sequence_number) {
112 // Commit responses, especially after the first commit, can update our ID.
113 id_ = response_id;
115 DCHECK_GT(response_version, highest_commit_response_version_)
116 << "Had expected higher response version."
117 << " id: " << id_;
119 // Commits are synchronous, so there's no reason why the sequence numbers
120 // wouldn't match.
121 DCHECK_EQ(sequence_number_, sequence_number)
122 << "Unexpected sequence number mismatch."
123 << " id: " << id_;
125 highest_commit_response_version_ = response_version;
127 // Because an in-progress commit blocks the sync thread, we can assume that
128 // the item we just committed successfully is exactly the one we have now.
129 // Nothing changed it while the commit was happening. Since we're now in
130 // sync with the server, we can clear the pending commit.
131 ClearPendingCommit();
134 void EntityTracker::ReceiveUpdate(int64 version) {
135 if (version <= highest_gu_response_version_)
136 return;
138 highest_gu_response_version_ = version;
140 // Got an applicable update newer than any pending updates. It must be safe
141 // to discard the old pending update, if there was one.
142 ClearPendingUpdate();
144 if (IsInConflict()) {
145 // Incoming update clobbers the pending commit on the sync thread.
146 // The model thread can re-request this commit later if it wants to.
147 ClearPendingCommit();
151 bool EntityTracker::ReceivePendingUpdate(const UpdateResponseData& data) {
152 if (data.response_version < highest_gu_response_version_)
153 return false;
155 highest_gu_response_version_ = data.response_version;
156 pending_update_.reset(new UpdateResponseData(data));
157 ClearPendingCommit();
158 return true;
161 bool EntityTracker::HasPendingUpdate() const {
162 return !!pending_update_;
165 UpdateResponseData EntityTracker::GetPendingUpdate() const {
166 return *pending_update_;
169 void EntityTracker::ClearPendingUpdate() {
170 pending_update_.reset();
173 bool EntityTracker::IsInConflict() const {
174 if (!HasPendingCommit())
175 return false;
177 if (HasPendingUpdate())
178 return true;
180 if (highest_gu_response_version_ <= highest_commit_response_version_) {
181 // The most recent server state was created in a commit made by this
182 // client. We're fully up to date, and therefore not in conflict.
183 return false;
184 } else {
185 // The most recent server state was written by someone else.
186 // Did the model thread have the most up to date version when it issued the
187 // commit request?
188 if (base_version_ >= highest_gu_response_version_) {
189 return false; // Yes.
190 } else {
191 return true; // No.
196 bool EntityTracker::IsServerKnown() const {
197 return base_version_ != kUncommittedVersion;
200 void EntityTracker::ClearPendingCommit() {
201 pending_commit_.reset();
204 } // namespace syncer