• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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