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