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 |