OLD | NEW |
| (Empty) |
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 | |
5 #include "chrome/browser/sync/sessions/sync_session.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/logging.h" | |
10 #include "chrome/browser/sync/syncable/model_type.h" | |
11 #include "chrome/browser/sync/syncable/syncable.h" | |
12 | |
13 namespace browser_sync { | |
14 namespace sessions { | |
15 | |
16 namespace { | |
17 | |
18 std::set<ModelSafeGroup> ComputeEnabledGroups( | |
19 const ModelSafeRoutingInfo& routing_info, | |
20 const std::vector<ModelSafeWorker*>& workers) { | |
21 std::set<ModelSafeGroup> enabled_groups; | |
22 // Project the list of enabled types (i.e., types in the routing | |
23 // info) to a list of enabled groups. | |
24 for (ModelSafeRoutingInfo::const_iterator it = routing_info.begin(); | |
25 it != routing_info.end(); ++it) { | |
26 enabled_groups.insert(it->second); | |
27 } | |
28 // GROUP_PASSIVE is always enabled, since that's the group that | |
29 // top-level folders map to. | |
30 enabled_groups.insert(GROUP_PASSIVE); | |
31 if (DCHECK_IS_ON()) { | |
32 // We sometimes create dummy SyncSession objects (see | |
33 // SyncScheduler::InitialSnapshot) so don't check in that case. | |
34 if (!routing_info.empty() || !workers.empty()) { | |
35 std::set<ModelSafeGroup> groups_with_workers; | |
36 for (std::vector<ModelSafeWorker*>::const_iterator it = workers.begin(); | |
37 it != workers.end(); ++it) { | |
38 groups_with_workers.insert((*it)->GetModelSafeGroup()); | |
39 } | |
40 // All enabled groups should have a corresponding worker. | |
41 DCHECK(std::includes( | |
42 groups_with_workers.begin(), groups_with_workers.end(), | |
43 enabled_groups.begin(), enabled_groups.end())); | |
44 } | |
45 } | |
46 return enabled_groups; | |
47 } | |
48 | |
49 } // namesepace | |
50 | |
51 SyncSession::SyncSession(SyncSessionContext* context, Delegate* delegate, | |
52 const SyncSourceInfo& source, | |
53 const ModelSafeRoutingInfo& routing_info, | |
54 const std::vector<ModelSafeWorker*>& workers) | |
55 : context_(context), | |
56 source_(source), | |
57 write_transaction_(NULL), | |
58 delegate_(delegate), | |
59 workers_(workers), | |
60 routing_info_(routing_info), | |
61 enabled_groups_(ComputeEnabledGroups(routing_info_, workers_)) { | |
62 status_controller_.reset(new StatusController(routing_info_)); | |
63 std::sort(workers_.begin(), workers_.end()); | |
64 } | |
65 | |
66 SyncSession::~SyncSession() {} | |
67 | |
68 void SyncSession::Coalesce(const SyncSession& session) { | |
69 if (context_ != session.context() || delegate_ != session.delegate_) { | |
70 NOTREACHED(); | |
71 return; | |
72 } | |
73 | |
74 // When we coalesce sessions, the sync update source gets overwritten with the | |
75 // most recent, while the type/payload map gets merged. | |
76 CoalescePayloads(&source_.types, session.source_.types); | |
77 source_.updates_source = session.source_.updates_source; | |
78 | |
79 std::vector<ModelSafeWorker*> temp; | |
80 std::set_union(workers_.begin(), workers_.end(), | |
81 session.workers_.begin(), session.workers_.end(), | |
82 std::back_inserter(temp)); | |
83 workers_.swap(temp); | |
84 | |
85 // We have to update the model safe routing info to the union. In case the | |
86 // same key is present in both pick the one from session. | |
87 for (ModelSafeRoutingInfo::const_iterator it = | |
88 session.routing_info_.begin(); | |
89 it != session.routing_info_.end(); | |
90 ++it) { | |
91 routing_info_[it->first] = it->second; | |
92 } | |
93 | |
94 // Now update enabled groups. | |
95 enabled_groups_ = ComputeEnabledGroups(routing_info_, workers_); | |
96 } | |
97 | |
98 void SyncSession::RebaseRoutingInfoWithLatest(const SyncSession& session) { | |
99 ModelSafeRoutingInfo temp_routing_info; | |
100 | |
101 // Take the intersecion and also set the routing info(it->second) from the | |
102 // passed in session. | |
103 for (ModelSafeRoutingInfo::const_iterator it = | |
104 session.routing_info_.begin(); it != session.routing_info_.end(); | |
105 ++it) { | |
106 if (routing_info_.find(it->first) != routing_info_.end()) { | |
107 temp_routing_info[it->first] = it->second; | |
108 } | |
109 } | |
110 | |
111 // Now swap it. | |
112 routing_info_.swap(temp_routing_info); | |
113 | |
114 // Now update the payload map. | |
115 PurgeStalePayload(&source_.types, session.routing_info_); | |
116 | |
117 // Now update the workers. | |
118 std::vector<ModelSafeWorker*> temp; | |
119 std::set_intersection(workers_.begin(), workers_.end(), | |
120 session.workers_.begin(), session.workers_.end(), | |
121 std::back_inserter(temp)); | |
122 workers_.swap(temp); | |
123 | |
124 // Now update enabled groups. | |
125 enabled_groups_ = ComputeEnabledGroups(routing_info_, workers_); | |
126 } | |
127 | |
128 void SyncSession::PrepareForAnotherSyncCycle() { | |
129 source_.updates_source = | |
130 sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; | |
131 status_controller_.reset(new StatusController(routing_info_)); | |
132 } | |
133 | |
134 SyncSessionSnapshot SyncSession::TakeSnapshot() const { | |
135 syncable::Directory* dir = context_->directory(); | |
136 | |
137 bool is_share_useable = true; | |
138 syncable::ModelTypeSet initial_sync_ended; | |
139 std::string download_progress_markers[syncable::MODEL_TYPE_COUNT]; | |
140 for (int i = syncable::FIRST_REAL_MODEL_TYPE; | |
141 i < syncable::MODEL_TYPE_COUNT; ++i) { | |
142 syncable::ModelType type(syncable::ModelTypeFromInt(i)); | |
143 if (routing_info_.count(type) != 0) { | |
144 if (dir->initial_sync_ended_for_type(type)) | |
145 initial_sync_ended.Put(type); | |
146 else | |
147 is_share_useable = false; | |
148 } | |
149 dir->GetDownloadProgressAsString(type, &download_progress_markers[i]); | |
150 } | |
151 | |
152 return SyncSessionSnapshot( | |
153 status_controller_->syncer_status(), | |
154 status_controller_->error(), | |
155 status_controller_->num_server_changes_remaining(), | |
156 is_share_useable, | |
157 initial_sync_ended, | |
158 download_progress_markers, | |
159 HasMoreToSync(), | |
160 delegate_->IsSyncingCurrentlySilenced(), | |
161 status_controller_->unsynced_handles().size(), | |
162 status_controller_->TotalNumEncryptionConflictingItems(), | |
163 status_controller_->TotalNumHierarchyConflictingItems(), | |
164 status_controller_->TotalNumSimpleConflictingItems(), | |
165 status_controller_->TotalNumServerConflictingItems(), | |
166 status_controller_->did_commit_items(), | |
167 source_, | |
168 dir->GetEntriesCount(), | |
169 status_controller_->sync_start_time(), | |
170 !Succeeded()); | |
171 } | |
172 | |
173 void SyncSession::SendEventNotification(SyncEngineEvent::EventCause cause) { | |
174 SyncEngineEvent event(cause); | |
175 const SyncSessionSnapshot& snapshot = TakeSnapshot(); | |
176 event.snapshot = &snapshot; | |
177 | |
178 DVLOG(1) << "Sending event with snapshot: " << snapshot.ToString(); | |
179 context()->NotifyListeners(event); | |
180 } | |
181 | |
182 bool SyncSession::HasMoreToSync() const { | |
183 const StatusController* status = status_controller_.get(); | |
184 return ((status->commit_ids().size() < status->unsynced_handles().size()) && | |
185 status->syncer_status().num_successful_commits > 0) || | |
186 status->conflicts_resolved(); | |
187 // Or, we have conflicting updates, but we're making progress on | |
188 // resolving them... | |
189 } | |
190 | |
191 const std::set<ModelSafeGroup>& SyncSession::GetEnabledGroups() const { | |
192 return enabled_groups_; | |
193 } | |
194 | |
195 std::set<ModelSafeGroup> SyncSession::GetEnabledGroupsWithConflicts() const { | |
196 const std::set<ModelSafeGroup>& enabled_groups = GetEnabledGroups(); | |
197 std::set<ModelSafeGroup> enabled_groups_with_conflicts; | |
198 for (std::set<ModelSafeGroup>::const_iterator it = | |
199 enabled_groups.begin(); it != enabled_groups.end(); ++it) { | |
200 const sessions::ConflictProgress* conflict_progress = | |
201 status_controller_->GetUnrestrictedConflictProgress(*it); | |
202 if (conflict_progress && | |
203 (conflict_progress->SimpleConflictingItemsBegin() != | |
204 conflict_progress->SimpleConflictingItemsEnd())) { | |
205 enabled_groups_with_conflicts.insert(*it); | |
206 } | |
207 } | |
208 return enabled_groups_with_conflicts; | |
209 } | |
210 | |
211 std::set<ModelSafeGroup> | |
212 SyncSession::GetEnabledGroupsWithVerifiedUpdates() const { | |
213 const std::set<ModelSafeGroup>& enabled_groups = GetEnabledGroups(); | |
214 std::set<ModelSafeGroup> enabled_groups_with_verified_updates; | |
215 for (std::set<ModelSafeGroup>::const_iterator it = | |
216 enabled_groups.begin(); it != enabled_groups.end(); ++it) { | |
217 const UpdateProgress* update_progress = | |
218 status_controller_->GetUnrestrictedUpdateProgress(*it); | |
219 if (update_progress && | |
220 (update_progress->VerifiedUpdatesBegin() != | |
221 update_progress->VerifiedUpdatesEnd())) { | |
222 enabled_groups_with_verified_updates.insert(*it); | |
223 } | |
224 } | |
225 | |
226 return enabled_groups_with_verified_updates; | |
227 } | |
228 | |
229 namespace { | |
230 // Return true if the command in question was attempted and did not complete | |
231 // successfully. | |
232 // | |
233 bool IsError(SyncerError error) { | |
234 return error != UNSET | |
235 && error != SYNCER_OK | |
236 && error != SERVER_RETURN_MIGRATION_DONE; | |
237 } | |
238 } // namespace | |
239 | |
240 bool SyncSession::Succeeded() const { | |
241 const bool download_updates_error = | |
242 IsError(status_controller_->error().last_download_updates_result); | |
243 const bool post_commit_error = | |
244 IsError(status_controller_->error().last_post_commit_result); | |
245 const bool process_commit_response_error = | |
246 IsError(status_controller_->error().last_process_commit_response_result); | |
247 return !download_updates_error | |
248 && !post_commit_error | |
249 && !process_commit_response_error; | |
250 } | |
251 | |
252 } // namespace sessions | |
253 } // namespace browser_sync | |
OLD | NEW |