syncer.cc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/sync/engine/syncer.h"
  5. #include <memory>
  6. #include <string>
  7. #include "base/auto_reset.h"
  8. #include "base/logging.h"
  9. #include "base/metrics/histogram_functions.h"
  10. #include "base/trace_event/trace_event.h"
  11. #include "components/sync/base/features.h"
  12. #include "components/sync/base/model_type.h"
  13. #include "components/sync/engine/active_devices_invalidation_info.h"
  14. #include "components/sync/engine/cancelation_signal.h"
  15. #include "components/sync/engine/commit.h"
  16. #include "components/sync/engine/commit_processor.h"
  17. #include "components/sync/engine/cycle/nudge_tracker.h"
  18. #include "components/sync/engine/cycle/sync_cycle.h"
  19. #include "components/sync/engine/get_updates_delegate.h"
  20. #include "components/sync/engine/get_updates_processor.h"
  21. #include "components/sync/engine/net/server_connection_manager.h"
  22. namespace syncer {
  23. namespace {
  24. // Returns invalidation info after applying updates. This is used to drop
  25. // optimization flags if DeviceInfo has been just updated (and new subscriptions
  26. // might be just received). Without that if a new device with enabled
  27. // invalidations has been just received, it may be updated only in the next
  28. // sync cycle due to delay between threads.
  29. ActiveDevicesInvalidationInfo GetInvalidationInfo(const SyncCycle* cycle) {
  30. if (cycle->status_controller().get_updated_types().Has(DEVICE_INFO) &&
  31. base::FeatureList::IsEnabled(
  32. kSkipInvalidationOptimizationsWhenDeviceInfoUpdated)) {
  33. return ActiveDevicesInvalidationInfo::CreateUninitialized();
  34. }
  35. return cycle->context()->active_devices_invalidation_info();
  36. }
  37. void HandleCycleBegin(SyncCycle* cycle) {
  38. cycle->mutable_status_controller()->UpdateStartTime();
  39. cycle->mutable_status_controller()->clear_updated_types();
  40. cycle->SendEventNotification(SyncCycleEvent::SYNC_CYCLE_BEGIN);
  41. }
  42. } // namespace
  43. Syncer::Syncer(CancelationSignal* cancelation_signal)
  44. : cancelation_signal_(cancelation_signal), is_syncing_(false) {}
  45. Syncer::~Syncer() = default;
  46. bool Syncer::IsSyncing() const {
  47. return is_syncing_;
  48. }
  49. bool Syncer::NormalSyncShare(ModelTypeSet request_types,
  50. NudgeTracker* nudge_tracker,
  51. SyncCycle* cycle) {
  52. base::AutoReset<bool> is_syncing(&is_syncing_, true);
  53. HandleCycleBegin(cycle);
  54. if (nudge_tracker->IsGetUpdatesRequired(request_types)) {
  55. VLOG(1) << "Downloading types " << ModelTypeSetToDebugString(request_types);
  56. if (!DownloadAndApplyUpdates(&request_types, cycle,
  57. NormalGetUpdatesDelegate(*nudge_tracker))) {
  58. return HandleCycleEnd(cycle, nudge_tracker->GetOrigin());
  59. }
  60. }
  61. SyncerError commit_result =
  62. BuildAndPostCommits(request_types, nudge_tracker, cycle);
  63. cycle->mutable_status_controller()->set_commit_result(commit_result);
  64. return HandleCycleEnd(cycle, nudge_tracker->GetOrigin());
  65. }
  66. bool Syncer::ConfigureSyncShare(const ModelTypeSet& request_types,
  67. sync_pb::SyncEnums::GetUpdatesOrigin origin,
  68. SyncCycle* cycle) {
  69. base::AutoReset<bool> is_syncing(&is_syncing_, true);
  70. // It is possible during configuration that datatypes get unregistered from
  71. // ModelTypeRegistry before scheduled configure sync cycle gets executed.
  72. // This happens either because DataTypeController::LoadModels fail and type
  73. // need to be stopped or during shutdown when all datatypes are stopped. When
  74. // it happens we should adjust set of types to download to only include
  75. // registered types.
  76. ModelTypeSet still_enabled_types =
  77. Intersection(request_types, cycle->context()->GetConnectedTypes());
  78. VLOG(1) << "Configuring types "
  79. << ModelTypeSetToDebugString(still_enabled_types);
  80. HandleCycleBegin(cycle);
  81. DownloadAndApplyUpdates(&still_enabled_types, cycle,
  82. ConfigureGetUpdatesDelegate(origin));
  83. return HandleCycleEnd(cycle, origin);
  84. }
  85. bool Syncer::PollSyncShare(ModelTypeSet request_types, SyncCycle* cycle) {
  86. base::AutoReset<bool> is_syncing(&is_syncing_, true);
  87. VLOG(1) << "Polling types " << ModelTypeSetToDebugString(request_types);
  88. HandleCycleBegin(cycle);
  89. DownloadAndApplyUpdates(&request_types, cycle, PollGetUpdatesDelegate());
  90. return HandleCycleEnd(cycle, sync_pb::SyncEnums::PERIODIC);
  91. }
  92. bool Syncer::DownloadAndApplyUpdates(ModelTypeSet* request_types,
  93. SyncCycle* cycle,
  94. const GetUpdatesDelegate& delegate) {
  95. // CommitOnlyTypes() should not be included in the GetUpdates, but should be
  96. // included in the Commit. We are given a set of types for our SyncShare,
  97. // and we must do this filtering. Note that |request_types| is also an out
  98. // param, see below where we update it.
  99. ModelTypeSet requested_commit_only_types =
  100. Intersection(*request_types, CommitOnlyTypes());
  101. ModelTypeSet download_types =
  102. Difference(*request_types, requested_commit_only_types);
  103. GetUpdatesProcessor get_updates_processor(
  104. cycle->context()->model_type_registry()->update_handler_map(), delegate);
  105. SyncerError download_result;
  106. do {
  107. download_result =
  108. get_updates_processor.DownloadUpdates(&download_types, cycle);
  109. } while (download_result.value() == SyncerError::SERVER_MORE_TO_DOWNLOAD);
  110. // It is our responsibility to propagate the removal of types that occurred in
  111. // GetUpdatesProcessor::DownloadUpdates().
  112. *request_types = Union(download_types, requested_commit_only_types);
  113. // Exit without applying if we're shutting down or an error was detected.
  114. if (download_result.value() != SyncerError::SYNCER_OK || ExitRequested())
  115. return false;
  116. {
  117. TRACE_EVENT0("sync", "ApplyUpdates");
  118. // Apply updates to the other types. May or may not involve cross-thread
  119. // traffic, depending on the underlying update handlers and the GU type's
  120. // delegate.
  121. get_updates_processor.ApplyUpdates(download_types,
  122. cycle->mutable_status_controller());
  123. cycle->SendEventNotification(SyncCycleEvent::STATUS_CHANGED);
  124. }
  125. return !ExitRequested();
  126. }
  127. SyncerError Syncer::BuildAndPostCommits(const ModelTypeSet& request_types,
  128. NudgeTracker* nudge_tracker,
  129. SyncCycle* cycle) {
  130. VLOG(1) << "Committing from types "
  131. << ModelTypeSetToDebugString(request_types);
  132. CommitProcessor commit_processor(
  133. request_types,
  134. cycle->context()->model_type_registry()->commit_contributor_map());
  135. // The ExitRequested() check is unnecessary, since we should start getting
  136. // errors from the ServerConnectionManager if an exist has been requested.
  137. // However, it doesn't hurt to check it anyway.
  138. while (!ExitRequested()) {
  139. std::unique_ptr<Commit> commit(Commit::Init(
  140. cycle->context()->GetConnectedTypes(),
  141. cycle->context()->proxy_tabs_datatype_enabled(),
  142. cycle->context()->max_commit_batch_size(),
  143. cycle->context()->account_name(), cycle->context()->cache_guid(),
  144. cycle->context()->cookie_jar_mismatch(), GetInvalidationInfo(cycle),
  145. &commit_processor, cycle->context()->extensions_activity()));
  146. if (!commit) {
  147. break;
  148. }
  149. SyncerError error = commit->PostAndProcessResponse(
  150. nudge_tracker, cycle, cycle->mutable_status_controller(),
  151. cycle->context()->extensions_activity());
  152. base::UmaHistogramEnumeration("Sync.CommitResponse", error.value());
  153. for (ModelType type : commit->GetContributingDataTypes()) {
  154. const std::string kPrefix = "Sync.CommitResponse.";
  155. base::UmaHistogramEnumeration(kPrefix + ModelTypeToHistogramSuffix(type),
  156. error.value());
  157. }
  158. if (error.value() != SyncerError::SYNCER_OK) {
  159. return error;
  160. }
  161. nudge_tracker->RecordSuccessfulCommitMessage(
  162. commit->GetContributingDataTypes());
  163. }
  164. return SyncerError(SyncerError::SYNCER_OK);
  165. }
  166. bool Syncer::ExitRequested() {
  167. return cancelation_signal_->IsSignalled();
  168. }
  169. bool Syncer::HandleCycleEnd(SyncCycle* cycle,
  170. sync_pb::SyncEnums::GetUpdatesOrigin origin) {
  171. if (ExitRequested())
  172. return false;
  173. bool success =
  174. !HasSyncerError(cycle->status_controller().model_neutral_state());
  175. if (success && origin == sync_pb::SyncEnums::PERIODIC) {
  176. cycle->mutable_status_controller()->UpdatePollTime();
  177. }
  178. cycle->SendSyncCycleEndEventNotification(origin);
  179. return success;
  180. }
  181. } // namespace syncer