| 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_driver/device_info_service.h" | 5 #include "components/sync_driver/device_info_service.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 DeviceInfoService::~DeviceInfoService() {} | 73 DeviceInfoService::~DeviceInfoService() {} |
| 74 | 74 |
| 75 std::unique_ptr<MetadataChangeList> | 75 std::unique_ptr<MetadataChangeList> |
| 76 DeviceInfoService::CreateMetadataChangeList() { | 76 DeviceInfoService::CreateMetadataChangeList() { |
| 77 return base::WrapUnique(new SimpleMetadataChangeList()); | 77 return base::WrapUnique(new SimpleMetadataChangeList()); |
| 78 } | 78 } |
| 79 | 79 |
| 80 SyncError DeviceInfoService::MergeSyncData( | 80 SyncError DeviceInfoService::MergeSyncData( |
| 81 std::unique_ptr<MetadataChangeList> metadata_change_list, | 81 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 82 EntityDataMap entity_data_map) { | 82 EntityDataMap entity_data_map) { |
| 83 if (!has_provider_initialized_ || !has_metadata_loaded_ || | 83 DCHECK(has_provider_initialized_); |
| 84 !change_processor()) { | 84 DCHECK(has_metadata_loaded_); |
| 85 return SyncError( | 85 DCHECK(change_processor()); |
| 86 FROM_HERE, SyncError::DATATYPE_ERROR, | |
| 87 "Cannot call MergeSyncData without provider, data, and processor.", | |
| 88 syncer::DEVICE_INFO); | |
| 89 } | |
| 90 | 86 |
| 91 // Local data should typically be near empty, with the only possible value | 87 // Local data should typically be near empty, with the only possible value |
| 92 // corresponding to this device. This is because on signout all device info | 88 // corresponding to this device. This is because on signout all device info |
| 93 // data is blown away. However, this simplification is being ignored here and | 89 // data is blown away. However, this simplification is being ignored here and |
| 94 // a full difference is going to be calculated to explore what other service | 90 // a full difference is going to be calculated to explore what other service |
| 95 // implementations may look like. | 91 // implementations may look like. |
| 96 std::set<std::string> local_guids_to_put; | 92 std::set<std::string> local_guids_to_put; |
| 97 for (const auto& kv : all_data_) { | 93 for (const auto& kv : all_data_) { |
| 98 local_guids_to_put.insert(kv.first); | 94 local_guids_to_put.insert(kv.first); |
| 99 } | 95 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 127 } | 123 } |
| 128 | 124 |
| 129 for (const std::string& guid : local_guids_to_put) { | 125 for (const std::string& guid : local_guids_to_put) { |
| 130 change_processor()->Put(DeviceInfoUtil::SpecificsToTag(*all_data_[guid]), | 126 change_processor()->Put(DeviceInfoUtil::SpecificsToTag(*all_data_[guid]), |
| 131 CopyToEntityData(*all_data_[guid]), | 127 CopyToEntityData(*all_data_[guid]), |
| 132 metadata_change_list.get()); | 128 metadata_change_list.get()); |
| 133 } | 129 } |
| 134 | 130 |
| 135 CommitAndNotify(std::move(batch), std::move(metadata_change_list), | 131 CommitAndNotify(std::move(batch), std::move(metadata_change_list), |
| 136 has_changes); | 132 has_changes); |
| 137 return syncer::SyncError(); | 133 return SyncError(); |
| 138 } | 134 } |
| 139 | 135 |
| 140 SyncError DeviceInfoService::ApplySyncChanges( | 136 SyncError DeviceInfoService::ApplySyncChanges( |
| 141 std::unique_ptr<MetadataChangeList> metadata_change_list, | 137 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 142 EntityChangeList entity_changes) { | 138 EntityChangeList entity_changes) { |
| 143 if (!has_provider_initialized_ || !has_metadata_loaded_) { | 139 DCHECK(has_provider_initialized_); |
| 144 return SyncError( | 140 DCHECK(has_metadata_loaded_); |
| 145 FROM_HERE, SyncError::DATATYPE_ERROR, | |
| 146 "Cannot call ApplySyncChanges before provider and data have loaded.", | |
| 147 syncer::DEVICE_INFO); | |
| 148 } | |
| 149 | 141 |
| 150 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); | 142 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); |
| 151 bool has_changes = false; | 143 bool has_changes = false; |
| 152 for (EntityChange& change : entity_changes) { | 144 for (EntityChange& change : entity_changes) { |
| 153 const std::string guid = | 145 const std::string guid = |
| 154 DeviceInfoUtil::TagToCacheGuid(change.client_tag()); | 146 DeviceInfoUtil::TagToCacheGuid(change.client_tag()); |
| 155 // Each device is the authoritative source for itself, ignore any remote | 147 // Each device is the authoritative source for itself, ignore any remote |
| 156 // changes that have our local cache guid. | 148 // changes that have our local cache guid. |
| 157 if (guid == local_device_info_provider_->GetLocalDeviceInfo()->guid()) { | 149 if (guid == local_device_info_provider_->GetLocalDeviceInfo()->guid()) { |
| 158 continue; | 150 continue; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 170 } | 162 } |
| 171 } | 163 } |
| 172 | 164 |
| 173 CommitAndNotify(std::move(batch), std::move(metadata_change_list), | 165 CommitAndNotify(std::move(batch), std::move(metadata_change_list), |
| 174 has_changes); | 166 has_changes); |
| 175 return SyncError(); | 167 return SyncError(); |
| 176 } | 168 } |
| 177 | 169 |
| 178 void DeviceInfoService::GetData(ClientTagList client_tags, | 170 void DeviceInfoService::GetData(ClientTagList client_tags, |
| 179 DataCallback callback) { | 171 DataCallback callback) { |
| 180 if (!has_metadata_loaded_) { | 172 DCHECK(has_metadata_loaded_); |
| 181 callback.Run( | |
| 182 SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, | |
| 183 "Should not call GetData before metadata has loaded.", | |
| 184 syncer::DEVICE_INFO), | |
| 185 std::unique_ptr<DataBatchImpl>()); | |
| 186 return; | |
| 187 } | |
| 188 | 173 |
| 189 std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); | 174 std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); |
| 190 for (const auto& tag : client_tags) { | 175 for (const auto& tag : client_tags) { |
| 191 const auto& iter = all_data_.find(DeviceInfoUtil::TagToCacheGuid(tag)); | 176 const auto& iter = all_data_.find(DeviceInfoUtil::TagToCacheGuid(tag)); |
| 192 if (iter != all_data_.end()) { | 177 if (iter != all_data_.end()) { |
| 193 DCHECK_EQ(tag, DeviceInfoUtil::SpecificsToTag(*iter->second)); | 178 DCHECK_EQ(tag, DeviceInfoUtil::SpecificsToTag(*iter->second)); |
| 194 batch->Put(tag, CopyToEntityData(*iter->second)); | 179 batch->Put(tag, CopyToEntityData(*iter->second)); |
| 195 } | 180 } |
| 196 } | 181 } |
| 197 callback.Run(syncer::SyncError(), std::move(batch)); | 182 |
| 183 callback.Run(SyncError(), std::move(batch)); |
| 198 } | 184 } |
| 199 | 185 |
| 200 void DeviceInfoService::GetAllData(DataCallback callback) { | 186 void DeviceInfoService::GetAllData(DataCallback callback) { |
| 201 if (!has_metadata_loaded_) { | 187 DCHECK(has_metadata_loaded_); |
| 202 callback.Run( | |
| 203 SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, | |
| 204 "Should not call GetAllData before metadata has loaded.", | |
| 205 syncer::DEVICE_INFO), | |
| 206 std::unique_ptr<DataBatchImpl>()); | |
| 207 return; | |
| 208 } | |
| 209 | 188 |
| 210 std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); | 189 std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); |
| 211 for (const auto& kv : all_data_) { | 190 for (const auto& kv : all_data_) { |
| 212 batch->Put(DeviceInfoUtil::SpecificsToTag(*kv.second), | 191 batch->Put(DeviceInfoUtil::SpecificsToTag(*kv.second), |
| 213 CopyToEntityData(*kv.second)); | 192 CopyToEntityData(*kv.second)); |
| 214 } | 193 } |
| 215 callback.Run(syncer::SyncError(), std::move(batch)); | 194 |
| 195 callback.Run(SyncError(), std::move(batch)); |
| 216 } | 196 } |
| 217 | 197 |
| 218 std::string DeviceInfoService::GetClientTag(const EntityData& entity_data) { | 198 std::string DeviceInfoService::GetClientTag(const EntityData& entity_data) { |
| 219 DCHECK(entity_data.specifics.has_device_info()); | 199 DCHECK(entity_data.specifics.has_device_info()); |
| 220 return DeviceInfoUtil::SpecificsToTag(entity_data.specifics.device_info()); | 200 return DeviceInfoUtil::SpecificsToTag(entity_data.specifics.device_info()); |
| 221 } | 201 } |
| 222 | 202 |
| 223 void DeviceInfoService::OnChangeProcessorSet() { | 203 void DeviceInfoService::OnChangeProcessorSet() { |
| 224 // We've recieved a new processor that needs metadata. If we're still in the | 204 // We've recieved a new processor that needs metadata. If we're still in the |
| 225 // process of loading data and/or metadata, then |has_metadata_loaded_| is | 205 // process of loading data and/or metadata, then |has_metadata_loaded_| is |
| 226 // false and we'll wait for those async reads to happen. If we've already | 206 // false and we'll wait for those async reads to happen. If we've already |
| 227 // loaded metadata and then subsequently we get a new processor, we must not | 207 // loaded metadata and then subsequently we get a new processor, we must not |
| 228 // have created the processor ourselves because we had no metadata. So there | 208 // have created the processor ourselves because we had no metadata. So there |
| 229 // must not be any metadata on disk. | 209 // must not be any metadata on disk. |
| 230 if (has_metadata_loaded_) { | 210 if (has_metadata_loaded_) { |
| 231 change_processor()->OnMetadataLoaded(syncer::SyncError(), | 211 change_processor()->OnMetadataLoaded(SyncError(), |
| 232 base::WrapUnique(new MetadataBatch())); | 212 base::WrapUnique(new MetadataBatch())); |
| 233 TryReconcileLocalAndStored(); | 213 ReconcileLocalAndStored(); |
| 234 } | 214 } |
| 235 } | 215 } |
| 236 | 216 |
| 237 bool DeviceInfoService::IsSyncing() const { | 217 bool DeviceInfoService::IsSyncing() const { |
| 238 return !all_data_.empty(); | 218 return !all_data_.empty(); |
| 239 } | 219 } |
| 240 | 220 |
| 241 std::unique_ptr<DeviceInfo> DeviceInfoService::GetDeviceInfo( | 221 std::unique_ptr<DeviceInfo> DeviceInfoService::GetDeviceInfo( |
| 242 const std::string& client_id) const { | 222 const std::string& client_id) const { |
| 243 const ClientIdToSpecifics::const_iterator iter = all_data_.find(client_id); | 223 const ClientIdToSpecifics::const_iterator iter = all_data_.find(client_id); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 store_->DeleteData(batch, guid); | 306 store_->DeleteData(batch, guid); |
| 327 all_data_.erase(iter); | 307 all_data_.erase(iter); |
| 328 return true; | 308 return true; |
| 329 } else { | 309 } else { |
| 330 return false; | 310 return false; |
| 331 } | 311 } |
| 332 } | 312 } |
| 333 | 313 |
| 334 void DeviceInfoService::OnProviderInitialized() { | 314 void DeviceInfoService::OnProviderInitialized() { |
| 335 has_provider_initialized_ = true; | 315 has_provider_initialized_ = true; |
| 336 TryReconcileLocalAndStored(); | 316 LoadMetadataIfReady(); |
| 337 } | 317 } |
| 338 | 318 |
| 339 void DeviceInfoService::OnStoreCreated(Result result, | 319 void DeviceInfoService::OnStoreCreated(Result result, |
| 340 std::unique_ptr<ModelTypeStore> store) { | 320 std::unique_ptr<ModelTypeStore> store) { |
| 341 if (result == Result::SUCCESS) { | 321 if (result == Result::SUCCESS) { |
| 342 std::swap(store_, store); | 322 std::swap(store_, store); |
| 343 store_->ReadAllData(base::Bind(&DeviceInfoService::OnReadAllData, | 323 store_->ReadAllData(base::Bind(&DeviceInfoService::OnReadAllData, |
| 344 weak_factory_.GetWeakPtr())); | 324 weak_factory_.GetWeakPtr())); |
| 345 } else { | 325 } else { |
| 346 LOG(WARNING) << "ModelTypeStore creation failed."; | 326 ReportStartupErrorToSync("ModelTypeStore creation failed."); |
| 347 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization | 327 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization |
| 348 // failure. | 328 // failure. |
| 349 } | 329 } |
| 350 } | 330 } |
| 351 | 331 |
| 352 void DeviceInfoService::OnReadAllData(Result result, | 332 void DeviceInfoService::OnReadAllData(Result result, |
| 353 std::unique_ptr<RecordList> record_list) { | 333 std::unique_ptr<RecordList> record_list) { |
| 354 if (result != Result::SUCCESS) { | 334 if (result != Result::SUCCESS) { |
| 355 LOG(WARNING) << "Initial load of data failed."; | 335 ReportStartupErrorToSync("Initial load of data failed."); |
| 356 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization | 336 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization |
| 357 // failure. | 337 // failure. |
| 358 return; | 338 return; |
| 359 } | 339 } |
| 360 | 340 |
| 361 for (const Record& r : *record_list.get()) { | 341 for (const Record& r : *record_list.get()) { |
| 362 std::unique_ptr<DeviceInfoSpecifics> specifics( | 342 std::unique_ptr<DeviceInfoSpecifics> specifics( |
| 363 base::WrapUnique(new DeviceInfoSpecifics())); | 343 base::WrapUnique(new DeviceInfoSpecifics())); |
| 364 if (specifics->ParseFromString(r.value)) { | 344 if (specifics->ParseFromString(r.value)) { |
| 365 all_data_[specifics->cache_guid()] = std::move(specifics); | 345 all_data_[specifics->cache_guid()] = std::move(specifics); |
| 366 } else { | 346 } else { |
| 367 LOG(WARNING) << "Failed to deserialize specifics."; | 347 ReportStartupErrorToSync("Failed to deserialize specifics."); |
| 368 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization | 348 // TODO(skym, crbug.com/582460): Handle unrecoverable initialization |
| 369 // failure. | 349 // failure. |
| 370 } | 350 } |
| 371 } | 351 } |
| 372 store_->ReadAllMetadata(base::Bind(&DeviceInfoService::OnReadAllMetadata, | 352 |
| 373 weak_factory_.GetWeakPtr())); | 353 has_data_loaded_ = true; |
| 354 LoadMetadataIfReady(); |
| 355 } |
| 356 |
| 357 void DeviceInfoService::LoadMetadataIfReady() { |
| 358 if (has_data_loaded_ && has_provider_initialized_) { |
| 359 store_->ReadAllMetadata(base::Bind(&DeviceInfoService::OnReadAllMetadata, |
| 360 weak_factory_.GetWeakPtr())); |
| 361 } |
| 374 } | 362 } |
| 375 | 363 |
| 376 void DeviceInfoService::OnReadAllMetadata( | 364 void DeviceInfoService::OnReadAllMetadata( |
| 377 Result result, | 365 Result result, |
| 378 std::unique_ptr<RecordList> metadata_records, | 366 std::unique_ptr<RecordList> metadata_records, |
| 379 const std::string& global_metadata) { | 367 const std::string& global_metadata) { |
| 368 DCHECK(!has_metadata_loaded_); |
| 369 |
| 380 if (result != Result::SUCCESS) { | 370 if (result != Result::SUCCESS) { |
| 381 // Store has encountered some serious error. We should still be able to | 371 // Store has encountered some serious error. We should still be able to |
| 382 // continue as a read only service, since if we got this far we must have | 372 // continue as a read only service, since if we got this far we must have |
| 383 // loaded all data out succesfully. TODO(skym): Should we communicate this | 373 // loaded all data out succesfully. |
| 384 // to sync somehow? | 374 ReportStartupErrorToSync("Load of metadata completely failed."); |
| 385 LOG(WARNING) << "Load of metadata completely failed."; | |
| 386 return; | 375 return; |
| 387 } | 376 } |
| 388 | 377 |
| 389 // If we have no metadata then we don't want to create a processor. The idea | 378 // If we have no metadata then we don't want to create a processor. The idea |
| 390 // is that by not having a processor, the services will suffer less of a | 379 // is that by not having a processor, the services will suffer less of a |
| 391 // performance hit. This isn't terribly applicable for this model type, but | 380 // performance hit. This isn't terribly applicable for this model type, but |
| 392 // we want this class to be as similar to other services as possible so follow | 381 // we want this class to be as similar to other services as possible so follow |
| 393 // the convention. | 382 // the convention. |
| 394 if (metadata_records->size() > 0 || !global_metadata.empty()) { | 383 if (metadata_records->size() > 0 || !global_metadata.empty()) { |
| 395 CreateChangeProcessor(); | 384 CreateChangeProcessor(); |
| 396 } | 385 } |
| 397 | 386 |
| 398 // Set this after OnChangeProcessorSet so that we can correctly avoid giving | 387 // Set this after OnChangeProcessorSet so that we can correctly avoid giving |
| 399 // the processor empty metadata. We always want to set |has_metadata_loaded_| | 388 // the processor empty metadata. We always want to set |has_metadata_loaded_| |
| 400 // at this point so that we'll know to give a processor empty metadata if it | 389 // at this point so that we'll know to give a processor empty metadata if it |
| 401 // is created later. | 390 // is created later. |
| 402 has_metadata_loaded_ = true; | 391 has_metadata_loaded_ = true; |
| 403 | 392 |
| 404 if (!change_processor()) { | 393 if (!change_processor()) { |
| 405 // This means we haven't been told to start sycning and we don't have any | 394 // This means we haven't been told to start syncing and we don't have any |
| 406 // local metadata | 395 // local metadata. |
| 407 return; | 396 return; |
| 408 } | 397 } |
| 409 | 398 |
| 410 std::unique_ptr<MetadataBatch> batch(new MetadataBatch()); | 399 std::unique_ptr<MetadataBatch> batch(new MetadataBatch()); |
| 411 DataTypeState state; | 400 DataTypeState state; |
| 412 if (state.ParseFromString(global_metadata)) { | 401 if (state.ParseFromString(global_metadata)) { |
| 413 batch->SetDataTypeState(state); | 402 batch->SetDataTypeState(state); |
| 414 } else { | 403 } else { |
| 415 // TODO(skym): How bad is this scenario? We may be able to just give an | 404 // TODO(skym): How bad is this scenario? We may be able to just give an |
| 416 // empty batch to the processor and we'll treat corrupted data type state | 405 // empty batch to the processor and we'll treat corrupted data type state |
| 417 // as no data type state at all. The question is do we want to add any of | 406 // as no data type state at all. The question is do we want to add any of |
| 418 // the entity metadata to the batch or completely skip that step? We're | 407 // the entity metadata to the batch or completely skip that step? We're |
| 419 // going to have to perform a merge shortly. Does this decision/logic even | 408 // going to have to perform a merge shortly. Does this decision/logic even |
| 420 // belong in this service? | 409 // belong in this service? |
| 421 LOG(WARNING) << "Failed to deserialize global metadata."; | 410 change_processor()->OnMetadataLoaded( |
| 411 change_processor()->CreateAndUploadError( |
| 412 FROM_HERE, "Failed to deserialize global metadata."), |
| 413 nullptr); |
| 422 } | 414 } |
| 423 for (const Record& r : *metadata_records.get()) { | 415 for (const Record& r : *metadata_records.get()) { |
| 424 sync_pb::EntityMetadata entity_metadata; | 416 sync_pb::EntityMetadata entity_metadata; |
| 425 if (entity_metadata.ParseFromString(r.value)) { | 417 if (entity_metadata.ParseFromString(r.value)) { |
| 426 batch->AddMetadata(r.id, entity_metadata); | 418 batch->AddMetadata(r.id, entity_metadata); |
| 427 } else { | 419 } else { |
| 428 // TODO(skym): This really isn't too bad. We just want to regenerate | 420 // TODO(skym): This really isn't too bad. We just want to regenerate |
| 429 // metadata for this particular entity. Unfortunately there isn't a | 421 // metadata for this particular entity. Unfortunately there isn't a |
| 430 // convinient way to tell the processor to do this. | 422 // convenient way to tell the processor to do this. |
| 431 LOG(WARNING) << "Failed to deserialize entity metadata."; | 423 LOG(WARNING) << "Failed to deserialize entity metadata."; |
| 432 } | 424 } |
| 433 } | 425 } |
| 434 change_processor()->OnMetadataLoaded(syncer::SyncError(), std::move(batch)); | 426 change_processor()->OnMetadataLoaded(SyncError(), std::move(batch)); |
| 435 TryReconcileLocalAndStored(); | 427 ReconcileLocalAndStored(); |
| 436 } | 428 } |
| 437 | 429 |
| 438 void DeviceInfoService::OnCommit(Result result) { | 430 void DeviceInfoService::OnCommit(Result result) { |
| 439 if (result != Result::SUCCESS) { | 431 if (result != Result::SUCCESS) { |
| 440 LOG(WARNING) << "Failed a write to store."; | 432 LOG(WARNING) << "Failed a write to store."; |
| 441 } | 433 } |
| 442 } | 434 } |
| 443 | 435 |
| 444 void DeviceInfoService::TryReconcileLocalAndStored() { | 436 void DeviceInfoService::ReconcileLocalAndStored() { |
| 445 // On initial syncing we will have a change processor here, but it will not be | 437 // On initial syncing we will have a change processor here, but it will not be |
| 446 // tracking changes. We need to persist a copy of our local device info to | 438 // tracking changes. We need to persist a copy of our local device info to |
| 447 // disk, but the Put call to the processor will be ignored. That should be | 439 // disk, but the Put call to the processor will be ignored. That should be |
| 448 // fine however, as the discrepancy will be picked up later in merge. We don't | 440 // fine however, as the discrepancy will be picked up later in merge. We don't |
| 449 // bother trying to track this case and act intelligently because simply not | 441 // bother trying to track this case and act intelligently because simply not |
| 450 // much of a benefit in doing so. | 442 // much of a benefit in doing so. |
| 451 if (has_provider_initialized_ && has_metadata_loaded_ && change_processor()) { | 443 DCHECK(has_provider_initialized_); |
| 452 const DeviceInfo* current_info = | 444 DCHECK(has_metadata_loaded_); |
| 453 local_device_info_provider_->GetLocalDeviceInfo(); | 445 DCHECK(change_processor()); |
| 454 auto iter = all_data_.find(current_info->guid()); | 446 const DeviceInfo* current_info = |
| 447 local_device_info_provider_->GetLocalDeviceInfo(); |
| 448 auto iter = all_data_.find(current_info->guid()); |
| 455 | 449 |
| 456 // Convert to DeviceInfo for Equals function. | 450 // Convert to DeviceInfo for Equals function. |
| 457 if (iter != all_data_.end() && | 451 if (iter != all_data_.end() && |
| 458 current_info->Equals(*CopyToModel(*iter->second))) { | 452 current_info->Equals(*CopyToModel(*iter->second))) { |
| 459 const TimeDelta pulse_delay(DeviceInfoUtil::CalculatePulseDelay( | 453 const TimeDelta pulse_delay(DeviceInfoUtil::CalculatePulseDelay( |
| 460 GetLastUpdateTime(*iter->second), Time::Now())); | 454 GetLastUpdateTime(*iter->second), Time::Now())); |
| 461 if (!pulse_delay.is_zero()) { | 455 if (!pulse_delay.is_zero()) { |
| 462 pulse_timer_.Start(FROM_HERE, pulse_delay, | 456 pulse_timer_.Start(FROM_HERE, pulse_delay, |
| 463 base::Bind(&DeviceInfoService::SendLocalData, | 457 base::Bind(&DeviceInfoService::SendLocalData, |
| 464 base::Unretained(this))); | 458 base::Unretained(this))); |
| 465 return; | 459 return; |
| 466 } | |
| 467 } | 460 } |
| 468 SendLocalData(); | |
| 469 } | 461 } |
| 462 SendLocalData(); |
| 470 } | 463 } |
| 471 | 464 |
| 472 void DeviceInfoService::SendLocalData() { | 465 void DeviceInfoService::SendLocalData() { |
| 473 DCHECK(has_provider_initialized_); | 466 DCHECK(has_provider_initialized_); |
| 474 // TODO(skym): Handle disconnecting and reconnecting, this will currently halt | 467 // TODO(skym): Handle disconnecting and reconnecting, this will currently halt |
| 475 // the pulse timer and never restart it. | 468 // the pulse timer and never restart it. |
| 476 if (change_processor()) { | 469 if (!change_processor()) { |
| 477 std::unique_ptr<DeviceInfoSpecifics> specifics = | 470 return; |
| 478 CopyToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo()); | 471 } |
| 479 specifics->set_last_updated_timestamp(syncer::TimeToProtoTime(Time::Now())); | |
| 480 | 472 |
| 481 std::unique_ptr<MetadataChangeList> metadata_change_list = | 473 std::unique_ptr<DeviceInfoSpecifics> specifics = |
| 482 CreateMetadataChangeList(); | 474 CopyToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo()); |
| 483 change_processor()->Put(DeviceInfoUtil::SpecificsToTag(*specifics), | 475 specifics->set_last_updated_timestamp(syncer::TimeToProtoTime(Time::Now())); |
| 484 CopyToEntityData(*specifics), | |
| 485 metadata_change_list.get()); | |
| 486 | 476 |
| 487 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); | 477 std::unique_ptr<MetadataChangeList> metadata_change_list = |
| 488 StoreSpecifics(std::move(specifics), batch.get()); | 478 CreateMetadataChangeList(); |
| 479 change_processor()->Put(DeviceInfoUtil::SpecificsToTag(*specifics), |
| 480 CopyToEntityData(*specifics), |
| 481 metadata_change_list.get()); |
| 489 | 482 |
| 490 CommitAndNotify(std::move(batch), std::move(metadata_change_list), true); | 483 std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); |
| 491 pulse_timer_.Start( | 484 StoreSpecifics(std::move(specifics), batch.get()); |
| 492 FROM_HERE, DeviceInfoUtil::kPulseInterval, | 485 |
| 493 base::Bind(&DeviceInfoService::SendLocalData, base::Unretained(this))); | 486 CommitAndNotify(std::move(batch), std::move(metadata_change_list), true); |
| 494 } | 487 pulse_timer_.Start( |
| 488 FROM_HERE, DeviceInfoUtil::kPulseInterval, |
| 489 base::Bind(&DeviceInfoService::SendLocalData, base::Unretained(this))); |
| 495 } | 490 } |
| 496 | 491 |
| 497 void DeviceInfoService::CommitAndNotify( | 492 void DeviceInfoService::CommitAndNotify( |
| 498 std::unique_ptr<WriteBatch> batch, | 493 std::unique_ptr<WriteBatch> batch, |
| 499 std::unique_ptr<MetadataChangeList> metadata_change_list, | 494 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 500 bool should_notify) { | 495 bool should_notify) { |
| 501 static_cast<SimpleMetadataChangeList*>(metadata_change_list.get()) | 496 static_cast<SimpleMetadataChangeList*>(metadata_change_list.get()) |
| 502 ->TransferChanges(store_.get(), batch.get()); | 497 ->TransferChanges(store_.get(), batch.get()); |
| 503 store_->CommitWriteBatch( | 498 store_->CommitWriteBatch( |
| 504 std::move(batch), | 499 std::move(batch), |
| 505 base::Bind(&DeviceInfoService::OnCommit, weak_factory_.GetWeakPtr())); | 500 base::Bind(&DeviceInfoService::OnCommit, weak_factory_.GetWeakPtr())); |
| 506 if (should_notify) { | 501 if (should_notify) { |
| 507 NotifyObservers(); | 502 NotifyObservers(); |
| 508 } | 503 } |
| 509 } | 504 } |
| 510 | 505 |
| 511 int DeviceInfoService::CountActiveDevices(const Time now) const { | 506 int DeviceInfoService::CountActiveDevices(const Time now) const { |
| 512 return std::count_if(all_data_.begin(), all_data_.end(), | 507 return std::count_if(all_data_.begin(), all_data_.end(), |
| 513 [now](ClientIdToSpecifics::const_reference pair) { | 508 [now](ClientIdToSpecifics::const_reference pair) { |
| 514 return DeviceInfoUtil::IsActive( | 509 return DeviceInfoUtil::IsActive( |
| 515 GetLastUpdateTime(*pair.second), now); | 510 GetLastUpdateTime(*pair.second), now); |
| 516 }); | 511 }); |
| 517 } | 512 } |
| 518 | 513 |
| 514 void DeviceInfoService::ReportStartupErrorToSync(const std::string& msg) { |
| 515 DCHECK(!has_metadata_loaded_); |
| 516 LOG(WARNING) << msg; |
| 517 |
| 518 // Create a processor and give it the error in case sync tries to start. |
| 519 if (!change_processor()) { |
| 520 CreateChangeProcessor(); |
| 521 } |
| 522 change_processor()->OnMetadataLoaded( |
| 523 change_processor()->CreateAndUploadError(FROM_HERE, msg), nullptr); |
| 524 } |
| 525 |
| 519 // static | 526 // static |
| 520 Time DeviceInfoService::GetLastUpdateTime( | 527 Time DeviceInfoService::GetLastUpdateTime( |
| 521 const DeviceInfoSpecifics& specifics) { | 528 const DeviceInfoSpecifics& specifics) { |
| 522 if (specifics.has_last_updated_timestamp()) { | 529 if (specifics.has_last_updated_timestamp()) { |
| 523 return syncer::ProtoTimeToTime(specifics.last_updated_timestamp()); | 530 return syncer::ProtoTimeToTime(specifics.last_updated_timestamp()); |
| 524 } else { | 531 } else { |
| 525 return Time(); | 532 return Time(); |
| 526 } | 533 } |
| 527 } | 534 } |
| 528 | 535 |
| 529 } // namespace sync_driver_v2 | 536 } // namespace sync_driver_v2 |
| OLD | NEW |