| 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 |