OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sync/engine/update_applicator.h" | 5 #include "sync/engine/update_applicator.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "sync/engine/syncer_util.h" | 10 #include "sync/engine/syncer_util.h" |
11 #include "sync/sessions/session_state.h" | |
12 #include "sync/syncable/entry.h" | 11 #include "sync/syncable/entry.h" |
13 #include "sync/syncable/mutable_entry.h" | 12 #include "sync/syncable/mutable_entry.h" |
14 #include "sync/syncable/syncable_id.h" | 13 #include "sync/syncable/syncable_id.h" |
15 #include "sync/syncable/write_transaction.h" | 14 #include "sync/syncable/write_transaction.h" |
16 | 15 |
17 using std::vector; | 16 using std::vector; |
18 | 17 |
19 namespace syncer { | 18 namespace syncer { |
20 | 19 |
21 using syncable::ID; | 20 using syncable::ID; |
22 | 21 |
23 UpdateApplicator::UpdateApplicator(Cryptographer* cryptographer, | 22 UpdateApplicator::UpdateApplicator(Cryptographer* cryptographer, |
24 const ModelSafeRoutingInfo& routes, | 23 const ModelSafeRoutingInfo& routes, |
25 ModelSafeGroup group_filter) | 24 ModelSafeGroup group_filter) |
26 : cryptographer_(cryptographer), | 25 : cryptographer_(cryptographer), |
27 group_filter_(group_filter), | 26 group_filter_(group_filter), |
28 routing_info_(routes) { | 27 routing_info_(routes), |
| 28 updates_applied_(0), |
| 29 encryption_conflicts_(0), |
| 30 hierarchy_conflicts_(0) { |
29 } | 31 } |
30 | 32 |
31 UpdateApplicator::~UpdateApplicator() { | 33 UpdateApplicator::~UpdateApplicator() { |
32 } | 34 } |
33 | 35 |
34 // Attempt to apply all updates, using multiple passes if necessary. | 36 // Attempt to apply all updates, using multiple passes if necessary. |
35 // | 37 // |
36 // Some updates must be applied in order. For example, children must be created | 38 // Some updates must be applied in order. For example, children must be created |
37 // after their parent folder is created. This function runs an O(n^2) algorithm | 39 // after their parent folder is created. This function runs an O(n^2) algorithm |
38 // that will keep trying until there is nothing left to apply, or it stops | 40 // that will keep trying until there is nothing left to apply, or it stops |
39 // making progress, which would indicate that the hierarchy is invalid. | 41 // making progress, which would indicate that the hierarchy is invalid. |
40 // | 42 // |
41 // The update applicator also has to deal with simple conflicts, which occur | 43 // The update applicator also has to deal with simple conflicts, which occur |
42 // when an item is modified on both the server and the local model, and | 44 // when an item is modified on both the server and the local model. We remember |
43 // encryption conflicts. There's not much we can do about them here, so we | 45 // their IDs so they can be passed to the conflict resolver after all the other |
44 // don't bother re-processing them on subsequent passes. | 46 // applications are complete. |
| 47 // |
| 48 // Finally, there are encryption conflicts, which can occur when we don't have |
| 49 // access to all the Nigori keys. There's nothing we can do about them here. |
45 void UpdateApplicator::AttemptApplications( | 50 void UpdateApplicator::AttemptApplications( |
46 syncable::WriteTransaction* trans, | 51 syncable::WriteTransaction* trans, |
47 const std::vector<int64>& handles, | 52 const std::vector<int64>& handles) { |
48 sessions::StatusController* status) { | |
49 std::vector<int64> to_apply = handles; | 53 std::vector<int64> to_apply = handles; |
50 std::set<syncable::Id>* simple_conflict_ids = | |
51 status->mutable_simple_conflict_ids(); | |
52 | 54 |
53 DVLOG(1) << "UpdateApplicator running over " << to_apply.size() << " items."; | 55 DVLOG(1) << "UpdateApplicator running over " << to_apply.size() << " items."; |
54 while (!to_apply.empty()) { | 56 while (!to_apply.empty()) { |
55 std::vector<int64> to_reapply; | 57 std::vector<int64> to_reapply; |
56 | 58 |
57 for (UpdateIterator i = to_apply.begin(); i != to_apply.end(); ++i) { | 59 for (std::vector<int64>::iterator i = to_apply.begin(); |
| 60 i != to_apply.end(); ++i) { |
58 syncable::Entry read_entry(trans, syncable::GET_BY_HANDLE, *i); | 61 syncable::Entry read_entry(trans, syncable::GET_BY_HANDLE, *i); |
59 if (SkipUpdate(read_entry)) { | 62 if (SkipUpdate(read_entry)) { |
60 continue; | 63 continue; |
61 } | 64 } |
62 | 65 |
63 syncable::MutableEntry entry(trans, syncable::GET_BY_HANDLE, *i); | 66 syncable::MutableEntry entry(trans, syncable::GET_BY_HANDLE, *i); |
64 UpdateAttemptResponse result = AttemptToUpdateEntry( | 67 UpdateAttemptResponse result = AttemptToUpdateEntry( |
65 trans, &entry, cryptographer_); | 68 trans, &entry, cryptographer_); |
66 | 69 |
67 switch (result) { | 70 switch (result) { |
68 case SUCCESS: | 71 case SUCCESS: |
69 status->increment_num_updates_applied(); | 72 updates_applied_++; |
70 break; | 73 break; |
71 case CONFLICT_SIMPLE: | 74 case CONFLICT_SIMPLE: |
72 simple_conflict_ids->insert(entry.Get(ID)); | 75 simple_conflict_ids_.insert(entry.Get(ID)); |
73 break; | 76 break; |
74 case CONFLICT_ENCRYPTION: | 77 case CONFLICT_ENCRYPTION: |
75 status->increment_num_encryption_conflicts(); | 78 encryption_conflicts_++; |
76 break; | 79 break; |
77 case CONFLICT_HIERARCHY: | 80 case CONFLICT_HIERARCHY: |
78 // The decision to classify these as hierarchy conflcits is tentative. | 81 // The decision to classify these as hierarchy conflcits is tentative. |
79 // If we make any progress this round, we'll clear the hierarchy | 82 // If we make any progress this round, we'll clear the hierarchy |
80 // conflict count and attempt to reapply these updates. | 83 // conflict count and attempt to reapply these updates. |
81 to_reapply.push_back(*i); | 84 to_reapply.push_back(*i); |
82 break; | 85 break; |
83 default: | 86 default: |
84 NOTREACHED(); | 87 NOTREACHED(); |
85 break; | 88 break; |
86 } | 89 } |
87 } | 90 } |
88 | 91 |
89 if (to_reapply.size() == to_apply.size()) { | 92 if (to_reapply.size() == to_apply.size()) { |
90 // We made no progress. Must be stubborn hierarchy conflicts. | 93 // We made no progress. Must be stubborn hierarchy conflicts. |
91 status->set_num_hierarchy_conflicts(to_apply.size()); | 94 hierarchy_conflicts_ = to_apply.size(); |
92 break; | 95 break; |
93 } | 96 } |
94 | 97 |
95 // We made some progress, so prepare for what might be another iteration. | 98 // We made some progress, so prepare for what might be another iteration. |
96 // If everything went well, to_reapply will be empty and we'll break out on | 99 // If everything went well, to_reapply will be empty and we'll break out on |
97 // the while condition. | 100 // the while condition. |
98 to_apply.swap(to_reapply); | 101 to_apply.swap(to_reapply); |
99 to_reapply.clear(); | 102 to_reapply.clear(); |
100 } | 103 } |
101 } | 104 } |
(...skipping 11 matching lines...) Expand all Loading... |
113 !routing_info_.count(type) && | 116 !routing_info_.count(type) && |
114 type != UNSPECIFIED && | 117 type != UNSPECIFIED && |
115 type != TOP_LEVEL_FOLDER) { | 118 type != TOP_LEVEL_FOLDER) { |
116 DVLOG(1) << "Skipping update application, type not permitted."; | 119 DVLOG(1) << "Skipping update application, type not permitted."; |
117 return true; | 120 return true; |
118 } | 121 } |
119 return false; | 122 return false; |
120 } | 123 } |
121 | 124 |
122 } // namespace syncer | 125 } // namespace syncer |
OLD | NEW |