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

Side by Side Diff: components/sync/device_info/device_info_service.cc

Issue 2406163006: [Sync] Services can now always assume processor exists. (Closed)
Patch Set: Updates for Max. Created 4 years, 2 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "components/sync/device_info/device_info_service.h" 5 #include "components/sync/device_info/device_info_service.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 60
61 std::unique_ptr<MetadataChangeList> 61 std::unique_ptr<MetadataChangeList>
62 DeviceInfoService::CreateMetadataChangeList() { 62 DeviceInfoService::CreateMetadataChangeList() {
63 return base::MakeUnique<SimpleMetadataChangeList>(); 63 return base::MakeUnique<SimpleMetadataChangeList>();
64 } 64 }
65 65
66 SyncError DeviceInfoService::MergeSyncData( 66 SyncError DeviceInfoService::MergeSyncData(
67 std::unique_ptr<MetadataChangeList> metadata_change_list, 67 std::unique_ptr<MetadataChangeList> metadata_change_list,
68 EntityDataMap entity_data_map) { 68 EntityDataMap entity_data_map) {
69 DCHECK(has_provider_initialized_); 69 DCHECK(has_provider_initialized_);
70 DCHECK(has_metadata_loaded_); 70 DCHECK(change_processor()->IsTrackingMetadata());
71 DCHECK(change_processor());
72 71
73 // Local data should typically be near empty, with the only possible value 72 // Local data should typically be near empty, with the only possible value
74 // corresponding to this device. This is because on signout all device info 73 // corresponding to this device. This is because on signout all device info
75 // data is blown away. However, this simplification is being ignored here and 74 // data is blown away. However, this simplification is being ignored here and
76 // a full difference is going to be calculated to explore what other service 75 // a full difference is going to be calculated to explore what other service
77 // implementations may look like. 76 // implementations may look like.
78 std::set<std::string> local_guids_to_put; 77 std::set<std::string> local_guids_to_put;
79 for (const auto& kv : all_data_) { 78 for (const auto& kv : all_data_) {
80 local_guids_to_put.insert(kv.first); 79 local_guids_to_put.insert(kv.first);
81 } 80 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 114
116 CommitAndNotify(std::move(batch), std::move(metadata_change_list), 115 CommitAndNotify(std::move(batch), std::move(metadata_change_list),
117 has_changes); 116 has_changes);
118 return SyncError(); 117 return SyncError();
119 } 118 }
120 119
121 SyncError DeviceInfoService::ApplySyncChanges( 120 SyncError DeviceInfoService::ApplySyncChanges(
122 std::unique_ptr<MetadataChangeList> metadata_change_list, 121 std::unique_ptr<MetadataChangeList> metadata_change_list,
123 EntityChangeList entity_changes) { 122 EntityChangeList entity_changes) {
124 DCHECK(has_provider_initialized_); 123 DCHECK(has_provider_initialized_);
125 DCHECK(has_metadata_loaded_);
126 124
127 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); 125 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
128 bool has_changes = false; 126 bool has_changes = false;
129 for (EntityChange& change : entity_changes) { 127 for (EntityChange& change : entity_changes) {
130 const std::string guid = change.storage_key(); 128 const std::string guid = change.storage_key();
131 // Each device is the authoritative source for itself, ignore any remote 129 // Each device is the authoritative source for itself, ignore any remote
132 // changes that have our local cache guid. 130 // changes that have our local cache guid.
133 if (guid == local_device_info_provider_->GetLocalDeviceInfo()->guid()) { 131 if (guid == local_device_info_provider_->GetLocalDeviceInfo()->guid()) {
134 continue; 132 continue;
135 } 133 }
(...skipping 10 matching lines...) Expand all
146 } 144 }
147 } 145 }
148 146
149 CommitAndNotify(std::move(batch), std::move(metadata_change_list), 147 CommitAndNotify(std::move(batch), std::move(metadata_change_list),
150 has_changes); 148 has_changes);
151 return SyncError(); 149 return SyncError();
152 } 150 }
153 151
154 void DeviceInfoService::GetData(StorageKeyList storage_keys, 152 void DeviceInfoService::GetData(StorageKeyList storage_keys,
155 DataCallback callback) { 153 DataCallback callback) {
156 DCHECK(has_metadata_loaded_);
157
158 std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); 154 std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl());
159 for (const auto& key : storage_keys) { 155 for (const auto& key : storage_keys) {
160 const auto& iter = all_data_.find(key); 156 const auto& iter = all_data_.find(key);
161 if (iter != all_data_.end()) { 157 if (iter != all_data_.end()) {
162 DCHECK_EQ(key, iter->second->cache_guid()); 158 DCHECK_EQ(key, iter->second->cache_guid());
163 batch->Put(key, CopyToEntityData(*iter->second)); 159 batch->Put(key, CopyToEntityData(*iter->second));
164 } 160 }
165 } 161 }
166
167 callback.Run(SyncError(), std::move(batch)); 162 callback.Run(SyncError(), std::move(batch));
168 } 163 }
169 164
170 void DeviceInfoService::GetAllData(DataCallback callback) { 165 void DeviceInfoService::GetAllData(DataCallback callback) {
171 DCHECK(has_metadata_loaded_);
172
173 std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); 166 std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl());
174 for (const auto& kv : all_data_) { 167 for (const auto& kv : all_data_) {
175 batch->Put(kv.first, CopyToEntityData(*kv.second)); 168 batch->Put(kv.first, CopyToEntityData(*kv.second));
176 } 169 }
177
178 callback.Run(SyncError(), std::move(batch)); 170 callback.Run(SyncError(), std::move(batch));
179 } 171 }
180 172
181 std::string DeviceInfoService::GetClientTag(const EntityData& entity_data) { 173 std::string DeviceInfoService::GetClientTag(const EntityData& entity_data) {
182 DCHECK(entity_data.specifics.has_device_info()); 174 DCHECK(entity_data.specifics.has_device_info());
183 return DeviceInfoUtil::SpecificsToTag(entity_data.specifics.device_info()); 175 return DeviceInfoUtil::SpecificsToTag(entity_data.specifics.device_info());
184 } 176 }
185 177
186 std::string DeviceInfoService::GetStorageKey(const EntityData& entity_data) { 178 std::string DeviceInfoService::GetStorageKey(const EntityData& entity_data) {
187 DCHECK(entity_data.specifics.has_device_info()); 179 DCHECK(entity_data.specifics.has_device_info());
188 return entity_data.specifics.device_info().cache_guid(); 180 return entity_data.specifics.device_info().cache_guid();
189 } 181 }
190 182
191 void DeviceInfoService::OnChangeProcessorSet() {
192 // We've recieved a new processor that needs metadata. If we're still in the
193 // process of loading data and/or metadata, then |has_metadata_loaded_| is
194 // false and we'll wait for those async reads to happen. If we've already
195 // loaded metadata and then subsequently we get a new processor, we must not
196 // have created the processor ourselves because we had no metadata. So there
197 // must not be any metadata on disk.
198 if (has_metadata_loaded_) {
199 change_processor()->OnMetadataLoaded(SyncError(),
200 base::MakeUnique<MetadataBatch>());
201 ReconcileLocalAndStored();
202 }
203 }
204
205 bool DeviceInfoService::IsSyncing() const { 183 bool DeviceInfoService::IsSyncing() const {
206 return !all_data_.empty(); 184 return !all_data_.empty();
207 } 185 }
208 186
209 std::unique_ptr<DeviceInfo> DeviceInfoService::GetDeviceInfo( 187 std::unique_ptr<DeviceInfo> DeviceInfoService::GetDeviceInfo(
210 const std::string& client_id) const { 188 const std::string& client_id) const {
211 const ClientIdToSpecifics::const_iterator iter = all_data_.find(client_id); 189 const ClientIdToSpecifics::const_iterator iter = all_data_.find(client_id);
212 if (iter == all_data_.end()) { 190 if (iter == all_data_.end()) {
213 return std::unique_ptr<DeviceInfo>(); 191 return std::unique_ptr<DeviceInfo>();
214 } 192 }
215
216 return CopyToModel(*iter->second); 193 return CopyToModel(*iter->second);
217 } 194 }
218 195
219 std::vector<std::unique_ptr<DeviceInfo>> DeviceInfoService::GetAllDeviceInfo() 196 std::vector<std::unique_ptr<DeviceInfo>> DeviceInfoService::GetAllDeviceInfo()
220 const { 197 const {
221 std::vector<std::unique_ptr<DeviceInfo>> list; 198 std::vector<std::unique_ptr<DeviceInfo>> list;
222
223 for (ClientIdToSpecifics::const_iterator iter = all_data_.begin(); 199 for (ClientIdToSpecifics::const_iterator iter = all_data_.begin();
224 iter != all_data_.end(); ++iter) { 200 iter != all_data_.end(); ++iter) {
225 list.push_back(CopyToModel(*iter->second)); 201 list.push_back(CopyToModel(*iter->second));
226 } 202 }
227
228 return list; 203 return list;
229 } 204 }
230 205
231 void DeviceInfoService::AddObserver(Observer* observer) { 206 void DeviceInfoService::AddObserver(Observer* observer) {
232 observers_.AddObserver(observer); 207 observers_.AddObserver(observer);
233 } 208 }
234 209
235 void DeviceInfoService::RemoveObserver(Observer* observer) { 210 void DeviceInfoService::RemoveObserver(Observer* observer) {
236 observers_.RemoveObserver(observer); 211 observers_.RemoveObserver(observer);
237 } 212 }
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 if (has_data_loaded_ && has_provider_initialized_) { 322 if (has_data_loaded_ && has_provider_initialized_) {
348 store_->ReadAllMetadata(base::Bind(&DeviceInfoService::OnReadAllMetadata, 323 store_->ReadAllMetadata(base::Bind(&DeviceInfoService::OnReadAllMetadata,
349 base::AsWeakPtr(this))); 324 base::AsWeakPtr(this)));
350 } 325 }
351 } 326 }
352 327
353 void DeviceInfoService::OnReadAllMetadata( 328 void DeviceInfoService::OnReadAllMetadata(
354 Result result, 329 Result result,
355 std::unique_ptr<RecordList> metadata_records, 330 std::unique_ptr<RecordList> metadata_records,
356 const std::string& global_metadata) { 331 const std::string& global_metadata) {
357 DCHECK(!has_metadata_loaded_);
358
359 if (result != Result::SUCCESS) { 332 if (result != Result::SUCCESS) {
360 // Store has encountered some serious error. We should still be able to 333 // Store has encountered some serious error. We should still be able to
361 // continue as a read only service, since if we got this far we must have 334 // continue as a read only service, since if we got this far we must have
362 // loaded all data out succesfully. 335 // loaded all data out succesfully.
363 ReportStartupErrorToSync("Load of metadata completely failed."); 336 ReportStartupErrorToSync("Load of metadata completely failed.");
364 return; 337 return;
365 } 338 }
366 339
367 // If we have no metadata then we don't want to create a processor. The idea
368 // is that by not having a processor, the services will suffer less of a
369 // performance hit. This isn't terribly applicable for this model type, but
370 // we want this class to be as similar to other services as possible so follow
371 // the convention.
372 if (metadata_records->size() > 0 || !global_metadata.empty()) {
373 CreateChangeProcessor();
374 }
375
376 // Set this after OnChangeProcessorSet so that we can correctly avoid giving
377 // the processor empty metadata. We always want to set |has_metadata_loaded_|
378 // at this point so that we'll know to give a processor empty metadata if it
379 // is created later.
380 has_metadata_loaded_ = true;
381
382 if (!change_processor()) {
383 // This means we haven't been told to start syncing and we don't have any
384 // local metadata.
385 return;
386 }
387
388 std::unique_ptr<MetadataBatch> batch(new MetadataBatch()); 340 std::unique_ptr<MetadataBatch> batch(new MetadataBatch());
389 ModelTypeState state; 341 ModelTypeState state;
390 if (state.ParseFromString(global_metadata)) { 342 if (state.ParseFromString(global_metadata)) {
391 batch->SetModelTypeState(state); 343 batch->SetModelTypeState(state);
392 } else { 344 } else {
393 // TODO(skym): How bad is this scenario? We may be able to just give an 345 // TODO(skym): How bad is this scenario? We may be able to just give an
394 // empty batch to the processor and we'll treat corrupted data type state 346 // empty batch to the processor and we'll treat corrupted data type state
395 // as no data type state at all. The question is do we want to add any of 347 // as no data type state at all. The question is do we want to add any of
396 // the entity metadata to the batch or completely skip that step? We're 348 // the entity metadata to the batch or completely skip that step? We're
397 // going to have to perform a merge shortly. Does this decision/logic even 349 // going to have to perform a merge shortly. Does this decision/logic even
(...skipping 25 matching lines...) Expand all
423 } 375 }
424 376
425 void DeviceInfoService::ReconcileLocalAndStored() { 377 void DeviceInfoService::ReconcileLocalAndStored() {
426 // On initial syncing we will have a change processor here, but it will not be 378 // On initial syncing we will have a change processor here, but it will not be
427 // tracking changes. We need to persist a copy of our local device info to 379 // tracking changes. We need to persist a copy of our local device info to
428 // disk, but the Put call to the processor will be ignored. That should be 380 // disk, but the Put call to the processor will be ignored. That should be
429 // fine however, as the discrepancy will be picked up later in merge. We don't 381 // fine however, as the discrepancy will be picked up later in merge. We don't
430 // bother trying to track this case and act intelligently because simply not 382 // bother trying to track this case and act intelligently because simply not
431 // much of a benefit in doing so. 383 // much of a benefit in doing so.
432 DCHECK(has_provider_initialized_); 384 DCHECK(has_provider_initialized_);
433 DCHECK(has_metadata_loaded_); 385
434 DCHECK(change_processor());
435 const DeviceInfo* current_info = 386 const DeviceInfo* current_info =
436 local_device_info_provider_->GetLocalDeviceInfo(); 387 local_device_info_provider_->GetLocalDeviceInfo();
437 auto iter = all_data_.find(current_info->guid()); 388 auto iter = all_data_.find(current_info->guid());
438 389
439 // Convert to DeviceInfo for Equals function. 390 // Convert to DeviceInfo for Equals function.
440 if (iter != all_data_.end() && 391 if (iter != all_data_.end() &&
441 current_info->Equals(*CopyToModel(*iter->second))) { 392 current_info->Equals(*CopyToModel(*iter->second))) {
442 const TimeDelta pulse_delay(DeviceInfoUtil::CalculatePulseDelay( 393 const TimeDelta pulse_delay(DeviceInfoUtil::CalculatePulseDelay(
443 GetLastUpdateTime(*iter->second), Time::Now())); 394 GetLastUpdateTime(*iter->second), Time::Now()));
444 if (!pulse_delay.is_zero()) { 395 if (!pulse_delay.is_zero()) {
445 pulse_timer_.Start(FROM_HERE, pulse_delay, 396 pulse_timer_.Start(FROM_HERE, pulse_delay,
446 base::Bind(&DeviceInfoService::SendLocalData, 397 base::Bind(&DeviceInfoService::SendLocalData,
447 base::Unretained(this))); 398 base::Unretained(this)));
448 return; 399 return;
449 } 400 }
450 } 401 }
451 SendLocalData(); 402 SendLocalData();
452 } 403 }
453 404
454 void DeviceInfoService::SendLocalData() { 405 void DeviceInfoService::SendLocalData() {
455 DCHECK(has_provider_initialized_); 406 DCHECK(has_provider_initialized_);
456 // TODO(skym): Handle disconnecting and reconnecting, this will currently halt
457 // the pulse timer and never restart it.
458 if (!change_processor()) {
459 return;
460 }
461 407
462 std::unique_ptr<DeviceInfoSpecifics> specifics = 408 std::unique_ptr<DeviceInfoSpecifics> specifics =
463 CopyToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo()); 409 CopyToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo());
464 specifics->set_last_updated_timestamp(TimeToProtoTime(Time::Now())); 410 specifics->set_last_updated_timestamp(TimeToProtoTime(Time::Now()));
465 411
466 std::unique_ptr<MetadataChangeList> metadata_change_list = 412 std::unique_ptr<MetadataChangeList> metadata_change_list =
467 CreateMetadataChangeList(); 413 CreateMetadataChangeList();
468 change_processor()->Put(specifics->cache_guid(), CopyToEntityData(*specifics), 414 if (change_processor()->IsTrackingMetadata()) {
469 metadata_change_list.get()); 415 change_processor()->Put(specifics->cache_guid(),
416 CopyToEntityData(*specifics),
417 metadata_change_list.get());
418 }
470 419
471 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); 420 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
472 StoreSpecifics(std::move(specifics), batch.get()); 421 StoreSpecifics(std::move(specifics), batch.get());
473 422
474 CommitAndNotify(std::move(batch), std::move(metadata_change_list), true); 423 CommitAndNotify(std::move(batch), std::move(metadata_change_list), true);
475 pulse_timer_.Start( 424 pulse_timer_.Start(
476 FROM_HERE, DeviceInfoUtil::kPulseInterval, 425 FROM_HERE, DeviceInfoUtil::kPulseInterval,
477 base::Bind(&DeviceInfoService::SendLocalData, base::Unretained(this))); 426 base::Bind(&DeviceInfoService::SendLocalData, base::Unretained(this)));
478 } 427 }
479 428
(...skipping 13 matching lines...) Expand all
493 442
494 int DeviceInfoService::CountActiveDevices(const Time now) const { 443 int DeviceInfoService::CountActiveDevices(const Time now) const {
495 return std::count_if(all_data_.begin(), all_data_.end(), 444 return std::count_if(all_data_.begin(), all_data_.end(),
496 [now](ClientIdToSpecifics::const_reference pair) { 445 [now](ClientIdToSpecifics::const_reference pair) {
497 return DeviceInfoUtil::IsActive( 446 return DeviceInfoUtil::IsActive(
498 GetLastUpdateTime(*pair.second), now); 447 GetLastUpdateTime(*pair.second), now);
499 }); 448 });
500 } 449 }
501 450
502 void DeviceInfoService::ReportStartupErrorToSync(const std::string& msg) { 451 void DeviceInfoService::ReportStartupErrorToSync(const std::string& msg) {
503 DCHECK(!has_metadata_loaded_); 452 // TODO(skym): Shouldn't need to log this here, reporting should always log.
504 LOG(WARNING) << msg; 453 LOG(WARNING) << msg;
505
506 // Create a processor and give it the error in case sync tries to start.
507 if (!change_processor()) {
508 CreateChangeProcessor();
509 }
510 change_processor()->OnMetadataLoaded( 454 change_processor()->OnMetadataLoaded(
511 change_processor()->CreateAndUploadError(FROM_HERE, msg), nullptr); 455 change_processor()->CreateAndUploadError(FROM_HERE, msg), nullptr);
512 } 456 }
513 457
514 // static 458 // static
515 Time DeviceInfoService::GetLastUpdateTime( 459 Time DeviceInfoService::GetLastUpdateTime(
516 const DeviceInfoSpecifics& specifics) { 460 const DeviceInfoSpecifics& specifics) {
517 if (specifics.has_last_updated_timestamp()) { 461 if (specifics.has_last_updated_timestamp()) {
518 return ProtoTimeToTime(specifics.last_updated_timestamp()); 462 return ProtoTimeToTime(specifics.last_updated_timestamp());
519 } else { 463 } else {
520 return Time(); 464 return Time();
521 } 465 }
522 } 466 }
523 467
524 } // namespace syncer 468 } // namespace syncer
OLDNEW
« no previous file with comments | « components/sync/device_info/device_info_service.h ('k') | components/sync/device_info/device_info_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698