OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |