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

Side by Side Diff: components/sync_driver/device_info_service.cc

Issue 1991023002: [Sync] USS: Fix race condition in DeviceInfoService + add error handling (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/sync_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
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
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
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
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
OLDNEW
« no previous file with comments | « components/sync_driver/device_info_service.h ('k') | components/sync_driver/device_info_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698