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/syncable/directory.h" | 5 #include "components/sync/syncable/directory.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <iterator> | 11 #include <iterator> |
12 #include <utility> | 12 #include <utility> |
13 | 13 |
14 #include "base/base64.h" | 14 #include "base/base64.h" |
15 #include "base/guid.h" | 15 #include "base/guid.h" |
16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
18 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
19 #include "base/trace_event/trace_event.h" | 19 #include "base/trace_event/trace_event.h" |
20 #include "sync/internal_api/public/base/attachment_id_proto.h" | 20 #include "components/sync/base/attachment_id_proto.h" |
21 #include "sync/internal_api/public/base/unique_position.h" | 21 #include "components/sync/base/unique_position.h" |
22 #include "sync/internal_api/public/util/unrecoverable_error_handler.h" | 22 #include "components/sync/base/unrecoverable_error_handler.h" |
23 #include "sync/syncable/entry.h" | 23 #include "components/sync/syncable/entry.h" |
24 #include "sync/syncable/entry_kernel.h" | 24 #include "components/sync/syncable/entry_kernel.h" |
25 #include "sync/syncable/in_memory_directory_backing_store.h" | 25 #include "components/sync/syncable/in_memory_directory_backing_store.h" |
26 #include "sync/syncable/model_neutral_mutable_entry.h" | 26 #include "components/sync/syncable/model_neutral_mutable_entry.h" |
27 #include "sync/syncable/on_disk_directory_backing_store.h" | 27 #include "components/sync/syncable/on_disk_directory_backing_store.h" |
28 #include "sync/syncable/scoped_kernel_lock.h" | 28 #include "components/sync/syncable/scoped_kernel_lock.h" |
29 #include "sync/syncable/scoped_parent_child_index_updater.h" | 29 #include "components/sync/syncable/scoped_parent_child_index_updater.h" |
30 #include "sync/syncable/syncable-inl.h" | 30 #include "components/sync/syncable/syncable-inl.h" |
31 #include "sync/syncable/syncable_base_transaction.h" | 31 #include "components/sync/syncable/syncable_base_transaction.h" |
32 #include "sync/syncable/syncable_changes_version.h" | 32 #include "components/sync/syncable/syncable_changes_version.h" |
33 #include "sync/syncable/syncable_read_transaction.h" | 33 #include "components/sync/syncable/syncable_read_transaction.h" |
34 #include "sync/syncable/syncable_util.h" | 34 #include "components/sync/syncable/syncable_util.h" |
35 #include "sync/syncable/syncable_write_transaction.h" | 35 #include "components/sync/syncable/syncable_write_transaction.h" |
36 | 36 |
37 using std::string; | 37 using std::string; |
38 | 38 |
39 namespace syncer { | 39 namespace syncer { |
40 namespace syncable { | 40 namespace syncable { |
41 | 41 |
42 // static | 42 // static |
43 const base::FilePath::CharType Directory::kSyncDatabaseFilename[] = | 43 const base::FilePath::CharType Directory::kSyncDatabaseFilename[] = |
44 FILE_PATH_LITERAL("SyncData.sqlite3"); | 44 FILE_PATH_LITERAL("SyncData.sqlite3"); |
45 | 45 |
(...skipping 20 matching lines...) Expand all Loading... |
66 } | 66 } |
67 | 67 |
68 bool Directory::PersistedKernelInfo::HasEmptyDownloadProgress( | 68 bool Directory::PersistedKernelInfo::HasEmptyDownloadProgress( |
69 ModelType model_type) { | 69 ModelType model_type) { |
70 const sync_pb::DataTypeProgressMarker& progress_marker = | 70 const sync_pb::DataTypeProgressMarker& progress_marker = |
71 download_progress[model_type]; | 71 download_progress[model_type]; |
72 return progress_marker.token().empty(); | 72 return progress_marker.token().empty(); |
73 } | 73 } |
74 | 74 |
75 Directory::SaveChangesSnapshot::SaveChangesSnapshot() | 75 Directory::SaveChangesSnapshot::SaveChangesSnapshot() |
76 : kernel_info_status(KERNEL_SHARE_INFO_INVALID) { | 76 : kernel_info_status(KERNEL_SHARE_INFO_INVALID) {} |
77 } | |
78 | 77 |
79 Directory::SaveChangesSnapshot::~SaveChangesSnapshot() { | 78 Directory::SaveChangesSnapshot::~SaveChangesSnapshot() { |
80 STLDeleteElements(&dirty_metas); | 79 STLDeleteElements(&dirty_metas); |
81 STLDeleteElements(&delete_journals); | 80 STLDeleteElements(&delete_journals); |
82 } | 81 } |
83 | 82 |
84 bool Directory::SaveChangesSnapshot::HasUnsavedMetahandleChanges() const { | 83 bool Directory::SaveChangesSnapshot::HasUnsavedMetahandleChanges() const { |
85 return !dirty_metas.empty() || !metahandles_to_purge.empty() || | 84 return !dirty_metas.empty() || !metahandles_to_purge.empty() || |
86 !delete_journals.empty() || !delete_journals_to_purge.empty(); | 85 !delete_journals.empty() || !delete_journals_to_purge.empty(); |
87 } | 86 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 Directory::~Directory() { | 126 Directory::~Directory() { |
128 Close(); | 127 Close(); |
129 } | 128 } |
130 | 129 |
131 DirOpenResult Directory::Open( | 130 DirOpenResult Directory::Open( |
132 const string& name, | 131 const string& name, |
133 DirectoryChangeDelegate* delegate, | 132 DirectoryChangeDelegate* delegate, |
134 const WeakHandle<TransactionObserver>& transaction_observer) { | 133 const WeakHandle<TransactionObserver>& transaction_observer) { |
135 TRACE_EVENT0("sync", "SyncDatabaseOpen"); | 134 TRACE_EVENT0("sync", "SyncDatabaseOpen"); |
136 | 135 |
137 const DirOpenResult result = | 136 const DirOpenResult result = OpenImpl(name, delegate, transaction_observer); |
138 OpenImpl(name, delegate, transaction_observer); | |
139 | 137 |
140 if (OPENED != result) | 138 if (OPENED != result) |
141 Close(); | 139 Close(); |
142 return result; | 140 return result; |
143 } | 141 } |
144 | 142 |
145 void Directory::InitializeIndices(MetahandlesMap* handles_map) { | 143 void Directory::InitializeIndices(MetahandlesMap* handles_map) { |
146 ScopedKernelLock lock(this); | 144 ScopedKernelLock lock(this); |
147 kernel_->metahandles_map.swap(*handles_map); | 145 kernel_->metahandles_map.swap(*handles_map); |
148 for (MetahandlesMap::const_iterator it = kernel_->metahandles_map.begin(); | 146 for (MetahandlesMap::const_iterator it = kernel_->metahandles_map.begin(); |
(...skipping 14 matching lines...) Expand all Loading... |
163 << "Unexpected duplicate use of client tag"; | 161 << "Unexpected duplicate use of client tag"; |
164 kernel_->server_tags_map[entry->ref(UNIQUE_SERVER_TAG)] = entry; | 162 kernel_->server_tags_map[entry->ref(UNIQUE_SERVER_TAG)] = entry; |
165 } | 163 } |
166 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { | 164 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { |
167 DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == | 165 DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == |
168 kernel_->server_tags_map.end()) | 166 kernel_->server_tags_map.end()) |
169 << "Unexpected duplicate use of server tag"; | 167 << "Unexpected duplicate use of server tag"; |
170 kernel_->client_tags_map[entry->ref(UNIQUE_CLIENT_TAG)] = entry; | 168 kernel_->client_tags_map[entry->ref(UNIQUE_CLIENT_TAG)] = entry; |
171 } | 169 } |
172 DCHECK(kernel_->ids_map.find(entry->ref(ID).value()) == | 170 DCHECK(kernel_->ids_map.find(entry->ref(ID).value()) == |
173 kernel_->ids_map.end()) << "Unexpected duplicate use of ID"; | 171 kernel_->ids_map.end()) |
| 172 << "Unexpected duplicate use of ID"; |
174 kernel_->ids_map[entry->ref(ID).value()] = entry; | 173 kernel_->ids_map[entry->ref(ID).value()] = entry; |
175 DCHECK(!entry->is_dirty()); | 174 DCHECK(!entry->is_dirty()); |
176 AddToAttachmentIndex(lock, metahandle, entry->ref(ATTACHMENT_METADATA)); | 175 AddToAttachmentIndex(lock, metahandle, entry->ref(ATTACHMENT_METADATA)); |
177 } | 176 } |
178 } | 177 } |
179 | 178 |
180 DirOpenResult Directory::OpenImpl( | 179 DirOpenResult Directory::OpenImpl( |
181 const string& name, | 180 const string& name, |
182 DirectoryChangeDelegate* delegate, | 181 DirectoryChangeDelegate* delegate, |
183 const WeakHandle<TransactionObserver>& | 182 const WeakHandle<TransactionObserver>& transaction_observer) { |
184 transaction_observer) { | |
185 KernelLoadInfo info; | 183 KernelLoadInfo info; |
186 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) | 184 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) |
187 // swap these later. | 185 // swap these later. |
188 Directory::MetahandlesMap tmp_handles_map; | 186 Directory::MetahandlesMap tmp_handles_map; |
189 | 187 |
190 // Avoids mem leaks on failure. Harmlessly deletes the empty hash map after | 188 // Avoids mem leaks on failure. Harmlessly deletes the empty hash map after |
191 // the swap in the success case. | 189 // the swap in the success case. |
192 STLValueDeleter<MetahandlesMap> deleter(&tmp_handles_map); | 190 STLValueDeleter<MetahandlesMap> deleter(&tmp_handles_map); |
193 | 191 |
194 JournalIndex delete_journals; | 192 JournalIndex delete_journals; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 void Directory::Close() { | 224 void Directory::Close() { |
227 store_.reset(); | 225 store_.reset(); |
228 if (kernel_) { | 226 if (kernel_) { |
229 delete kernel_; | 227 delete kernel_; |
230 kernel_ = NULL; | 228 kernel_ = NULL; |
231 } | 229 } |
232 } | 230 } |
233 | 231 |
234 void Directory::OnUnrecoverableError(const BaseTransaction* trans, | 232 void Directory::OnUnrecoverableError(const BaseTransaction* trans, |
235 const tracked_objects::Location& location, | 233 const tracked_objects::Location& location, |
236 const std::string & message) { | 234 const std::string& message) { |
237 DCHECK(trans != NULL); | 235 DCHECK(trans != NULL); |
238 unrecoverable_error_set_ = true; | 236 unrecoverable_error_set_ = true; |
239 unrecoverable_error_handler_.Call( | 237 unrecoverable_error_handler_.Call( |
240 FROM_HERE, &UnrecoverableErrorHandler::OnUnrecoverableError, location, | 238 FROM_HERE, &UnrecoverableErrorHandler::OnUnrecoverableError, location, |
241 message); | 239 message); |
242 } | 240 } |
243 | 241 |
244 EntryKernel* Directory::GetEntryById(const Id& id) { | 242 EntryKernel* Directory::GetEntryById(const Id& id) { |
245 ScopedKernelLock lock(this); | 243 ScopedKernelLock lock(this); |
246 return GetEntryById(lock, id); | 244 return GetEntryById(lock, id); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 } | 277 } |
280 | 278 |
281 EntryKernel* Directory::GetEntryByHandle(int64_t metahandle) { | 279 EntryKernel* Directory::GetEntryByHandle(int64_t metahandle) { |
282 ScopedKernelLock lock(this); | 280 ScopedKernelLock lock(this); |
283 return GetEntryByHandle(lock, metahandle); | 281 return GetEntryByHandle(lock, metahandle); |
284 } | 282 } |
285 | 283 |
286 EntryKernel* Directory::GetEntryByHandle(const ScopedKernelLock& lock, | 284 EntryKernel* Directory::GetEntryByHandle(const ScopedKernelLock& lock, |
287 int64_t metahandle) { | 285 int64_t metahandle) { |
288 // Look up in memory | 286 // Look up in memory |
289 MetahandlesMap::iterator found = | 287 MetahandlesMap::iterator found = kernel_->metahandles_map.find(metahandle); |
290 kernel_->metahandles_map.find(metahandle); | |
291 if (found != kernel_->metahandles_map.end()) { | 288 if (found != kernel_->metahandles_map.end()) { |
292 // Found it in memory. Easy. | 289 // Found it in memory. Easy. |
293 return found->second; | 290 return found->second; |
294 } | 291 } |
295 return NULL; | 292 return NULL; |
296 } | 293 } |
297 | 294 |
298 bool Directory::GetChildHandlesById( | 295 bool Directory::GetChildHandlesById(BaseTransaction* trans, |
299 BaseTransaction* trans, const Id& parent_id, | 296 const Id& parent_id, |
300 Directory::Metahandles* result) { | 297 Directory::Metahandles* result) { |
301 if (!SyncAssert(this == trans->directory(), FROM_HERE, | 298 if (!SyncAssert(this == trans->directory(), FROM_HERE, |
302 "Directories don't match", trans)) | 299 "Directories don't match", trans)) |
303 return false; | 300 return false; |
304 result->clear(); | 301 result->clear(); |
305 | 302 |
306 ScopedKernelLock lock(this); | 303 ScopedKernelLock lock(this); |
307 AppendChildHandles(lock, parent_id, result); | 304 AppendChildHandles(lock, parent_id, result); |
308 return true; | 305 return true; |
309 } | 306 } |
310 | 307 |
311 int Directory::GetTotalNodeCount( | 308 int Directory::GetTotalNodeCount(BaseTransaction* trans, |
312 BaseTransaction* trans, | 309 EntryKernel* kernel) const { |
313 EntryKernel* kernel) const { | |
314 if (!SyncAssert(this == trans->directory(), FROM_HERE, | 310 if (!SyncAssert(this == trans->directory(), FROM_HERE, |
315 "Directories don't match", trans)) | 311 "Directories don't match", trans)) |
316 return false; | 312 return false; |
317 | 313 |
318 int count = 1; | 314 int count = 1; |
319 std::deque<const OrderedChildSet*> child_sets; | 315 std::deque<const OrderedChildSet*> child_sets; |
320 | 316 |
321 GetChildSetForKernel(trans, kernel, &child_sets); | 317 GetChildSetForKernel(trans, kernel, &child_sets); |
322 while (!child_sets.empty()) { | 318 while (!child_sets.empty()) { |
323 const OrderedChildSet* set = child_sets.front(); | 319 const OrderedChildSet* set = child_sets.front(); |
324 child_sets.pop_front(); | 320 child_sets.pop_front(); |
325 for (OrderedChildSet::const_iterator it = set->begin(); | 321 for (OrderedChildSet::const_iterator it = set->begin(); it != set->end(); |
326 it != set->end(); ++it) { | 322 ++it) { |
327 count++; | 323 count++; |
328 GetChildSetForKernel(trans, *it, &child_sets); | 324 GetChildSetForKernel(trans, *it, &child_sets); |
329 } | 325 } |
330 } | 326 } |
331 | 327 |
332 return count; | 328 return count; |
333 } | 329 } |
334 | 330 |
335 void Directory::GetChildSetForKernel( | 331 void Directory::GetChildSetForKernel( |
336 BaseTransaction* trans, | 332 BaseTransaction* trans, |
337 EntryKernel* kernel, | 333 EntryKernel* kernel, |
338 std::deque<const OrderedChildSet*>* child_sets) const { | 334 std::deque<const OrderedChildSet*>* child_sets) const { |
339 if (!kernel->ref(IS_DIR)) | 335 if (!kernel->ref(IS_DIR)) |
340 return; // Not a directory => no children. | 336 return; // Not a directory => no children. |
341 | 337 |
342 const OrderedChildSet* descendants = | 338 const OrderedChildSet* descendants = |
343 kernel_->parent_child_index.GetChildren(kernel->ref(ID)); | 339 kernel_->parent_child_index.GetChildren(kernel->ref(ID)); |
344 if (!descendants) | 340 if (!descendants) |
345 return; // This directory has no children. | 341 return; // This directory has no children. |
346 | 342 |
347 // Add our children to the list of items to be traversed. | 343 // Add our children to the list of items to be traversed. |
348 child_sets->push_back(descendants); | 344 child_sets->push_back(descendants); |
349 } | 345 } |
350 | 346 |
351 int Directory::GetPositionIndex( | 347 int Directory::GetPositionIndex(BaseTransaction* trans, |
352 BaseTransaction* trans, | 348 EntryKernel* kernel) const { |
353 EntryKernel* kernel) const { | |
354 const OrderedChildSet* siblings = | 349 const OrderedChildSet* siblings = |
355 kernel_->parent_child_index.GetSiblings(kernel); | 350 kernel_->parent_child_index.GetSiblings(kernel); |
356 | 351 |
357 OrderedChildSet::const_iterator it = siblings->find(kernel); | 352 OrderedChildSet::const_iterator it = siblings->find(kernel); |
358 return std::distance(siblings->begin(), it); | 353 return std::distance(siblings->begin(), it); |
359 } | 354 } |
360 | 355 |
361 bool Directory::InsertEntry(BaseWriteTransaction* trans, EntryKernel* entry) { | 356 bool Directory::InsertEntry(BaseWriteTransaction* trans, EntryKernel* entry) { |
362 ScopedKernelLock lock(this); | 357 ScopedKernelLock lock(this); |
363 return InsertEntry(lock, trans, entry); | 358 return InsertEntry(lock, trans, entry); |
364 } | 359 } |
365 | 360 |
366 bool Directory::InsertEntry(const ScopedKernelLock& lock, | 361 bool Directory::InsertEntry(const ScopedKernelLock& lock, |
367 BaseWriteTransaction* trans, | 362 BaseWriteTransaction* trans, |
368 EntryKernel* entry) { | 363 EntryKernel* entry) { |
369 if (!SyncAssert(NULL != entry, FROM_HERE, "Entry is null", trans)) | 364 if (!SyncAssert(NULL != entry, FROM_HERE, "Entry is null", trans)) |
370 return false; | 365 return false; |
371 | 366 |
372 static const char error[] = "Entry already in memory index."; | 367 static const char error[] = "Entry already in memory index."; |
373 | 368 |
374 if (!SyncAssert( | 369 if (!SyncAssert(kernel_->metahandles_map |
375 kernel_->metahandles_map.insert( | 370 .insert(std::make_pair(entry->ref(META_HANDLE), entry)) |
376 std::make_pair(entry->ref(META_HANDLE), entry)).second, | 371 .second, |
377 FROM_HERE, | 372 FROM_HERE, error, trans)) { |
378 error, | |
379 trans)) { | |
380 return false; | 373 return false; |
381 } | 374 } |
382 if (!SyncAssert( | 375 if (!SyncAssert( |
383 kernel_->ids_map.insert( | 376 kernel_->ids_map.insert(std::make_pair(entry->ref(ID).value(), entry)) |
384 std::make_pair(entry->ref(ID).value(), entry)).second, | 377 .second, |
385 FROM_HERE, | 378 FROM_HERE, error, trans)) { |
386 error, | |
387 trans)) { | |
388 return false; | 379 return false; |
389 } | 380 } |
390 if (ParentChildIndex::ShouldInclude(entry)) { | 381 if (ParentChildIndex::ShouldInclude(entry)) { |
391 if (!SyncAssert(kernel_->parent_child_index.Insert(entry), | 382 if (!SyncAssert(kernel_->parent_child_index.Insert(entry), FROM_HERE, error, |
392 FROM_HERE, | |
393 error, | |
394 trans)) { | 383 trans)) { |
395 return false; | 384 return false; |
396 } | 385 } |
397 } | 386 } |
398 AddToAttachmentIndex( | 387 AddToAttachmentIndex(lock, entry->ref(META_HANDLE), |
399 lock, entry->ref(META_HANDLE), entry->ref(ATTACHMENT_METADATA)); | 388 entry->ref(ATTACHMENT_METADATA)); |
400 | 389 |
401 // Should NEVER be created with a client tag or server tag. | 390 // Should NEVER be created with a client tag or server tag. |
402 if (!SyncAssert(entry->ref(UNIQUE_SERVER_TAG).empty(), FROM_HERE, | 391 if (!SyncAssert(entry->ref(UNIQUE_SERVER_TAG).empty(), FROM_HERE, |
403 "Server tag should be empty", trans)) { | 392 "Server tag should be empty", trans)) { |
404 return false; | 393 return false; |
405 } | 394 } |
406 if (!SyncAssert(entry->ref(UNIQUE_CLIENT_TAG).empty(), FROM_HERE, | 395 if (!SyncAssert(entry->ref(UNIQUE_CLIENT_TAG).empty(), FROM_HERE, |
407 "Client tag should be empty", trans)) | 396 "Client tag should be empty", trans)) |
408 return false; | 397 return false; |
409 | 398 |
410 return true; | 399 return true; |
411 } | 400 } |
412 | 401 |
413 bool Directory::ReindexId(BaseWriteTransaction* trans, | 402 bool Directory::ReindexId(BaseWriteTransaction* trans, |
414 EntryKernel* const entry, | 403 EntryKernel* const entry, |
415 const Id& new_id) { | 404 const Id& new_id) { |
416 ScopedKernelLock lock(this); | 405 ScopedKernelLock lock(this); |
417 if (NULL != GetEntryById(lock, new_id)) | 406 if (NULL != GetEntryById(lock, new_id)) |
418 return false; | 407 return false; |
419 | 408 |
420 { | 409 { |
421 // Update the indices that depend on the ID field. | 410 // Update the indices that depend on the ID field. |
422 ScopedParentChildIndexUpdater updater_b(lock, entry, | 411 ScopedParentChildIndexUpdater updater_b(lock, entry, |
423 &kernel_->parent_child_index); | 412 &kernel_->parent_child_index); |
424 size_t num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); | 413 size_t num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); |
425 DCHECK_EQ(1U, num_erased); | 414 DCHECK_EQ(1U, num_erased); |
426 entry->put(ID, new_id); | 415 entry->put(ID, new_id); |
427 kernel_->ids_map[entry->ref(ID).value()] = entry; | 416 kernel_->ids_map[entry->ref(ID).value()] = entry; |
428 } | 417 } |
429 return true; | 418 return true; |
430 } | 419 } |
431 | 420 |
432 bool Directory::ReindexParentId(BaseWriteTransaction* trans, | 421 bool Directory::ReindexParentId(BaseWriteTransaction* trans, |
433 EntryKernel* const entry, | 422 EntryKernel* const entry, |
434 const Id& new_parent_id) { | 423 const Id& new_parent_id) { |
435 ScopedKernelLock lock(this); | 424 ScopedKernelLock lock(this); |
436 | 425 |
437 { | 426 { |
438 // Update the indices that depend on the PARENT_ID field. | 427 // Update the indices that depend on the PARENT_ID field. |
439 ScopedParentChildIndexUpdater index_updater(lock, entry, | 428 ScopedParentChildIndexUpdater index_updater(lock, entry, |
440 &kernel_->parent_child_index); | 429 &kernel_->parent_child_index); |
441 entry->put(PARENT_ID, new_parent_id); | 430 entry->put(PARENT_ID, new_parent_id); |
442 } | 431 } |
443 return true; | 432 return true; |
444 } | 433 } |
445 | 434 |
446 void Directory::RemoveFromAttachmentIndex( | 435 void Directory::RemoveFromAttachmentIndex( |
447 const ScopedKernelLock& lock, | 436 const ScopedKernelLock& lock, |
448 const int64_t metahandle, | 437 const int64_t metahandle, |
449 const sync_pb::AttachmentMetadata& attachment_metadata) { | 438 const sync_pb::AttachmentMetadata& attachment_metadata) { |
450 for (int i = 0; i < attachment_metadata.record_size(); ++i) { | 439 for (int i = 0; i < attachment_metadata.record_size(); ++i) { |
(...skipping 13 matching lines...) Expand all Loading... |
464 void Directory::AddToAttachmentIndex( | 453 void Directory::AddToAttachmentIndex( |
465 const ScopedKernelLock& lock, | 454 const ScopedKernelLock& lock, |
466 const int64_t metahandle, | 455 const int64_t metahandle, |
467 const sync_pb::AttachmentMetadata& attachment_metadata) { | 456 const sync_pb::AttachmentMetadata& attachment_metadata) { |
468 for (int i = 0; i < attachment_metadata.record_size(); ++i) { | 457 for (int i = 0; i < attachment_metadata.record_size(); ++i) { |
469 AttachmentIdUniqueId unique_id = | 458 AttachmentIdUniqueId unique_id = |
470 attachment_metadata.record(i).id().unique_id(); | 459 attachment_metadata.record(i).id().unique_id(); |
471 IndexByAttachmentId::iterator iter = | 460 IndexByAttachmentId::iterator iter = |
472 kernel_->index_by_attachment_id.find(unique_id); | 461 kernel_->index_by_attachment_id.find(unique_id); |
473 if (iter == kernel_->index_by_attachment_id.end()) { | 462 if (iter == kernel_->index_by_attachment_id.end()) { |
474 iter = kernel_->index_by_attachment_id.insert(std::make_pair( | 463 iter = kernel_->index_by_attachment_id |
475 unique_id, | 464 .insert(std::make_pair(unique_id, MetahandleSet())) |
476 MetahandleSet())).first; | 465 .first; |
477 } | 466 } |
478 iter->second.insert(metahandle); | 467 iter->second.insert(metahandle); |
479 } | 468 } |
480 } | 469 } |
481 | 470 |
482 void Directory::UpdateAttachmentIndex( | 471 void Directory::UpdateAttachmentIndex( |
483 const int64_t metahandle, | 472 const int64_t metahandle, |
484 const sync_pb::AttachmentMetadata& old_metadata, | 473 const sync_pb::AttachmentMetadata& old_metadata, |
485 const sync_pb::AttachmentMetadata& new_metadata) { | 474 const sync_pb::AttachmentMetadata& new_metadata) { |
486 ScopedKernelLock lock(this); | 475 ScopedKernelLock lock(this); |
487 RemoveFromAttachmentIndex(lock, metahandle, old_metadata); | 476 RemoveFromAttachmentIndex(lock, metahandle, old_metadata); |
488 AddToAttachmentIndex(lock, metahandle, new_metadata); | 477 AddToAttachmentIndex(lock, metahandle, new_metadata); |
489 } | 478 } |
490 | 479 |
491 void Directory::GetMetahandlesByAttachmentId( | 480 void Directory::GetMetahandlesByAttachmentId( |
492 BaseTransaction* trans, | 481 BaseTransaction* trans, |
493 const sync_pb::AttachmentIdProto& attachment_id_proto, | 482 const sync_pb::AttachmentIdProto& attachment_id_proto, |
494 Metahandles* result) { | 483 Metahandles* result) { |
495 DCHECK(result); | 484 DCHECK(result); |
496 result->clear(); | 485 result->clear(); |
497 ScopedKernelLock lock(this); | 486 ScopedKernelLock lock(this); |
498 IndexByAttachmentId::const_iterator index_iter = | 487 IndexByAttachmentId::const_iterator index_iter = |
499 kernel_->index_by_attachment_id.find(attachment_id_proto.unique_id()); | 488 kernel_->index_by_attachment_id.find(attachment_id_proto.unique_id()); |
500 if (index_iter == kernel_->index_by_attachment_id.end()) | 489 if (index_iter == kernel_->index_by_attachment_id.end()) |
501 return; | 490 return; |
502 const MetahandleSet& metahandle_set = index_iter->second; | 491 const MetahandleSet& metahandle_set = index_iter->second; |
503 std::copy( | 492 std::copy(metahandle_set.begin(), metahandle_set.end(), |
504 metahandle_set.begin(), metahandle_set.end(), back_inserter(*result)); | 493 back_inserter(*result)); |
505 } | 494 } |
506 | 495 |
507 bool Directory::unrecoverable_error_set(const BaseTransaction* trans) const { | 496 bool Directory::unrecoverable_error_set(const BaseTransaction* trans) const { |
508 DCHECK(trans != NULL); | 497 DCHECK(trans != NULL); |
509 return unrecoverable_error_set_; | 498 return unrecoverable_error_set_; |
510 } | 499 } |
511 | 500 |
512 void Directory::ClearDirtyMetahandles(const ScopedKernelLock& lock) { | 501 void Directory::ClearDirtyMetahandles(const ScopedKernelLock& lock) { |
513 kernel_->transaction_mutex.AssertAcquired(); | 502 kernel_->transaction_mutex.AssertAcquired(); |
514 kernel_->dirty_metahandles.clear(); | 503 kernel_->dirty_metahandles.clear(); |
515 } | 504 } |
516 | 505 |
517 bool Directory::SafeToPurgeFromMemory(WriteTransaction* trans, | 506 bool Directory::SafeToPurgeFromMemory(WriteTransaction* trans, |
518 const EntryKernel* const entry) const { | 507 const EntryKernel* const entry) const { |
519 bool safe = entry->ref(IS_DEL) && !entry->is_dirty() && | 508 bool safe = entry->ref(IS_DEL) && !entry->is_dirty() && |
520 !entry->ref(SYNCING) && !entry->ref(IS_UNAPPLIED_UPDATE) && | 509 !entry->ref(SYNCING) && !entry->ref(IS_UNAPPLIED_UPDATE) && |
521 !entry->ref(IS_UNSYNCED); | 510 !entry->ref(IS_UNSYNCED); |
522 | 511 |
523 if (safe) { | 512 if (safe) { |
524 int64_t handle = entry->ref(META_HANDLE); | 513 int64_t handle = entry->ref(META_HANDLE); |
525 const ModelType type = entry->GetServerModelType(); | 514 const ModelType type = entry->GetServerModelType(); |
526 if (!SyncAssert(kernel_->dirty_metahandles.count(handle) == 0U, | 515 if (!SyncAssert(kernel_->dirty_metahandles.count(handle) == 0U, FROM_HERE, |
527 FROM_HERE, | |
528 "Dirty metahandles should be empty", trans)) | 516 "Dirty metahandles should be empty", trans)) |
529 return false; | 517 return false; |
530 // TODO(tim): Bug 49278. | 518 // TODO(tim): Bug 49278. |
531 if (!SyncAssert(!kernel_->unsynced_metahandles.count(handle), | 519 if (!SyncAssert(!kernel_->unsynced_metahandles.count(handle), FROM_HERE, |
532 FROM_HERE, | 520 "Unsynced handles should be empty", trans)) |
533 "Unsynced handles should be empty", | |
534 trans)) | |
535 return false; | 521 return false; |
536 if (!SyncAssert(!kernel_->unapplied_update_metahandles[type].count(handle), | 522 if (!SyncAssert(!kernel_->unapplied_update_metahandles[type].count(handle), |
537 FROM_HERE, | 523 FROM_HERE, "Unapplied metahandles should be empty", trans)) |
538 "Unapplied metahandles should be empty", | |
539 trans)) | |
540 return false; | 524 return false; |
541 } | 525 } |
542 | 526 |
543 return safe; | 527 return safe; |
544 } | 528 } |
545 | 529 |
546 void Directory::TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot) { | 530 void Directory::TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot) { |
547 ReadTransaction trans(FROM_HERE, this); | 531 ReadTransaction trans(FROM_HERE, this); |
548 ScopedKernelLock lock(this); | 532 ScopedKernelLock lock(this); |
549 | 533 |
(...skipping 23 matching lines...) Expand all Loading... |
573 // Set purged handles. | 557 // Set purged handles. |
574 DCHECK(snapshot->metahandles_to_purge.empty()); | 558 DCHECK(snapshot->metahandles_to_purge.empty()); |
575 snapshot->metahandles_to_purge.swap(kernel_->metahandles_to_purge); | 559 snapshot->metahandles_to_purge.swap(kernel_->metahandles_to_purge); |
576 | 560 |
577 // Fill kernel_info_status and kernel_info. | 561 // Fill kernel_info_status and kernel_info. |
578 snapshot->kernel_info = kernel_->persisted_info; | 562 snapshot->kernel_info = kernel_->persisted_info; |
579 snapshot->kernel_info_status = kernel_->info_status; | 563 snapshot->kernel_info_status = kernel_->info_status; |
580 // This one we reset on failure. | 564 // This one we reset on failure. |
581 kernel_->info_status = KERNEL_SHARE_INFO_VALID; | 565 kernel_->info_status = KERNEL_SHARE_INFO_VALID; |
582 | 566 |
583 delete_journal_->TakeSnapshotAndClear( | 567 delete_journal_->TakeSnapshotAndClear(&trans, &snapshot->delete_journals, |
584 &trans, &snapshot->delete_journals, &snapshot->delete_journals_to_purge); | 568 &snapshot->delete_journals_to_purge); |
585 } | 569 } |
586 | 570 |
587 bool Directory::SaveChanges() { | 571 bool Directory::SaveChanges() { |
588 bool success = false; | 572 bool success = false; |
589 | 573 |
590 base::AutoLock scoped_lock(kernel_->save_changes_mutex); | 574 base::AutoLock scoped_lock(kernel_->save_changes_mutex); |
591 | 575 |
592 // Snapshot and save. | 576 // Snapshot and save. |
593 SaveChangesSnapshot snapshot; | 577 SaveChangesSnapshot snapshot; |
594 TakeSnapshotForSaveChanges(&snapshot); | 578 TakeSnapshotForSaveChanges(&snapshot); |
(...skipping 12 matching lines...) Expand all Loading... |
607 return true; | 591 return true; |
608 | 592 |
609 // Need a write transaction as we are about to permanently purge entries. | 593 // Need a write transaction as we are about to permanently purge entries. |
610 WriteTransaction trans(FROM_HERE, VACUUM_AFTER_SAVE, this); | 594 WriteTransaction trans(FROM_HERE, VACUUM_AFTER_SAVE, this); |
611 ScopedKernelLock lock(this); | 595 ScopedKernelLock lock(this); |
612 // Now drop everything we can out of memory. | 596 // Now drop everything we can out of memory. |
613 for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); | 597 for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); |
614 i != snapshot.dirty_metas.end(); ++i) { | 598 i != snapshot.dirty_metas.end(); ++i) { |
615 MetahandlesMap::iterator found = | 599 MetahandlesMap::iterator found = |
616 kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); | 600 kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); |
617 EntryKernel* entry = (found == kernel_->metahandles_map.end() ? | 601 EntryKernel* entry = |
618 NULL : found->second); | 602 (found == kernel_->metahandles_map.end() ? NULL : found->second); |
619 if (entry && SafeToPurgeFromMemory(&trans, entry)) { | 603 if (entry && SafeToPurgeFromMemory(&trans, entry)) { |
620 // We now drop deleted metahandles that are up to date on both the client | 604 // We now drop deleted metahandles that are up to date on both the client |
621 // and the server. | 605 // and the server. |
622 size_t num_erased = 0; | 606 size_t num_erased = 0; |
623 num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); | 607 num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); |
624 DCHECK_EQ(1u, num_erased); | 608 DCHECK_EQ(1u, num_erased); |
625 num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); | 609 num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); |
626 DCHECK_EQ(1u, num_erased); | 610 DCHECK_EQ(1u, num_erased); |
627 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { | 611 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { |
628 num_erased = | 612 num_erased = |
629 kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); | 613 kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); |
630 DCHECK_EQ(1u, num_erased); | 614 DCHECK_EQ(1u, num_erased); |
631 } | 615 } |
632 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { | 616 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { |
633 num_erased = | 617 num_erased = |
634 kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); | 618 kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); |
635 DCHECK_EQ(1u, num_erased); | 619 DCHECK_EQ(1u, num_erased); |
636 } | 620 } |
637 if (!SyncAssert(!kernel_->parent_child_index.Contains(entry), | 621 if (!SyncAssert(!kernel_->parent_child_index.Contains(entry), FROM_HERE, |
638 FROM_HERE, | 622 "Deleted entry still present", (&trans))) |
639 "Deleted entry still present", | |
640 (&trans))) | |
641 return false; | 623 return false; |
642 RemoveFromAttachmentIndex( | 624 RemoveFromAttachmentIndex(lock, entry->ref(META_HANDLE), |
643 lock, entry->ref(META_HANDLE), entry->ref(ATTACHMENT_METADATA)); | 625 entry->ref(ATTACHMENT_METADATA)); |
644 | 626 |
645 delete entry; | 627 delete entry; |
646 } | 628 } |
647 if (trans.unrecoverable_error_set()) | 629 if (trans.unrecoverable_error_set()) |
648 return false; | 630 return false; |
649 } | 631 } |
650 return true; | 632 return true; |
651 } | 633 } |
652 | 634 |
653 void Directory::UnapplyEntry(EntryKernel* entry) { | 635 void Directory::UnapplyEntry(EntryKernel* entry) { |
654 int64_t handle = entry->ref(META_HANDLE); | 636 int64_t handle = entry->ref(META_HANDLE); |
655 ModelType server_type = GetModelTypeFromSpecifics( | 637 ModelType server_type = |
656 entry->ref(SERVER_SPECIFICS)); | 638 GetModelTypeFromSpecifics(entry->ref(SERVER_SPECIFICS)); |
657 | 639 |
658 // Clear enough so that on the next sync cycle all local data will | 640 // Clear enough so that on the next sync cycle all local data will |
659 // be overwritten. | 641 // be overwritten. |
660 // Note: do not modify the root node in order to preserve the | 642 // Note: do not modify the root node in order to preserve the |
661 // initial sync ended bit for this type (else on the next restart | 643 // initial sync ended bit for this type (else on the next restart |
662 // this type will be treated as disabled and therefore fully purged). | 644 // this type will be treated as disabled and therefore fully purged). |
663 if (entry->ref(PARENT_ID).IsRoot()) { | 645 if (entry->ref(PARENT_ID).IsRoot()) { |
664 ModelType root_type = server_type; | 646 ModelType root_type = server_type; |
665 // Support both server created and client created type root folders. | 647 // Support both server created and client created type root folders. |
666 if (!IsRealDataType(root_type)) { | 648 if (!IsRealDataType(root_type)) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
704 // deleted items, and purged on the next snapshot. All other items will match | 686 // deleted items, and purged on the next snapshot. All other items will match |
705 // the state they would have had if they were just created via a server | 687 // the state they would have had if they were just created via a server |
706 // update. See MutableEntry::MutableEntry(.., CreateNewUpdateItem, ..). | 688 // update. See MutableEntry::MutableEntry(.., CreateNewUpdateItem, ..). |
707 } | 689 } |
708 | 690 |
709 void Directory::DeleteEntry(const ScopedKernelLock& lock, | 691 void Directory::DeleteEntry(const ScopedKernelLock& lock, |
710 bool save_to_journal, | 692 bool save_to_journal, |
711 EntryKernel* entry, | 693 EntryKernel* entry, |
712 EntryKernelSet* entries_to_journal) { | 694 EntryKernelSet* entries_to_journal) { |
713 int64_t handle = entry->ref(META_HANDLE); | 695 int64_t handle = entry->ref(META_HANDLE); |
714 ModelType server_type = GetModelTypeFromSpecifics( | 696 ModelType server_type = |
715 entry->ref(SERVER_SPECIFICS)); | 697 GetModelTypeFromSpecifics(entry->ref(SERVER_SPECIFICS)); |
716 | 698 |
717 kernel_->metahandles_to_purge.insert(handle); | 699 kernel_->metahandles_to_purge.insert(handle); |
718 | 700 |
719 size_t num_erased = 0; | 701 size_t num_erased = 0; |
720 num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); | 702 num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); |
721 DCHECK_EQ(1u, num_erased); | 703 DCHECK_EQ(1u, num_erased); |
722 num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); | 704 num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); |
723 DCHECK_EQ(1u, num_erased); | 705 DCHECK_EQ(1u, num_erased); |
724 num_erased = kernel_->unsynced_metahandles.erase(handle); | 706 num_erased = kernel_->unsynced_metahandles.erase(handle); |
725 DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0); | 707 DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0); |
726 num_erased = | 708 num_erased = kernel_->unapplied_update_metahandles[server_type].erase(handle); |
727 kernel_->unapplied_update_metahandles[server_type].erase(handle); | |
728 DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0); | 709 DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0); |
729 if (kernel_->parent_child_index.Contains(entry)) | 710 if (kernel_->parent_child_index.Contains(entry)) |
730 kernel_->parent_child_index.Remove(entry); | 711 kernel_->parent_child_index.Remove(entry); |
731 | 712 |
732 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { | 713 if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { |
733 num_erased = | 714 num_erased = kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); |
734 kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); | |
735 DCHECK_EQ(1u, num_erased); | 715 DCHECK_EQ(1u, num_erased); |
736 } | 716 } |
737 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { | 717 if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { |
738 num_erased = | 718 num_erased = kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); |
739 kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); | |
740 DCHECK_EQ(1u, num_erased); | 719 DCHECK_EQ(1u, num_erased); |
741 } | 720 } |
742 RemoveFromAttachmentIndex(lock, handle, entry->ref(ATTACHMENT_METADATA)); | 721 RemoveFromAttachmentIndex(lock, handle, entry->ref(ATTACHMENT_METADATA)); |
743 | 722 |
744 if (save_to_journal) { | 723 if (save_to_journal) { |
745 entries_to_journal->insert(entry); | 724 entries_to_journal->insert(entry); |
746 } else { | 725 } else { |
747 delete entry; | 726 delete entry; |
748 } | 727 } |
749 } | 728 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 (delete_journal_->IsDeleteJournalEnabled(local_type) || | 781 (delete_journal_->IsDeleteJournalEnabled(local_type) || |
803 delete_journal_->IsDeleteJournalEnabled(server_type)); | 782 delete_journal_->IsDeleteJournalEnabled(server_type)); |
804 DeleteEntry(lock, save_to_journal, entry, &entries_to_journal); | 783 DeleteEntry(lock, save_to_journal, entry, &entries_to_journal); |
805 } | 784 } |
806 } | 785 } |
807 } | 786 } |
808 | 787 |
809 delete_journal_->AddJournalBatch(&trans, entries_to_journal); | 788 delete_journal_->AddJournalBatch(&trans, entries_to_journal); |
810 | 789 |
811 // Ensure meta tracking for these data types reflects the purged state. | 790 // Ensure meta tracking for these data types reflects the purged state. |
812 for (ModelTypeSet::Iterator it = disabled_types.First(); | 791 for (ModelTypeSet::Iterator it = disabled_types.First(); it.Good(); |
813 it.Good(); it.Inc()) { | 792 it.Inc()) { |
814 kernel_->persisted_info.transaction_version[it.Get()] = 0; | 793 kernel_->persisted_info.transaction_version[it.Get()] = 0; |
815 | 794 |
816 // Don't discard progress markers or context for unapplied types. | 795 // Don't discard progress markers or context for unapplied types. |
817 if (!types_to_unapply.Has(it.Get())) { | 796 if (!types_to_unapply.Has(it.Get())) { |
818 kernel_->persisted_info.ResetDownloadProgress(it.Get()); | 797 kernel_->persisted_info.ResetDownloadProgress(it.Get()); |
819 kernel_->persisted_info.datatype_context[it.Get()].Clear(); | 798 kernel_->persisted_info.datatype_context[it.Get()].Clear(); |
820 } | 799 } |
821 } | 800 } |
822 | 801 |
823 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 802 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 } | 879 } |
901 | 880 |
902 void Directory::GetDownloadProgress( | 881 void Directory::GetDownloadProgress( |
903 ModelType model_type, | 882 ModelType model_type, |
904 sync_pb::DataTypeProgressMarker* value_out) const { | 883 sync_pb::DataTypeProgressMarker* value_out) const { |
905 ScopedKernelLock lock(this); | 884 ScopedKernelLock lock(this); |
906 return value_out->CopyFrom( | 885 return value_out->CopyFrom( |
907 kernel_->persisted_info.download_progress[model_type]); | 886 kernel_->persisted_info.download_progress[model_type]); |
908 } | 887 } |
909 | 888 |
910 void Directory::GetDownloadProgressAsString( | 889 void Directory::GetDownloadProgressAsString(ModelType model_type, |
911 ModelType model_type, | 890 std::string* value_out) const { |
912 std::string* value_out) const { | |
913 ScopedKernelLock lock(this); | 891 ScopedKernelLock lock(this); |
914 kernel_->persisted_info.download_progress[model_type].SerializeToString( | 892 kernel_->persisted_info.download_progress[model_type].SerializeToString( |
915 value_out); | 893 value_out); |
916 } | 894 } |
917 | 895 |
918 size_t Directory::GetEntriesCount() const { | 896 size_t Directory::GetEntriesCount() const { |
919 ScopedKernelLock lock(this); | 897 ScopedKernelLock lock(this); |
920 return kernel_->metahandles_map.size(); | 898 return kernel_->metahandles_map.size(); |
921 } | 899 } |
922 | 900 |
(...skipping 21 matching lines...) Expand all Loading... |
944 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 922 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
945 } | 923 } |
946 | 924 |
947 void Directory::GetDataTypeContext(BaseTransaction* trans, | 925 void Directory::GetDataTypeContext(BaseTransaction* trans, |
948 ModelType type, | 926 ModelType type, |
949 sync_pb::DataTypeContext* context) const { | 927 sync_pb::DataTypeContext* context) const { |
950 ScopedKernelLock lock(this); | 928 ScopedKernelLock lock(this); |
951 context->CopyFrom(kernel_->persisted_info.datatype_context[type]); | 929 context->CopyFrom(kernel_->persisted_info.datatype_context[type]); |
952 } | 930 } |
953 | 931 |
954 void Directory::SetDataTypeContext( | 932 void Directory::SetDataTypeContext(BaseWriteTransaction* trans, |
955 BaseWriteTransaction* trans, | 933 ModelType type, |
956 ModelType type, | 934 const sync_pb::DataTypeContext& context) { |
957 const sync_pb::DataTypeContext& context) { | |
958 ScopedKernelLock lock(this); | 935 ScopedKernelLock lock(this); |
959 kernel_->persisted_info.datatype_context[type].CopyFrom(context); | 936 kernel_->persisted_info.datatype_context[type].CopyFrom(context); |
960 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 937 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
961 } | 938 } |
962 | 939 |
963 // TODO(stanisc): crbug.com/438313: change these to not rely on the folders. | 940 // TODO(stanisc): crbug.com/438313: change these to not rely on the folders. |
964 ModelTypeSet Directory::InitialSyncEndedTypes() { | 941 ModelTypeSet Directory::InitialSyncEndedTypes() { |
965 syncable::ReadTransaction trans(FROM_HERE, this); | 942 syncable::ReadTransaction trans(FROM_HERE, this); |
966 ModelTypeSet protocol_types = ProtocolTypes(); | 943 ModelTypeSet protocol_types = ProtocolTypes(); |
967 ModelTypeSet initial_sync_ended_types; | 944 ModelTypeSet initial_sync_ended_types; |
968 for (ModelTypeSet::Iterator i = protocol_types.First(); i.Good(); i.Inc()) { | 945 for (ModelTypeSet::Iterator i = protocol_types.First(); i.Good(); i.Inc()) { |
969 if (InitialSyncEndedForType(&trans, i.Get())) { | 946 if (InitialSyncEndedForType(&trans, i.Get())) { |
970 initial_sync_ended_types.Put(i.Get()); | 947 initial_sync_ended_types.Put(i.Get()); |
971 } | 948 } |
972 } | 949 } |
973 return initial_sync_ended_types; | 950 return initial_sync_ended_types; |
974 } | 951 } |
975 | 952 |
976 bool Directory::InitialSyncEndedForType(ModelType type) { | 953 bool Directory::InitialSyncEndedForType(ModelType type) { |
977 syncable::ReadTransaction trans(FROM_HERE, this); | 954 syncable::ReadTransaction trans(FROM_HERE, this); |
978 return InitialSyncEndedForType(&trans, type); | 955 return InitialSyncEndedForType(&trans, type); |
979 } | 956 } |
980 | 957 |
981 bool Directory::InitialSyncEndedForType( | 958 bool Directory::InitialSyncEndedForType(BaseTransaction* trans, |
982 BaseTransaction* trans, ModelType type) { | 959 ModelType type) { |
983 // True iff the type's root node has been created and changes | 960 // True iff the type's root node has been created and changes |
984 // for the type have been applied at least once. | 961 // for the type have been applied at least once. |
985 Entry root(trans, GET_TYPE_ROOT, type); | 962 Entry root(trans, GET_TYPE_ROOT, type); |
986 return root.good() && root.GetBaseVersion() != CHANGES_VERSION; | 963 return root.good() && root.GetBaseVersion() != CHANGES_VERSION; |
987 } | 964 } |
988 | 965 |
989 void Directory::MarkInitialSyncEndedForType(BaseWriteTransaction* trans, | 966 void Directory::MarkInitialSyncEndedForType(BaseWriteTransaction* trans, |
990 ModelType type) { | 967 ModelType type) { |
991 // If the root folder is downloaded for the server, the root's base version | 968 // If the root folder is downloaded for the server, the root's base version |
992 // get updated automatically at the end of update cycle when the update gets | 969 // get updated automatically at the end of update cycle when the update gets |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 } | 1003 } |
1027 | 1004 |
1028 void Directory::set_bag_of_chips(const string& bag_of_chips) { | 1005 void Directory::set_bag_of_chips(const string& bag_of_chips) { |
1029 ScopedKernelLock lock(this); | 1006 ScopedKernelLock lock(this); |
1030 if (kernel_->persisted_info.bag_of_chips == bag_of_chips) | 1007 if (kernel_->persisted_info.bag_of_chips == bag_of_chips) |
1031 return; | 1008 return; |
1032 kernel_->persisted_info.bag_of_chips = bag_of_chips; | 1009 kernel_->persisted_info.bag_of_chips = bag_of_chips; |
1033 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; | 1010 kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; |
1034 } | 1011 } |
1035 | 1012 |
1036 | |
1037 string Directory::cache_guid() const { | 1013 string Directory::cache_guid() const { |
1038 // No need to lock since nothing ever writes to it after load. | 1014 // No need to lock since nothing ever writes to it after load. |
1039 return kernel_->cache_guid; | 1015 return kernel_->cache_guid; |
1040 } | 1016 } |
1041 | 1017 |
1042 NigoriHandler* Directory::GetNigoriHandler() { | 1018 NigoriHandler* Directory::GetNigoriHandler() { |
1043 return nigori_handler_; | 1019 return nigori_handler_; |
1044 } | 1020 } |
1045 | 1021 |
1046 Cryptographer* Directory::GetCryptographer(const BaseTransaction* trans) { | 1022 Cryptographer* Directory::GetCryptographer(const BaseTransaction* trans) { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 | 1164 |
1189 bool Directory::FullyCheckTreeInvariants(syncable::BaseTransaction* trans) { | 1165 bool Directory::FullyCheckTreeInvariants(syncable::BaseTransaction* trans) { |
1190 MetahandleSet handles; | 1166 MetahandleSet handles; |
1191 GetAllMetaHandles(trans, &handles); | 1167 GetAllMetaHandles(trans, &handles); |
1192 return CheckTreeInvariants(trans, handles); | 1168 return CheckTreeInvariants(trans, handles); |
1193 } | 1169 } |
1194 | 1170 |
1195 bool Directory::CheckTreeInvariants(syncable::BaseTransaction* trans, | 1171 bool Directory::CheckTreeInvariants(syncable::BaseTransaction* trans, |
1196 const MetahandleSet& handles) { | 1172 const MetahandleSet& handles) { |
1197 MetahandleSet::const_iterator i; | 1173 MetahandleSet::const_iterator i; |
1198 for (i = handles.begin() ; i != handles.end() ; ++i) { | 1174 for (i = handles.begin(); i != handles.end(); ++i) { |
1199 int64_t metahandle = *i; | 1175 int64_t metahandle = *i; |
1200 Entry e(trans, GET_BY_HANDLE, metahandle); | 1176 Entry e(trans, GET_BY_HANDLE, metahandle); |
1201 if (!SyncAssert(e.good(), FROM_HERE, "Entry is bad", trans)) | 1177 if (!SyncAssert(e.good(), FROM_HERE, "Entry is bad", trans)) |
1202 return false; | 1178 return false; |
1203 syncable::Id id = e.GetId(); | 1179 syncable::Id id = e.GetId(); |
1204 syncable::Id parentid = e.GetParentId(); | 1180 syncable::Id parentid = e.GetParentId(); |
1205 | 1181 |
1206 if (id.IsRoot()) { | 1182 if (id.IsRoot()) { |
1207 if (!SyncAssert(e.GetIsDir(), FROM_HERE, | 1183 if (!SyncAssert(e.GetIsDir(), FROM_HERE, "Entry should be a directory", |
1208 "Entry should be a directory", | |
1209 trans)) | 1184 trans)) |
1210 return false; | 1185 return false; |
1211 if (!SyncAssert(parentid.IsRoot(), FROM_HERE, | 1186 if (!SyncAssert(parentid.IsRoot(), FROM_HERE, "Entry should be root", |
1212 "Entry should be root", | |
1213 trans)) | 1187 trans)) |
1214 return false; | 1188 return false; |
1215 if (!SyncAssert(!e.GetIsUnsynced(), FROM_HERE, "Entry should be synced", | 1189 if (!SyncAssert(!e.GetIsUnsynced(), FROM_HERE, "Entry should be synced", |
1216 trans)) | 1190 trans)) |
1217 return false; | 1191 return false; |
1218 continue; | 1192 continue; |
1219 } | 1193 } |
1220 | 1194 |
1221 if (!e.GetIsDel()) { | 1195 if (!e.GetIsDel()) { |
1222 if (!SyncAssert(id != parentid, FROM_HERE, | 1196 if (!SyncAssert(id != parentid, FROM_HERE, |
1223 "Id should be different from parent id.", | 1197 "Id should be different from parent id.", trans)) |
1224 trans)) | 1198 return false; |
1225 return false; | |
1226 if (!SyncAssert(!e.GetNonUniqueName().empty(), FROM_HERE, | 1199 if (!SyncAssert(!e.GetNonUniqueName().empty(), FROM_HERE, |
1227 "Non unique name should not be empty.", | 1200 "Non unique name should not be empty.", trans)) |
1228 trans)) | |
1229 return false; | 1201 return false; |
1230 | 1202 |
1231 if (!parentid.IsNull()) { | 1203 if (!parentid.IsNull()) { |
1232 int safety_count = handles.size() + 1; | 1204 int safety_count = handles.size() + 1; |
1233 while (!parentid.IsRoot()) { | 1205 while (!parentid.IsRoot()) { |
1234 Entry parent(trans, GET_BY_ID, parentid); | 1206 Entry parent(trans, GET_BY_ID, parentid); |
1235 if (!SyncAssert(parent.good(), FROM_HERE, | 1207 if (!SyncAssert(parent.good(), FROM_HERE, |
1236 "Parent entry is not valid.", trans)) | 1208 "Parent entry is not valid.", trans)) |
1237 return false; | 1209 return false; |
1238 if (handles.end() == handles.find(parent.GetMetahandle())) | 1210 if (handles.end() == handles.find(parent.GetMetahandle())) |
(...skipping 14 matching lines...) Expand all Loading... |
1253 return false; | 1225 return false; |
1254 } | 1226 } |
1255 } | 1227 } |
1256 } | 1228 } |
1257 int64_t base_version = e.GetBaseVersion(); | 1229 int64_t base_version = e.GetBaseVersion(); |
1258 int64_t server_version = e.GetServerVersion(); | 1230 int64_t server_version = e.GetServerVersion(); |
1259 bool using_unique_client_tag = !e.GetUniqueClientTag().empty(); | 1231 bool using_unique_client_tag = !e.GetUniqueClientTag().empty(); |
1260 if (CHANGES_VERSION == base_version || 0 == base_version) { | 1232 if (CHANGES_VERSION == base_version || 0 == base_version) { |
1261 ModelType model_type = e.GetModelType(); | 1233 ModelType model_type = e.GetModelType(); |
1262 bool is_client_creatable_type_root_folder = | 1234 bool is_client_creatable_type_root_folder = |
1263 parentid.IsRoot() && | 1235 parentid.IsRoot() && IsTypeWithClientGeneratedRoot(model_type) && |
1264 IsTypeWithClientGeneratedRoot(model_type) && | |
1265 e.GetUniqueServerTag() == ModelTypeToRootTag(model_type); | 1236 e.GetUniqueServerTag() == ModelTypeToRootTag(model_type); |
1266 if (e.GetIsUnappliedUpdate()) { | 1237 if (e.GetIsUnappliedUpdate()) { |
1267 // Must be a new item, or a de-duplicated unique client tag | 1238 // Must be a new item, or a de-duplicated unique client tag |
1268 // that was created both locally and remotely, or a type root folder | 1239 // that was created both locally and remotely, or a type root folder |
1269 // that was created both locally and remotely. | 1240 // that was created both locally and remotely. |
1270 if (!(using_unique_client_tag || | 1241 if (!(using_unique_client_tag || |
1271 is_client_creatable_type_root_folder)) { | 1242 is_client_creatable_type_root_folder)) { |
1272 if (!SyncAssert(e.GetIsDel(), FROM_HERE, | 1243 if (!SyncAssert(e.GetIsDel(), FROM_HERE, |
1273 "The entry should have been deleted.", trans)) | 1244 "The entry should have been deleted.", trans)) |
1274 return false; | 1245 return false; |
1275 } | 1246 } |
1276 // It came from the server, so it must have a server ID. | 1247 // It came from the server, so it must have a server ID. |
1277 if (!SyncAssert(id.ServerKnows(), FROM_HERE, | 1248 if (!SyncAssert(id.ServerKnows(), FROM_HERE, |
1278 "The id should be from a server.", | 1249 "The id should be from a server.", trans)) |
1279 trans)) | |
1280 return false; | 1250 return false; |
1281 } else { | 1251 } else { |
1282 if (e.GetIsDir()) { | 1252 if (e.GetIsDir()) { |
1283 // TODO(chron): Implement this mode if clients ever need it. | 1253 // TODO(chron): Implement this mode if clients ever need it. |
1284 // For now, you can't combine a client tag and a directory. | 1254 // For now, you can't combine a client tag and a directory. |
1285 if (!SyncAssert(!using_unique_client_tag, FROM_HERE, | 1255 if (!SyncAssert(!using_unique_client_tag, FROM_HERE, |
1286 "Directory cannot have a client tag.", | 1256 "Directory cannot have a client tag.", trans)) |
1287 trans)) | |
1288 return false; | 1257 return false; |
1289 } | 1258 } |
1290 if (is_client_creatable_type_root_folder) { | 1259 if (is_client_creatable_type_root_folder) { |
1291 // This must be a locally created type root folder. | 1260 // This must be a locally created type root folder. |
1292 if (!SyncAssert( | 1261 if (!SyncAssert( |
1293 !e.GetIsUnsynced(), FROM_HERE, | 1262 !e.GetIsUnsynced(), FROM_HERE, |
1294 "Locally created type root folders should not be unsynced.", | 1263 "Locally created type root folders should not be unsynced.", |
1295 trans)) | 1264 trans)) |
1296 return false; | 1265 return false; |
1297 | 1266 |
1298 if (!SyncAssert( | 1267 if (!SyncAssert( |
1299 !e.GetIsDel(), FROM_HERE, | 1268 !e.GetIsDel(), FROM_HERE, |
1300 "Locally created type root folders should not be deleted.", | 1269 "Locally created type root folders should not be deleted.", |
1301 trans)) | 1270 trans)) |
1302 return false; | 1271 return false; |
1303 } else { | 1272 } else { |
1304 // Should be an uncomitted item, or a successfully deleted one. | 1273 // Should be an uncomitted item, or a successfully deleted one. |
1305 if (!e.GetIsDel()) { | 1274 if (!e.GetIsDel()) { |
1306 if (!SyncAssert(e.GetIsUnsynced(), FROM_HERE, | 1275 if (!SyncAssert(e.GetIsUnsynced(), FROM_HERE, |
1307 "The item should be unsynced.", trans)) | 1276 "The item should be unsynced.", trans)) |
1308 return false; | 1277 return false; |
1309 } | 1278 } |
1310 } | 1279 } |
1311 // If the next check failed, it would imply that an item exists | 1280 // If the next check failed, it would imply that an item exists |
1312 // on the server, isn't waiting for application locally, but either | 1281 // on the server, isn't waiting for application locally, but either |
1313 // is an unsynced create or a successful delete in the local copy. | 1282 // is an unsynced create or a successful delete in the local copy. |
1314 // Either way, that's a mismatch. | 1283 // Either way, that's a mismatch. |
1315 if (!SyncAssert(0 == server_version, FROM_HERE, | 1284 if (!SyncAssert(0 == server_version, FROM_HERE, |
1316 "Server version should be zero.", | 1285 "Server version should be zero.", trans)) |
1317 trans)) | |
1318 return false; | 1286 return false; |
1319 // Items that aren't using the unique client tag should have a zero | 1287 // Items that aren't using the unique client tag should have a zero |
1320 // base version only if they have a local ID. Items with unique client | 1288 // base version only if they have a local ID. Items with unique client |
1321 // tags are allowed to use the zero base version for undeletion and | 1289 // tags are allowed to use the zero base version for undeletion and |
1322 // de-duplication; the unique client tag trumps the server ID. | 1290 // de-duplication; the unique client tag trumps the server ID. |
1323 if (!using_unique_client_tag) { | 1291 if (!using_unique_client_tag) { |
1324 if (!SyncAssert(!id.ServerKnows(), FROM_HERE, | 1292 if (!SyncAssert(!id.ServerKnows(), FROM_HERE, |
1325 "Should be a client only id.", | 1293 "Should be a client only id.", trans)) |
1326 trans)) | |
1327 return false; | 1294 return false; |
1328 } | 1295 } |
1329 } | 1296 } |
1330 } else { | 1297 } else { |
1331 if (!SyncAssert(id.ServerKnows(), | 1298 if (!SyncAssert(id.ServerKnows(), FROM_HERE, "Should be a server id.", |
1332 FROM_HERE, | |
1333 "Should be a server id.", | |
1334 trans)) | 1299 trans)) |
1335 return false; | 1300 return false; |
1336 } | 1301 } |
1337 | 1302 |
1338 // Previously we would assert that locally deleted items that have never | 1303 // Previously we would assert that locally deleted items that have never |
1339 // been synced must not be sent to the server (IS_UNSYNCED must be false). | 1304 // been synced must not be sent to the server (IS_UNSYNCED must be false). |
1340 // This is not always true in the case that an item is deleted while the | 1305 // This is not always true in the case that an item is deleted while the |
1341 // initial commit is in flight. See crbug.com/426865. | 1306 // initial commit is in flight. See crbug.com/426865. |
1342 } | 1307 } |
1343 return true; | 1308 return true; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1445 UniquePosition successor_pos = (*siblings->begin())->ref(UNIQUE_POSITION); | 1410 UniquePosition successor_pos = (*siblings->begin())->ref(UNIQUE_POSITION); |
1446 | 1411 |
1447 UniquePosition pos; | 1412 UniquePosition pos; |
1448 if (!successor_pos.IsValid()) { | 1413 if (!successor_pos.IsValid()) { |
1449 // If all our successors are of non-positionable types, just create an | 1414 // If all our successors are of non-positionable types, just create an |
1450 // initial position. We arbitrarily choose to sort invalid positions to | 1415 // initial position. We arbitrarily choose to sort invalid positions to |
1451 // the right of the valid positions. | 1416 // the right of the valid positions. |
1452 // | 1417 // |
1453 // We really shouldn't need to support this. See TODO above. | 1418 // We really shouldn't need to support this. See TODO above. |
1454 pos = UniquePosition::InitialPosition(suffix); | 1419 pos = UniquePosition::InitialPosition(suffix); |
1455 } else { | 1420 } else { |
1456 DCHECK(!siblings->empty()); | 1421 DCHECK(!siblings->empty()); |
1457 pos = UniquePosition::Before(successor_pos, suffix); | 1422 pos = UniquePosition::Before(successor_pos, suffix); |
1458 } | 1423 } |
1459 | 1424 |
1460 e->put(UNIQUE_POSITION, pos); | 1425 e->put(UNIQUE_POSITION, pos); |
1461 return; | 1426 return; |
1462 } | 1427 } |
1463 | 1428 |
1464 // We can't support placing an item after an invalid position. Fortunately, | 1429 // We can't support placing an item after an invalid position. Fortunately, |
1465 // the tests don't exercise this particular case. We should not support | 1430 // the tests don't exercise this particular case. We should not support |
1466 // siblings with invalid positions at all. See TODO above. | 1431 // siblings with invalid positions at all. See TODO above. |
1467 DCHECK(predecessor->ref(UNIQUE_POSITION).IsValid()); | 1432 DCHECK(predecessor->ref(UNIQUE_POSITION).IsValid()); |
1468 | 1433 |
1469 OrderedChildSet::const_iterator neighbour = siblings->find(predecessor); | 1434 OrderedChildSet::const_iterator neighbour = siblings->find(predecessor); |
1470 DCHECK(neighbour != siblings->end()); | 1435 DCHECK(neighbour != siblings->end()); |
1471 | 1436 |
1472 ++neighbour; | 1437 ++neighbour; |
1473 if (neighbour == siblings->end()) { | 1438 if (neighbour == siblings->end()) { |
1474 // Inserting at the end of the list. | 1439 // Inserting at the end of the list. |
1475 UniquePosition pos = UniquePosition::After( | 1440 UniquePosition pos = |
1476 predecessor->ref(UNIQUE_POSITION), | 1441 UniquePosition::After(predecessor->ref(UNIQUE_POSITION), suffix); |
1477 suffix); | |
1478 e->put(UNIQUE_POSITION, pos); | 1442 e->put(UNIQUE_POSITION, pos); |
1479 return; | 1443 return; |
1480 } | 1444 } |
1481 | 1445 |
1482 EntryKernel* successor = *neighbour; | 1446 EntryKernel* successor = *neighbour; |
1483 | 1447 |
1484 // Another mixed valid and invalid position case. This one could be supported | 1448 // Another mixed valid and invalid position case. This one could be supported |
1485 // in theory, but we're trying to deprecate support for siblings with and | 1449 // in theory, but we're trying to deprecate support for siblings with and |
1486 // without valid positions. See TODO above. | 1450 // without valid positions. See TODO above. |
1487 // Using a release CHECK here because the following UniquePosition::Between | 1451 // Using a release CHECK here because the following UniquePosition::Between |
1488 // call crashes anyway when the position string is empty (see crbug/332371). | 1452 // call crashes anyway when the position string is empty (see crbug/332371). |
1489 CHECK(successor->ref(UNIQUE_POSITION).IsValid()) << *successor; | 1453 CHECK(successor->ref(UNIQUE_POSITION).IsValid()) << *successor; |
1490 | 1454 |
1491 // Finally, the normal case: inserting between two elements. | 1455 // Finally, the normal case: inserting between two elements. |
1492 UniquePosition pos = UniquePosition::Between( | 1456 UniquePosition pos = |
1493 predecessor->ref(UNIQUE_POSITION), | 1457 UniquePosition::Between(predecessor->ref(UNIQUE_POSITION), |
1494 successor->ref(UNIQUE_POSITION), | 1458 successor->ref(UNIQUE_POSITION), suffix); |
1495 suffix); | |
1496 e->put(UNIQUE_POSITION, pos); | 1459 e->put(UNIQUE_POSITION, pos); |
1497 return; | 1460 return; |
1498 } | 1461 } |
1499 | 1462 |
1500 // TODO(rlarocque): Avoid this indirection. Just return the set. | 1463 // TODO(rlarocque): Avoid this indirection. Just return the set. |
1501 void Directory::AppendChildHandles(const ScopedKernelLock& lock, | 1464 void Directory::AppendChildHandles(const ScopedKernelLock& lock, |
1502 const Id& parent_id, | 1465 const Id& parent_id, |
1503 Directory::Metahandles* result) { | 1466 Directory::Metahandles* result) { |
1504 const OrderedChildSet* children = | 1467 const OrderedChildSet* children = |
1505 kernel_->parent_child_index.GetChildren(parent_id); | 1468 kernel_->parent_child_index.GetChildren(parent_id); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1579 Directory::Kernel* Directory::kernel() { | 1542 Directory::Kernel* Directory::kernel() { |
1580 return kernel_; | 1543 return kernel_; |
1581 } | 1544 } |
1582 | 1545 |
1583 const Directory::Kernel* Directory::kernel() const { | 1546 const Directory::Kernel* Directory::kernel() const { |
1584 return kernel_; | 1547 return kernel_; |
1585 } | 1548 } |
1586 | 1549 |
1587 } // namespace syncable | 1550 } // namespace syncable |
1588 } // namespace syncer | 1551 } // namespace syncer |
OLD | NEW |