1 // Copyright (c) 2011 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/session_state.h"
6
7 #include <map>
8 #include <set>
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include "base/base64.h"
14 #include "base/values.h"
15 #include "chrome/browser/sync/protocol/proto_enum_conversions.h"
16
17 using std::set;
18 using std::vector;
19
20 namespace browser_sync {
21 namespace sessions {
22
SyncSourceInfo()23 SyncSourceInfo::SyncSourceInfo()
24 : updates_source(sync_pb::GetUpdatesCallerInfo::UNKNOWN) {}
25
SyncSourceInfo(const syncable::ModelTypePayloadMap & t)26 SyncSourceInfo::SyncSourceInfo(
27 const syncable::ModelTypePayloadMap& t)
28 : updates_source(sync_pb::GetUpdatesCallerInfo::UNKNOWN), types(t) {}
29
SyncSourceInfo(const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource & u,const syncable::ModelTypePayloadMap & t)30 SyncSourceInfo::SyncSourceInfo(
31 const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource& u,
32 const syncable::ModelTypePayloadMap& t)
33 : updates_source(u), types(t) {}
34
~SyncSourceInfo()35 SyncSourceInfo::~SyncSourceInfo() {}
36
ToValue() const37 DictionaryValue* SyncSourceInfo::ToValue() const {
38 DictionaryValue* value = new DictionaryValue();
39 value->SetString("updatesSource",
40 GetUpdatesSourceString(updates_source));
41 value->Set("types", syncable::ModelTypePayloadMapToValue(types));
42 return value;
43 }
44
SyncerStatus()45 SyncerStatus::SyncerStatus()
46 : invalid_store(false),
47 syncer_stuck(false),
48 syncing(false),
49 num_successful_commits(0),
50 num_successful_bookmark_commits(0),
51 num_updates_downloaded_total(0),
52 num_tombstone_updates_downloaded_total(0) {
53 }
54
~SyncerStatus()55 SyncerStatus::~SyncerStatus() {
56 }
57
ToValue() const58 DictionaryValue* SyncerStatus::ToValue() const {
59 DictionaryValue* value = new DictionaryValue();
60 value->SetBoolean("invalidStore", invalid_store);
61 value->SetBoolean("syncerStuck", syncer_stuck);
62 value->SetBoolean("syncing", syncing);
63 value->SetInteger("numSuccessfulCommits", num_successful_commits);
64 value->SetInteger("numSuccessfulBookmarkCommits",
65 num_successful_bookmark_commits);
66 value->SetInteger("numUpdatesDownloadedTotal",
67 num_updates_downloaded_total);
68 value->SetInteger("numTombstoneUpdatesDownloadedTotal",
69 num_tombstone_updates_downloaded_total);
70 return value;
71 }
72
DownloadProgressMarkersToValue(const std::string (& download_progress_markers)[syncable::MODEL_TYPE_COUNT])73 DictionaryValue* DownloadProgressMarkersToValue(
74 const std::string
75 (&download_progress_markers)[syncable::MODEL_TYPE_COUNT]) {
76 DictionaryValue* value = new DictionaryValue();
77 for (int i = syncable::FIRST_REAL_MODEL_TYPE;
78 i < syncable::MODEL_TYPE_COUNT; ++i) {
79 // TODO(akalin): Unpack the value into a protobuf.
80 std::string base64_marker;
81 bool encoded =
82 base::Base64Encode(download_progress_markers[i], &base64_marker);
83 DCHECK(encoded);
84 value->SetString(
85 syncable::ModelTypeToString(syncable::ModelTypeFromInt(i)),
86 base64_marker);
87 }
88 return value;
89 }
90
ErrorCounters()91 ErrorCounters::ErrorCounters()
92 : num_conflicting_commits(0),
93 consecutive_transient_error_commits(0),
94 consecutive_errors(0) {
95 }
96
ToValue() const97 DictionaryValue* ErrorCounters::ToValue() const {
98 DictionaryValue* value = new DictionaryValue();
99 value->SetInteger("numConflictingCommits", num_conflicting_commits);
100 value->SetInteger("consecutiveTransientErrorCommits",
101 consecutive_transient_error_commits);
102 value->SetInteger("consecutiveErrors", consecutive_errors);
103 return value;
104 }
105
SyncSessionSnapshot(const SyncerStatus & syncer_status,const ErrorCounters & errors,int64 num_server_changes_remaining,bool is_share_usable,const syncable::ModelTypeBitSet & initial_sync_ended,const std::string (& download_progress_markers)[syncable::MODEL_TYPE_COUNT],bool more_to_sync,bool is_silenced,int64 unsynced_count,int num_conflicting_updates,bool did_commit_items,const SyncSourceInfo & source)106 SyncSessionSnapshot::SyncSessionSnapshot(
107 const SyncerStatus& syncer_status,
108 const ErrorCounters& errors,
109 int64 num_server_changes_remaining,
110 bool is_share_usable,
111 const syncable::ModelTypeBitSet& initial_sync_ended,
112 const std::string
113 (&download_progress_markers)[syncable::MODEL_TYPE_COUNT],
114 bool more_to_sync,
115 bool is_silenced,
116 int64 unsynced_count,
117 int num_conflicting_updates,
118 bool did_commit_items,
119 const SyncSourceInfo& source)
120 : syncer_status(syncer_status),
121 errors(errors),
122 num_server_changes_remaining(num_server_changes_remaining),
123 is_share_usable(is_share_usable),
124 initial_sync_ended(initial_sync_ended),
125 download_progress_markers(),
126 has_more_to_sync(more_to_sync),
127 is_silenced(is_silenced),
128 unsynced_count(unsynced_count),
129 num_conflicting_updates(num_conflicting_updates),
130 did_commit_items(did_commit_items),
131 source(source) {
132 for (int i = syncable::FIRST_REAL_MODEL_TYPE;
133 i < syncable::MODEL_TYPE_COUNT; ++i) {
134 const_cast<std::string&>(this->download_progress_markers[i]).assign(
135 download_progress_markers[i]);
136 }
137 }
138
~SyncSessionSnapshot()139 SyncSessionSnapshot::~SyncSessionSnapshot() {}
140
ToValue() const141 DictionaryValue* SyncSessionSnapshot::ToValue() const {
142 DictionaryValue* value = new DictionaryValue();
143 value->Set("syncerStatus", syncer_status.ToValue());
144 value->Set("errors", errors.ToValue());
145 // We don't care too much if we lose precision here.
146 value->SetInteger("numServerChangesRemaining",
147 static_cast<int>(num_server_changes_remaining));
148 value->SetBoolean("isShareUsable", is_share_usable);
149 value->Set("initialSyncEnded",
150 syncable::ModelTypeBitSetToValue(initial_sync_ended));
151 value->Set("downloadProgressMarkers",
152 DownloadProgressMarkersToValue(download_progress_markers));
153 value->SetBoolean("hasMoreToSync", has_more_to_sync);
154 value->SetBoolean("isSilenced", is_silenced);
155 // We don't care too much if we lose precision here, also.
156 value->SetInteger("unsyncedCount",
157 static_cast<int>(unsynced_count));
158 value->SetInteger("numConflictingUpdates", num_conflicting_updates);
159 value->SetBoolean("didCommitItems", did_commit_items);
160 value->Set("source", source.ToValue());
161 return value;
162 }
163
ConflictProgress(bool * dirty_flag)164 ConflictProgress::ConflictProgress(bool* dirty_flag) : dirty_(dirty_flag) {}
165
~ConflictProgress()166 ConflictProgress::~ConflictProgress() {
167 CleanupSets();
168 }
169
IdToConflictSetFind(const syncable::Id & the_id) const170 IdToConflictSetMap::const_iterator ConflictProgress::IdToConflictSetFind(
171 const syncable::Id& the_id) const {
172 return id_to_conflict_set_.find(the_id);
173 }
174
175 IdToConflictSetMap::const_iterator
IdToConflictSetBegin() const176 ConflictProgress::IdToConflictSetBegin() const {
177 return id_to_conflict_set_.begin();
178 }
179
180 IdToConflictSetMap::const_iterator
IdToConflictSetEnd() const181 ConflictProgress::IdToConflictSetEnd() const {
182 return id_to_conflict_set_.end();
183 }
184
IdToConflictSetSize() const185 IdToConflictSetMap::size_type ConflictProgress::IdToConflictSetSize() const {
186 return id_to_conflict_set_.size();
187 }
188
IdToConflictSetGet(const syncable::Id & the_id)189 const ConflictSet* ConflictProgress::IdToConflictSetGet(
190 const syncable::Id& the_id) {
191 return id_to_conflict_set_[the_id];
192 }
193
194 std::set<ConflictSet*>::const_iterator
ConflictSetsBegin() const195 ConflictProgress::ConflictSetsBegin() const {
196 return conflict_sets_.begin();
197 }
198
199 std::set<ConflictSet*>::const_iterator
ConflictSetsEnd() const200 ConflictProgress::ConflictSetsEnd() const {
201 return conflict_sets_.end();
202 }
203
204 std::set<ConflictSet*>::size_type
ConflictSetsSize() const205 ConflictProgress::ConflictSetsSize() const {
206 return conflict_sets_.size();
207 }
208
209 std::set<syncable::Id>::iterator
ConflictingItemsBegin()210 ConflictProgress::ConflictingItemsBegin() {
211 return conflicting_item_ids_.begin();
212 }
213 std::set<syncable::Id>::const_iterator
ConflictingItemsBeginConst() const214 ConflictProgress::ConflictingItemsBeginConst() const {
215 return conflicting_item_ids_.begin();
216 }
217 std::set<syncable::Id>::const_iterator
ConflictingItemsEnd() const218 ConflictProgress::ConflictingItemsEnd() const {
219 return conflicting_item_ids_.end();
220 }
221
AddConflictingItemById(const syncable::Id & the_id)222 void ConflictProgress::AddConflictingItemById(const syncable::Id& the_id) {
223 std::pair<std::set<syncable::Id>::iterator, bool> ret =
224 conflicting_item_ids_.insert(the_id);
225 if (ret.second)
226 *dirty_ = true;
227 }
228
EraseConflictingItemById(const syncable::Id & the_id)229 void ConflictProgress::EraseConflictingItemById(const syncable::Id& the_id) {
230 int items_erased = conflicting_item_ids_.erase(the_id);
231 if (items_erased != 0)
232 *dirty_ = true;
233 }
234
MergeSets(const syncable::Id & id1,const syncable::Id & id2)235 void ConflictProgress::MergeSets(const syncable::Id& id1,
236 const syncable::Id& id2) {
237 // There are no single item sets, we just leave those entries == 0
238 vector<syncable::Id>* set1 = id_to_conflict_set_[id1];
239 vector<syncable::Id>* set2 = id_to_conflict_set_[id2];
240 vector<syncable::Id>* rv = 0;
241 if (0 == set1 && 0 == set2) {
242 // Neither item currently has a set so we build one.
243 rv = new vector<syncable::Id>();
244 rv->push_back(id1);
245 if (id1 != id2) {
246 rv->push_back(id2);
247 } else {
248 LOG(WARNING) << "[BUG] Attempting to merge two identical conflict ids.";
249 }
250 conflict_sets_.insert(rv);
251 } else if (0 == set1) {
252 // Add the item to the existing set.
253 rv = set2;
254 rv->push_back(id1);
255 } else if (0 == set2) {
256 // Add the item to the existing set.
257 rv = set1;
258 rv->push_back(id2);
259 } else if (set1 == set2) {
260 // It's the same set already.
261 return;
262 } else {
263 // Merge the two sets.
264 rv = set1;
265 // Point all the second sets id's back to the first.
266 vector<syncable::Id>::iterator i;
267 for (i = set2->begin() ; i != set2->end() ; ++i) {
268 id_to_conflict_set_[*i] = rv;
269 }
270 // Copy the second set to the first.
271 rv->insert(rv->end(), set2->begin(), set2->end());
272 conflict_sets_.erase(set2);
273 delete set2;
274 }
275 id_to_conflict_set_[id1] = id_to_conflict_set_[id2] = rv;
276 }
277
CleanupSets()278 void ConflictProgress::CleanupSets() {
279 // Clean up all the sets.
280 set<ConflictSet*>::iterator i;
281 for (i = conflict_sets_.begin(); i != conflict_sets_.end(); i++) {
282 delete *i;
283 }
284 conflict_sets_.clear();
285 id_to_conflict_set_.clear();
286 }
287
UpdateProgress()288 UpdateProgress::UpdateProgress() {}
289
~UpdateProgress()290 UpdateProgress::~UpdateProgress() {}
291
AddVerifyResult(const VerifyResult & verify_result,const sync_pb::SyncEntity & entity)292 void UpdateProgress::AddVerifyResult(const VerifyResult& verify_result,
293 const sync_pb::SyncEntity& entity) {
294 verified_updates_.push_back(std::make_pair(verify_result, entity));
295 }
296
AddAppliedUpdate(const UpdateAttemptResponse & response,const syncable::Id & id)297 void UpdateProgress::AddAppliedUpdate(const UpdateAttemptResponse& response,
298 const syncable::Id& id) {
299 applied_updates_.push_back(std::make_pair(response, id));
300 }
301
AppliedUpdatesBegin()302 std::vector<AppliedUpdate>::iterator UpdateProgress::AppliedUpdatesBegin() {
303 return applied_updates_.begin();
304 }
305
306 std::vector<VerifiedUpdate>::const_iterator
VerifiedUpdatesBegin() const307 UpdateProgress::VerifiedUpdatesBegin() const {
308 return verified_updates_.begin();
309 }
310
311 std::vector<AppliedUpdate>::const_iterator
AppliedUpdatesEnd() const312 UpdateProgress::AppliedUpdatesEnd() const {
313 return applied_updates_.end();
314 }
315
316 std::vector<VerifiedUpdate>::const_iterator
VerifiedUpdatesEnd() const317 UpdateProgress::VerifiedUpdatesEnd() const {
318 return verified_updates_.end();
319 }
320
SuccessfullyAppliedUpdateCount() const321 int UpdateProgress::SuccessfullyAppliedUpdateCount() const {
322 int count = 0;
323 for (std::vector<AppliedUpdate>::const_iterator it =
324 applied_updates_.begin();
325 it != applied_updates_.end();
326 ++it) {
327 if (it->first == SUCCESS)
328 count++;
329 }
330 return count;
331 }
332
333 // Returns true if at least one update application failed due to a conflict
334 // during this sync cycle.
HasConflictingUpdates() const335 bool UpdateProgress::HasConflictingUpdates() const {
336 std::vector<AppliedUpdate>::const_iterator it;
337 for (it = applied_updates_.begin(); it != applied_updates_.end(); ++it) {
338 if (it->first == CONFLICT) {
339 return true;
340 }
341 }
342 return false;
343 }
344
AllModelTypeState(bool * dirty_flag)345 AllModelTypeState::AllModelTypeState(bool* dirty_flag)
346 : unsynced_handles(dirty_flag),
347 syncer_status(dirty_flag),
348 error_counters(dirty_flag),
349 num_server_changes_remaining(dirty_flag, 0),
350 commit_set(ModelSafeRoutingInfo()) {
351 }
352
~AllModelTypeState()353 AllModelTypeState::~AllModelTypeState() {}
354
PerModelSafeGroupState(bool * dirty_flag)355 PerModelSafeGroupState::PerModelSafeGroupState(bool* dirty_flag)
356 : conflict_progress(dirty_flag) {
357 }
358
~PerModelSafeGroupState()359 PerModelSafeGroupState::~PerModelSafeGroupState() {
360 }
361
362 } // namespace sessions
363 } // namespace browser_sync
364