| 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 |