Index: sync/engine/sync_directory_update_handler.cc |
diff --git a/sync/engine/sync_directory_update_handler.cc b/sync/engine/sync_directory_update_handler.cc |
index 0d7953bb483dd1f4907fe59780fe05cb4c0847fa..f7046d8caa9f180bc0b5861105910fbe4c3fdd99 100644 |
--- a/sync/engine/sync_directory_update_handler.cc |
+++ b/sync/engine/sync_directory_update_handler.cc |
@@ -4,19 +4,25 @@ |
#include "sync/engine/sync_directory_update_handler.h" |
+#include "sync/engine/conflict_resolver.h" |
#include "sync/engine/process_updates_util.h" |
+#include "sync/engine/update_applicator.h" |
#include "sync/sessions/status_controller.h" |
#include "sync/syncable/directory.h" |
#include "sync/syncable/syncable_model_neutral_write_transaction.h" |
+#include "sync/syncable/syncable_write_transaction.h" |
namespace syncer { |
using syncable::SYNCER; |
SyncDirectoryUpdateHandler::SyncDirectoryUpdateHandler( |
- syncable::Directory* dir, ModelType type) |
+ syncable::Directory* dir, |
+ ModelType type, |
+ scoped_refptr<ModelSafeWorker> worker) |
: dir_(dir), |
- type_(type) {} |
+ type_(type), |
+ worker_(worker) {} |
SyncDirectoryUpdateHandler::~SyncDirectoryUpdateHandler() {} |
@@ -34,6 +40,92 @@ void SyncDirectoryUpdateHandler::ProcessGetUpdatesResponse( |
UpdateProgressMarker(progress_marker); |
} |
+void SyncDirectoryUpdateHandler::ApplyUpdates( |
+ sessions::StatusController* status) { |
+ if (IsControlType(type_)) { |
+ return; // We don't process control types here. |
Nicolas Zea
2013/11/19 22:45:26
What's the plan for control types? Do they not hav
rlarocque
2013/11/21 18:28:47
No, they do have SyncDirectoryUpdateHandlers. Tha
|
+ } |
+ |
+ if (!dir_->TypeHasUnappliedUpdates(type_)) { |
+ return; // No work to do. Skip this type. |
+ } |
+ |
+ WorkCallback c = base::Bind( |
+ &SyncDirectoryUpdateHandler::ApplyUpdatesImpl, |
+ // We wait until the callback is executed. So it is safe to use |
+ // unretained. |
+ base::Unretained(this), |
+ base::Unretained(status)); |
+ worker_->DoWorkAndWaitUntilDone(c); |
+} |
+ |
+SyncerError SyncDirectoryUpdateHandler::ApplyUpdatesImpl( |
+ sessions::StatusController* status) { |
+ syncable::WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir_); |
+ |
+ std::vector<int64> handles; |
+ dir_->GetUnappliedUpdateMetaHandles( |
+ &trans, |
+ FullModelTypeSet(type_), |
+ &handles); |
+ |
+ // First set of update application passes. |
+ UpdateApplicator applicator(dir_->GetCryptographer(&trans)); |
+ applicator.AttemptApplications(&trans, handles); |
+ status->increment_num_updates_applied_by(applicator.updates_applied()); |
+ status->increment_num_hierarchy_conflicts_by( |
+ applicator.hierarchy_conflicts()); |
+ status->increment_num_encryption_conflicts_by( |
+ applicator.encryption_conflicts()); |
+ |
+ if (applicator.simple_conflict_ids().size() != 0) { |
+ // Resolve the simple conflicts we just detected. |
+ ConflictResolver resolver; |
+ resolver.ResolveConflicts(&trans, |
+ dir_->GetCryptographer(&trans), |
+ applicator.simple_conflict_ids(), |
+ status); |
+ |
+ // Conflict resolution sometimes results in more updates to apply. |
+ handles.clear(); |
+ dir_->GetUnappliedUpdateMetaHandles( |
+ &trans, |
+ FullModelTypeSet(type_), |
+ &handles); |
+ |
+ UpdateApplicator conflict_applicator(dir_->GetCryptographer(&trans)); |
+ conflict_applicator.AttemptApplications(&trans, handles); |
+ |
+ // We count the number of updates from both applicator passes. |
+ status->increment_num_updates_applied_by( |
+ conflict_applicator.updates_applied()); |
+ |
+ // Encryption conflicts should remain unchanged by the resolution of simple |
+ // conflicts. Those can only be solved by updating our nigori key bag. |
+ DCHECK_EQ(conflict_applicator.encryption_conflicts(), |
+ applicator.encryption_conflicts()); |
+ |
+ // Hierarchy conflicts should also remain unchanged, for reasons that are |
+ // more subtle. Hierarchy conflicts exist when the application of a pending |
+ // update from the server would make the local folder hierarchy |
+ // inconsistent. The resolution of simple conflicts could never affect the |
+ // hierarchy conflicting item directly, because hierarchy conflicts are not |
+ // processed by the conflict resolver. It could, in theory, modify the |
+ // local hierarchy on which hierarchy conflict detection depends. However, |
+ // the conflict resolution algorithm currently in use does not allow this. |
+ DCHECK_EQ(conflict_applicator.hierarchy_conflicts(), |
+ applicator.hierarchy_conflicts()); |
+ |
+ // There should be no simple conflicts remaining. We know this because the |
+ // resolver should have resolved all the conflicts we detected last time |
+ // and, by the two previous assertions, that no conflicts have been |
+ // downgraded from encryption or hierarchy down to simple. |
+ DCHECK(conflict_applicator.simple_conflict_ids().empty()); |
+ } |
+ |
+ return SYNCER_OK; |
+} |
+ |
void SyncDirectoryUpdateHandler::UpdateSyncEntities( |
syncable::ModelNeutralWriteTransaction* trans, |
const SyncEntityList& applicable_updates, |