OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/process_updates_util.h" | 5 #include "sync/engine/process_updates_util.h" |
6 | 6 |
7 #include "base/location.h" | 7 #include "base/location.h" |
8 #include "sync/engine/syncer_proto_util.h" | 8 #include "sync/engine/syncer_proto_util.h" |
| 9 #include "sync/engine/syncer_types.h" |
9 #include "sync/engine/syncer_util.h" | 10 #include "sync/engine/syncer_util.h" |
10 #include "sync/syncable/directory.h" | 11 #include "sync/syncable/directory.h" |
11 #include "sync/syncable/model_neutral_mutable_entry.h" | 12 #include "sync/syncable/model_neutral_mutable_entry.h" |
12 #include "sync/syncable/syncable_model_neutral_write_transaction.h" | 13 #include "sync/syncable/syncable_model_neutral_write_transaction.h" |
13 #include "sync/syncable/syncable_proto_util.h" | 14 #include "sync/syncable/syncable_proto_util.h" |
14 #include "sync/syncable/syncable_util.h" | 15 #include "sync/syncable/syncable_util.h" |
15 #include "sync/util/cryptographer.h" | 16 #include "sync/util/cryptographer.h" |
16 | 17 |
17 namespace syncer { | 18 namespace syncer { |
18 | 19 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 // Unique client tags will have their version set to zero when they're | 68 // Unique client tags will have their version set to zero when they're |
68 // deleted. The usual version comparison logic won't be able to detect | 69 // deleted. The usual version comparison logic won't be able to detect |
69 // reflections of these items. Instead, we assume any received tombstones | 70 // reflections of these items. Instead, we assume any received tombstones |
70 // are reflections. That should be correct most of the time. | 71 // are reflections. That should be correct most of the time. |
71 return false; | 72 return false; |
72 } | 73 } |
73 | 74 |
74 return existing_version < update.version(); | 75 return existing_version < update.version(); |
75 } | 76 } |
76 | 77 |
77 } // namespace | |
78 | |
79 void PartitionUpdatesByType( | |
80 const sync_pb::GetUpdatesResponse& updates, | |
81 ModelTypeSet requested_types, | |
82 TypeSyncEntityMap* updates_by_type) { | |
83 int update_count = updates.entries().size(); | |
84 for (ModelTypeSet::Iterator it = requested_types.First(); | |
85 it.Good(); it.Inc()) { | |
86 updates_by_type->insert(std::make_pair(it.Get(), SyncEntityList())); | |
87 } | |
88 for (int i = 0; i < update_count; ++i) { | |
89 const sync_pb::SyncEntity& update = updates.entries(i); | |
90 ModelType type = GetModelType(update); | |
91 if (!IsRealDataType(type)) { | |
92 NOTREACHED() << "Received update with invalid type."; | |
93 continue; | |
94 } | |
95 | |
96 TypeSyncEntityMap::iterator it = updates_by_type->find(type); | |
97 if (it == updates_by_type->end()) { | |
98 DLOG(WARNING) << "Skipping update for unexpected type " | |
99 << ModelTypeToString(type); | |
100 continue; | |
101 } | |
102 | |
103 it->second.push_back(&update); | |
104 } | |
105 } | |
106 | |
107 void ProcessDownloadedUpdates( | |
108 syncable::Directory* dir, | |
109 syncable::ModelNeutralWriteTransaction* trans, | |
110 ModelType type, | |
111 const SyncEntityList& applicable_updates, | |
112 sessions::StatusController* status) { | |
113 for (SyncEntityList::const_iterator update_it = applicable_updates.begin(); | |
114 update_it != applicable_updates.end(); ++update_it) { | |
115 DCHECK_EQ(type, GetModelType(**update_it)); | |
116 if (!UpdateContainsNewVersion(trans, **update_it)) | |
117 status->increment_num_reflected_updates_downloaded_by(1); | |
118 if ((*update_it)->deleted()) | |
119 status->increment_num_tombstone_updates_downloaded_by(1); | |
120 VerifyResult verify_result = VerifyUpdate(trans, **update_it, type); | |
121 if (verify_result != VERIFY_SUCCESS && verify_result != VERIFY_UNDELETE) | |
122 continue; | |
123 ProcessUpdate(**update_it, dir->GetCryptographer(trans), trans); | |
124 } | |
125 } | |
126 | |
127 namespace { | |
128 | |
129 // In the event that IDs match, but tags differ AttemptReuniteClient tag | 78 // In the event that IDs match, but tags differ AttemptReuniteClient tag |
130 // will have refused to unify the update. | 79 // will have refused to unify the update. |
131 // We should not attempt to apply it at all since it violates consistency | 80 // We should not attempt to apply it at all since it violates consistency |
132 // rules. | 81 // rules. |
133 VerifyResult VerifyTagConsistency( | 82 VerifyResult VerifyTagConsistency( |
134 const sync_pb::SyncEntity& entry, | 83 const sync_pb::SyncEntity& entry, |
135 const syncable::ModelNeutralMutableEntry& same_id) { | 84 const syncable::ModelNeutralMutableEntry& same_id) { |
136 if (entry.has_client_defined_unique_tag() && | 85 if (entry.has_client_defined_unique_tag() && |
137 entry.client_defined_unique_tag() != | 86 entry.client_defined_unique_tag() != |
138 same_id.GetUniqueClientTag()) { | 87 same_id.GetUniqueClientTag()) { |
139 return VERIFY_FAIL; | 88 return VERIFY_FAIL; |
140 } | 89 } |
141 return VERIFY_UNDECIDED; | 90 return VERIFY_UNDECIDED; |
142 } | 91 } |
143 | 92 |
144 } // namespace | 93 // Checks whether or not an update is fit for processing. |
145 | 94 // |
| 95 // The answer may be "no" if the update appears invalid, or it's not releveant |
| 96 // (ie. a delete for an item we've never heard of), or other reasons. |
146 VerifyResult VerifyUpdate( | 97 VerifyResult VerifyUpdate( |
147 syncable::ModelNeutralWriteTransaction* trans, | 98 syncable::ModelNeutralWriteTransaction* trans, |
148 const sync_pb::SyncEntity& entry, | 99 const sync_pb::SyncEntity& entry, |
149 ModelType requested_type) { | 100 ModelType requested_type) { |
150 syncable::Id id = SyncableIdFromProto(entry.id_string()); | 101 syncable::Id id = SyncableIdFromProto(entry.id_string()); |
151 VerifyResult result = VERIFY_FAIL; | 102 VerifyResult result = VERIFY_FAIL; |
152 | 103 |
153 const bool deleted = entry.has_deleted() && entry.deleted(); | 104 const bool deleted = entry.has_deleted() && entry.deleted(); |
154 const bool is_directory = IsFolder(entry); | 105 const bool is_directory = IsFolder(entry); |
155 const ModelType model_type = GetModelType(entry); | 106 const ModelType model_type = GetModelType(entry); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 result = VerifyUpdateConsistency(trans, entry, deleted, | 145 result = VerifyUpdateConsistency(trans, entry, deleted, |
195 is_directory, model_type, &same_id); | 146 is_directory, model_type, &same_id); |
196 } | 147 } |
197 | 148 |
198 if (VERIFY_UNDECIDED == result) | 149 if (VERIFY_UNDECIDED == result) |
199 result = VERIFY_SUCCESS; // No news is good news. | 150 result = VERIFY_SUCCESS; // No news is good news. |
200 | 151 |
201 return result; // This might be VERIFY_SUCCESS as well | 152 return result; // This might be VERIFY_SUCCESS as well |
202 } | 153 } |
203 | 154 |
204 namespace { | |
205 // Returns true if the entry is still ok to process. | 155 // Returns true if the entry is still ok to process. |
206 bool ReverifyEntry(syncable::ModelNeutralWriteTransaction* trans, | 156 bool ReverifyEntry(syncable::ModelNeutralWriteTransaction* trans, |
207 const sync_pb::SyncEntity& entry, | 157 const sync_pb::SyncEntity& entry, |
208 syncable::ModelNeutralMutableEntry* same_id) { | 158 syncable::ModelNeutralMutableEntry* same_id) { |
209 | 159 |
210 const bool deleted = entry.has_deleted() && entry.deleted(); | 160 const bool deleted = entry.has_deleted() && entry.deleted(); |
211 const bool is_directory = IsFolder(entry); | 161 const bool is_directory = IsFolder(entry); |
212 const ModelType model_type = GetModelType(entry); | 162 const ModelType model_type = GetModelType(entry); |
213 | 163 |
214 return VERIFY_SUCCESS == VerifyUpdateConsistency(trans, | 164 return VERIFY_SUCCESS == VerifyUpdateConsistency(trans, |
215 entry, | 165 entry, |
216 deleted, | 166 deleted, |
217 is_directory, | 167 is_directory, |
218 model_type, | 168 model_type, |
219 same_id); | 169 same_id); |
220 } | 170 } |
221 } // namespace | |
222 | 171 |
223 // Process a single update. Will avoid touching global state. | 172 // Process a single update. Will avoid touching global state. |
| 173 // |
| 174 // If the update passes a series of checks, this function will copy |
| 175 // the SyncEntity's data into the SERVER side of the syncable::Directory. |
224 void ProcessUpdate( | 176 void ProcessUpdate( |
225 const sync_pb::SyncEntity& update, | 177 const sync_pb::SyncEntity& update, |
226 const Cryptographer* cryptographer, | 178 const Cryptographer* cryptographer, |
227 syncable::ModelNeutralWriteTransaction* const trans) { | 179 syncable::ModelNeutralWriteTransaction* const trans) { |
228 const syncable::Id& server_id = SyncableIdFromProto(update.id_string()); | 180 const syncable::Id& server_id = SyncableIdFromProto(update.id_string()); |
229 const std::string name = SyncerProtoUtil::NameFromSyncEntity(update); | 181 const std::string name = SyncerProtoUtil::NameFromSyncEntity(update); |
230 | 182 |
231 // Look to see if there's a local item that should recieve this update, | 183 // Look to see if there's a local item that should recieve this update, |
232 // maybe due to a duplicate client tag or a lost commit response. | 184 // maybe due to a duplicate client tag or a lost commit response. |
233 syncable::Id local_id = FindLocalIdToUpdate(trans, update); | 185 syncable::Id local_id = FindLocalIdToUpdate(trans, update); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 // changes, so we clear BASE_SERVER_SPECIFICS. | 271 // changes, so we clear BASE_SERVER_SPECIFICS. |
320 target_entry.PutBaseServerSpecifics( | 272 target_entry.PutBaseServerSpecifics( |
321 sync_pb::EntitySpecifics()); | 273 sync_pb::EntitySpecifics()); |
322 } | 274 } |
323 | 275 |
324 UpdateServerFieldsFromUpdate(&target_entry, update, name); | 276 UpdateServerFieldsFromUpdate(&target_entry, update, name); |
325 | 277 |
326 return; | 278 return; |
327 } | 279 } |
328 | 280 |
| 281 } // namespace |
| 282 |
| 283 void ProcessDownloadedUpdates( |
| 284 syncable::Directory* dir, |
| 285 syncable::ModelNeutralWriteTransaction* trans, |
| 286 ModelType type, |
| 287 const SyncEntityList& applicable_updates, |
| 288 sessions::StatusController* status) { |
| 289 for (SyncEntityList::const_iterator update_it = applicable_updates.begin(); |
| 290 update_it != applicable_updates.end(); ++update_it) { |
| 291 DCHECK_EQ(type, GetModelType(**update_it)); |
| 292 if (!UpdateContainsNewVersion(trans, **update_it)) |
| 293 status->increment_num_reflected_updates_downloaded_by(1); |
| 294 if ((*update_it)->deleted()) |
| 295 status->increment_num_tombstone_updates_downloaded_by(1); |
| 296 VerifyResult verify_result = VerifyUpdate(trans, **update_it, type); |
| 297 if (verify_result != VERIFY_SUCCESS && verify_result != VERIFY_UNDELETE) |
| 298 continue; |
| 299 ProcessUpdate(**update_it, dir->GetCryptographer(trans), trans); |
| 300 } |
| 301 } |
| 302 |
329 } // namespace syncer | 303 } // namespace syncer |
OLD | NEW |