- add sources.
[platform/framework/web/crosswalk.git] / src / sync / engine / apply_updates_and_resolve_conflicts_command.cc
1 // Copyright 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 "sync/engine/apply_updates_and_resolve_conflicts_command.h"
6
7 #include "base/location.h"
8 #include "sync/engine/conflict_resolver.h"
9 #include "sync/engine/update_applicator.h"
10 #include "sync/sessions/sync_session.h"
11 #include "sync/syncable/directory.h"
12 #include "sync/syncable/syncable_read_transaction.h"
13 #include "sync/syncable/syncable_write_transaction.h"
14
15 namespace syncer {
16
17 using sessions::SyncSession;
18
19 ApplyUpdatesAndResolveConflictsCommand::
20     ApplyUpdatesAndResolveConflictsCommand() {}
21 ApplyUpdatesAndResolveConflictsCommand::
22     ~ApplyUpdatesAndResolveConflictsCommand() {}
23
24 std::set<ModelSafeGroup>
25 ApplyUpdatesAndResolveConflictsCommand::GetGroupsToChange(
26     const sessions::SyncSession& session) const {
27   std::set<ModelSafeGroup> groups_with_unapplied_updates;
28
29   FullModelTypeSet server_types_with_unapplied_updates;
30   {
31     syncable::Directory* dir = session.context()->directory();
32     syncable::ReadTransaction trans(FROM_HERE, dir);
33     server_types_with_unapplied_updates =
34         dir->GetServerTypesWithUnappliedUpdates(&trans);
35   }
36
37   for (FullModelTypeSet::Iterator it =
38            server_types_with_unapplied_updates.First(); it.Good(); it.Inc()) {
39     groups_with_unapplied_updates.insert(
40         GetGroupForModelType(it.Get(), session.context()->routing_info()));
41   }
42
43   return groups_with_unapplied_updates;
44 }
45
46 SyncerError ApplyUpdatesAndResolveConflictsCommand::ModelChangingExecuteImpl(
47     SyncSession* session) {
48   sessions::StatusController* status = session->mutable_status_controller();
49   syncable::Directory* dir = session->context()->directory();
50   syncable::WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir);
51
52   // Compute server types with unapplied updates that fall under our
53   // group restriction.
54   const FullModelTypeSet server_types_with_unapplied_updates =
55       dir->GetServerTypesWithUnappliedUpdates(&trans);
56   FullModelTypeSet server_type_restriction;
57   for (FullModelTypeSet::Iterator it =
58            server_types_with_unapplied_updates.First(); it.Good(); it.Inc()) {
59     if (GetGroupForModelType(it.Get(), session->context()->routing_info()) ==
60         status->group_restriction()) {
61       server_type_restriction.Put(it.Get());
62     }
63   }
64
65   // Don't process control type updates here.  They will be handled elsewhere.
66   FullModelTypeSet control_types = ToFullModelTypeSet(ControlTypes());
67   server_type_restriction.RemoveAll(control_types);
68
69   std::vector<int64> handles;
70   dir->GetUnappliedUpdateMetaHandles(
71       &trans, server_type_restriction, &handles);
72
73   // First set of update application passes.
74   UpdateApplicator applicator(
75       dir->GetCryptographer(&trans),
76       session->context()->routing_info(),
77       status->group_restriction());
78   applicator.AttemptApplications(&trans, handles);
79   status->increment_num_updates_applied_by(applicator.updates_applied());
80   status->increment_num_hierarchy_conflicts_by(
81       applicator.hierarchy_conflicts());
82   status->increment_num_encryption_conflicts_by(
83       applicator.encryption_conflicts());
84
85   if (applicator.simple_conflict_ids().size() != 0) {
86     // Resolve the simple conflicts we just detected.
87     ConflictResolver resolver;
88     resolver.ResolveConflicts(&trans,
89                               dir->GetCryptographer(&trans),
90                               applicator.simple_conflict_ids(),
91                               status);
92
93     // Conflict resolution sometimes results in more updates to apply.
94     handles.clear();
95     dir->GetUnappliedUpdateMetaHandles(
96         &trans, server_type_restriction, &handles);
97
98     UpdateApplicator conflict_applicator(
99         dir->GetCryptographer(&trans),
100         session->context()->routing_info(),
101         status->group_restriction());
102     conflict_applicator.AttemptApplications(&trans, handles);
103
104     // We count the number of updates from both applicator passes.
105     status->increment_num_updates_applied_by(
106         conflict_applicator.updates_applied());
107
108     // Encryption conflicts should remain unchanged by the resolution of simple
109     // conflicts.  Those can only be solved by updating our nigori key bag.
110     DCHECK_EQ(conflict_applicator.encryption_conflicts(),
111               applicator.encryption_conflicts());
112
113     // Hierarchy conflicts should also remain unchanged, for reasons that are
114     // more subtle.  Hierarchy conflicts exist when the application of a pending
115     // update from the server would make the local folder hierarchy
116     // inconsistent.  The resolution of simple conflicts could never affect the
117     // hierarchy conflicting item directly, because hierarchy conflicts are not
118     // processed by the conflict resolver.  It could, in theory, modify the
119     // local hierarchy on which hierarchy conflict detection depends.  However,
120     // the conflict resolution algorithm currently in use does not allow this.
121     DCHECK_EQ(conflict_applicator.hierarchy_conflicts(),
122               applicator.hierarchy_conflicts());
123
124     // There should be no simple conflicts remaining.  We know this because the
125     // resolver should have resolved all the conflicts we detected last time
126     // and, by the two previous assertions, that no conflicts have been
127     // downgraded from encryption or hierarchy down to simple.
128     DCHECK(conflict_applicator.simple_conflict_ids().empty());
129   }
130
131   return SYNCER_OK;
132 }
133
134 }  // namespace syncer