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