Home | History | Annotate | Download | only in sessions
      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 
     23 SyncSourceInfo::SyncSourceInfo()
     24     : updates_source(sync_pb::GetUpdatesCallerInfo::UNKNOWN) {}
     25 
     26 SyncSourceInfo::SyncSourceInfo(
     27     const syncable::ModelTypePayloadMap& t)
     28     : updates_source(sync_pb::GetUpdatesCallerInfo::UNKNOWN), types(t) {}
     29 
     30 SyncSourceInfo::SyncSourceInfo(
     31     const sync_pb::GetUpdatesCallerInfo::GetUpdatesSource& u,
     32     const syncable::ModelTypePayloadMap& t)
     33     : updates_source(u), types(t) {}
     34 
     35 SyncSourceInfo::~SyncSourceInfo() {}
     36 
     37 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 
     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 
     55 SyncerStatus::~SyncerStatus() {
     56 }
     57 
     58 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 
     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 
     91 ErrorCounters::ErrorCounters()
     92     : num_conflicting_commits(0),
     93       consecutive_transient_error_commits(0),
     94       consecutive_errors(0) {
     95 }
     96 
     97 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 
    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 
    139 SyncSessionSnapshot::~SyncSessionSnapshot() {}
    140 
    141 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 
    164 ConflictProgress::ConflictProgress(bool* dirty_flag) : dirty_(dirty_flag) {}
    165 
    166 ConflictProgress::~ConflictProgress() {
    167   CleanupSets();
    168 }
    169 
    170 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
    176 ConflictProgress::IdToConflictSetBegin() const {
    177   return id_to_conflict_set_.begin();
    178 }
    179 
    180 IdToConflictSetMap::const_iterator
    181 ConflictProgress::IdToConflictSetEnd() const {
    182   return id_to_conflict_set_.end();
    183 }
    184 
    185 IdToConflictSetMap::size_type ConflictProgress::IdToConflictSetSize() const {
    186   return id_to_conflict_set_.size();
    187 }
    188 
    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
    195 ConflictProgress::ConflictSetsBegin() const {
    196   return conflict_sets_.begin();
    197 }
    198 
    199 std::set<ConflictSet*>::const_iterator
    200 ConflictProgress::ConflictSetsEnd() const {
    201   return conflict_sets_.end();
    202 }
    203 
    204 std::set<ConflictSet*>::size_type
    205 ConflictProgress::ConflictSetsSize() const {
    206   return conflict_sets_.size();
    207 }
    208 
    209 std::set<syncable::Id>::iterator
    210 ConflictProgress::ConflictingItemsBegin() {
    211   return conflicting_item_ids_.begin();
    212 }
    213 std::set<syncable::Id>::const_iterator
    214 ConflictProgress::ConflictingItemsBeginConst() const {
    215   return conflicting_item_ids_.begin();
    216 }
    217 std::set<syncable::Id>::const_iterator
    218 ConflictProgress::ConflictingItemsEnd() const {
    219   return conflicting_item_ids_.end();
    220 }
    221 
    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 
    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 
    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 
    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 
    288 UpdateProgress::UpdateProgress() {}
    289 
    290 UpdateProgress::~UpdateProgress() {}
    291 
    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 
    297 void UpdateProgress::AddAppliedUpdate(const UpdateAttemptResponse& response,
    298     const syncable::Id& id) {
    299   applied_updates_.push_back(std::make_pair(response, id));
    300 }
    301 
    302 std::vector<AppliedUpdate>::iterator UpdateProgress::AppliedUpdatesBegin() {
    303   return applied_updates_.begin();
    304 }
    305 
    306 std::vector<VerifiedUpdate>::const_iterator
    307 UpdateProgress::VerifiedUpdatesBegin() const {
    308   return verified_updates_.begin();
    309 }
    310 
    311 std::vector<AppliedUpdate>::const_iterator
    312 UpdateProgress::AppliedUpdatesEnd() const {
    313   return applied_updates_.end();
    314 }
    315 
    316 std::vector<VerifiedUpdate>::const_iterator
    317 UpdateProgress::VerifiedUpdatesEnd() const {
    318   return verified_updates_.end();
    319 }
    320 
    321 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.
    335 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 
    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 
    353 AllModelTypeState::~AllModelTypeState() {}
    354 
    355 PerModelSafeGroupState::PerModelSafeGroupState(bool* dirty_flag)
    356     : conflict_progress(dirty_flag) {
    357 }
    358 
    359 PerModelSafeGroupState::~PerModelSafeGroupState() {
    360 }
    361 
    362 }  // namespace sessions
    363 }  // namespace browser_sync
    364