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/engine/update_applicator.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/logging.h" | |
10 #include "chrome/browser/sync/engine/syncer_util.h" | |
11 #include "chrome/browser/sync/sessions/session_state.h" | |
12 #include "chrome/browser/sync/syncable/syncable.h" | |
13 #include "chrome/browser/sync/syncable/syncable_id.h" | |
14 | |
15 using std::vector; | |
16 | |
17 namespace browser_sync { | |
18 | |
19 UpdateApplicator::UpdateApplicator(ConflictResolver* resolver, | |
20 Cryptographer* cryptographer, | |
21 const UpdateIterator& begin, | |
22 const UpdateIterator& end, | |
23 const ModelSafeRoutingInfo& routes, | |
24 ModelSafeGroup group_filter) | |
25 : resolver_(resolver), | |
26 cryptographer_(cryptographer), | |
27 begin_(begin), | |
28 end_(end), | |
29 pointer_(begin), | |
30 group_filter_(group_filter), | |
31 progress_(false), | |
32 routing_info_(routes), | |
33 application_results_(end - begin) { | |
34 size_t item_count = end - begin; | |
35 DVLOG(1) << "UpdateApplicator created for " << item_count << " items."; | |
36 } | |
37 | |
38 UpdateApplicator::~UpdateApplicator() { | |
39 } | |
40 | |
41 // Returns true if there's more to do. | |
42 bool UpdateApplicator::AttemptOneApplication( | |
43 syncable::WriteTransaction* trans) { | |
44 // If there are no updates left to consider, we're done. | |
45 if (end_ == begin_) | |
46 return false; | |
47 if (pointer_ == end_) { | |
48 if (!progress_) | |
49 return false; | |
50 | |
51 DVLOG(1) << "UpdateApplicator doing additional pass."; | |
52 pointer_ = begin_; | |
53 progress_ = false; | |
54 | |
55 // Clear the tracked failures to avoid double-counting. | |
56 application_results_.ClearConflicts(); | |
57 } | |
58 | |
59 syncable::Entry read_only(trans, syncable::GET_BY_HANDLE, *pointer_); | |
60 if (SkipUpdate(read_only)) { | |
61 Advance(); | |
62 return true; | |
63 } | |
64 | |
65 syncable::MutableEntry entry(trans, syncable::GET_BY_HANDLE, *pointer_); | |
66 UpdateAttemptResponse updateResponse = SyncerUtil::AttemptToUpdateEntry( | |
67 trans, &entry, resolver_, cryptographer_); | |
68 switch (updateResponse) { | |
69 case SUCCESS: | |
70 Advance(); | |
71 progress_ = true; | |
72 application_results_.AddSuccess(entry.Get(syncable::ID)); | |
73 break; | |
74 case CONFLICT_SIMPLE: | |
75 pointer_++; | |
76 application_results_.AddSimpleConflict(entry.Get(syncable::ID)); | |
77 break; | |
78 case CONFLICT_ENCRYPTION: | |
79 pointer_++; | |
80 application_results_.AddEncryptionConflict(entry.Get(syncable::ID)); | |
81 break; | |
82 case CONFLICT_HIERARCHY: | |
83 pointer_++; | |
84 application_results_.AddHierarchyConflict(entry.Get(syncable::ID)); | |
85 break; | |
86 default: | |
87 NOTREACHED(); | |
88 break; | |
89 } | |
90 DVLOG(1) << "Apply Status for " << entry.Get(syncable::META_HANDLE) | |
91 << " is " << updateResponse; | |
92 | |
93 return true; | |
94 } | |
95 | |
96 void UpdateApplicator::Advance() { | |
97 --end_; | |
98 *pointer_ = *end_; | |
99 } | |
100 | |
101 bool UpdateApplicator::SkipUpdate(const syncable::Entry& entry) { | |
102 syncable::ModelType type = entry.GetServerModelType(); | |
103 ModelSafeGroup g = GetGroupForModelType(type, routing_info_); | |
104 // The set of updates passed to the UpdateApplicator should already | |
105 // be group-filtered. | |
106 if (g != group_filter_) { | |
107 NOTREACHED(); | |
108 return true; | |
109 } | |
110 if (g == GROUP_PASSIVE && | |
111 !routing_info_.count(type) && | |
112 type != syncable::UNSPECIFIED && | |
113 type != syncable::TOP_LEVEL_FOLDER) { | |
114 DVLOG(1) << "Skipping update application, type not permitted."; | |
115 return true; | |
116 } | |
117 return false; | |
118 } | |
119 | |
120 bool UpdateApplicator::AllUpdatesApplied() const { | |
121 return application_results_.no_conflicts() && begin_ == end_; | |
122 } | |
123 | |
124 void UpdateApplicator::SaveProgressIntoSessionState( | |
125 sessions::ConflictProgress* conflict_progress, | |
126 sessions::UpdateProgress* update_progress) { | |
127 DCHECK(begin_ == end_ || ((pointer_ == end_) && !progress_)) | |
128 << "SaveProgress called before updates exhausted."; | |
129 | |
130 application_results_.SaveProgress(conflict_progress, update_progress); | |
131 } | |
132 | |
133 UpdateApplicator::ResultTracker::ResultTracker(size_t num_results) { | |
134 successful_ids_.reserve(num_results); | |
135 } | |
136 | |
137 UpdateApplicator::ResultTracker::~ResultTracker() { | |
138 } | |
139 | |
140 void UpdateApplicator::ResultTracker::AddSimpleConflict(syncable::Id id) { | |
141 conflicting_ids_.push_back(id); | |
142 } | |
143 | |
144 void UpdateApplicator::ResultTracker::AddEncryptionConflict(syncable::Id id) { | |
145 encryption_conflict_ids_.push_back(id); | |
146 } | |
147 | |
148 void UpdateApplicator::ResultTracker::AddHierarchyConflict(syncable::Id id) { | |
149 hierarchy_conflict_ids_.push_back(id); | |
150 } | |
151 | |
152 void UpdateApplicator::ResultTracker::AddSuccess(syncable::Id id) { | |
153 successful_ids_.push_back(id); | |
154 } | |
155 | |
156 void UpdateApplicator::ResultTracker::SaveProgress( | |
157 sessions::ConflictProgress* conflict_progress, | |
158 sessions::UpdateProgress* update_progress) { | |
159 vector<syncable::Id>::const_iterator i; | |
160 for (i = conflicting_ids_.begin(); i != conflicting_ids_.end(); ++i) { | |
161 conflict_progress->AddSimpleConflictingItemById(*i); | |
162 update_progress->AddAppliedUpdate(CONFLICT_SIMPLE, *i); | |
163 } | |
164 for (i = encryption_conflict_ids_.begin(); | |
165 i != encryption_conflict_ids_.end(); ++i) { | |
166 conflict_progress->AddEncryptionConflictingItemById(*i); | |
167 update_progress->AddAppliedUpdate(CONFLICT_ENCRYPTION, *i); | |
168 } | |
169 for (i = hierarchy_conflict_ids_.begin(); | |
170 i != hierarchy_conflict_ids_.end(); ++i) { | |
171 conflict_progress->AddHierarchyConflictingItemById(*i); | |
172 update_progress->AddAppliedUpdate(CONFLICT_HIERARCHY, *i); | |
173 } | |
174 for (i = successful_ids_.begin(); i != successful_ids_.end(); ++i) { | |
175 conflict_progress->EraseSimpleConflictingItemById(*i); | |
176 update_progress->AddAppliedUpdate(SUCCESS, *i); | |
177 } | |
178 } | |
179 | |
180 void UpdateApplicator::ResultTracker::ClearConflicts() { | |
181 conflicting_ids_.clear(); | |
182 encryption_conflict_ids_.clear(); | |
183 hierarchy_conflict_ids_.clear(); | |
184 } | |
185 | |
186 bool UpdateApplicator::ResultTracker::no_conflicts() const { | |
187 return conflicting_ids_.empty(); | |
188 } | |
189 | |
190 } // namespace browser_sync | |
OLD | NEW |