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 #ifndef SYNC_SYNCABLE_DIRECTORY_H_ | 5 #ifndef SYNC_SYNCABLE_DIRECTORY_H_ |
6 #define SYNC_SYNCABLE_DIRECTORY_H_ | 6 #define SYNC_SYNCABLE_DIRECTORY_H_ |
7 | 7 |
8 #include <deque> | 8 #include <deque> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 class WriteTransaction; | 44 class WriteTransaction; |
45 | 45 |
46 enum InvariantCheckLevel { | 46 enum InvariantCheckLevel { |
47 OFF = 0, // No checking. | 47 OFF = 0, // No checking. |
48 VERIFY_CHANGES = 1, // Checks only mutated entries. Does not check hierarchy. | 48 VERIFY_CHANGES = 1, // Checks only mutated entries. Does not check hierarchy. |
49 FULL_DB_VERIFICATION = 2 // Check every entry. This can be expensive. | 49 FULL_DB_VERIFICATION = 2 // Check every entry. This can be expensive. |
50 }; | 50 }; |
51 | 51 |
52 // Directory stores and manages EntryKernels. | 52 // Directory stores and manages EntryKernels. |
53 // | 53 // |
54 // This class is tightly coupled to several other classes (see friends). | 54 // This class is tightly coupled to several other classes via Directory::Kernel. |
| 55 // Although Directory's kernel_ is exposed via public accessor it should be |
| 56 // treated as pseudo-private. |
55 class SYNC_EXPORT Directory { | 57 class SYNC_EXPORT Directory { |
56 friend class BaseTransaction; | |
57 friend class Entry; | |
58 friend class ModelNeutralMutableEntry; | |
59 friend class MutableEntry; | |
60 friend class ReadTransaction; | |
61 friend class ScopedKernelLock; | |
62 friend class WriteTransaction; | |
63 friend class SyncableDirectoryTest; | 58 friend class SyncableDirectoryTest; |
64 friend class syncer::TestUserShare; | 59 friend class syncer::TestUserShare; |
65 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, ManageDeleteJournals); | 60 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, ManageDeleteJournals); |
66 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, | 61 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, |
67 TakeSnapshotGetsAllDirtyHandlesTest); | 62 TakeSnapshotGetsAllDirtyHandlesTest); |
68 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, | 63 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, |
69 TakeSnapshotGetsOnlyDirtyHandlesTest); | 64 TakeSnapshotGetsOnlyDirtyHandlesTest); |
70 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, | 65 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, |
71 TakeSnapshotGetsMetahandlesToPurge); | 66 TakeSnapshotGetsMetahandlesToPurge); |
72 | 67 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 ~SaveChangesSnapshot(); | 148 ~SaveChangesSnapshot(); |
154 | 149 |
155 KernelShareInfoStatus kernel_info_status; | 150 KernelShareInfoStatus kernel_info_status; |
156 PersistedKernelInfo kernel_info; | 151 PersistedKernelInfo kernel_info; |
157 EntryKernelSet dirty_metas; | 152 EntryKernelSet dirty_metas; |
158 MetahandleSet metahandles_to_purge; | 153 MetahandleSet metahandles_to_purge; |
159 EntryKernelSet delete_journals; | 154 EntryKernelSet delete_journals; |
160 MetahandleSet delete_journals_to_purge; | 155 MetahandleSet delete_journals_to_purge; |
161 }; | 156 }; |
162 | 157 |
| 158 struct Kernel { |
| 159 // |delegate| must not be NULL. |transaction_observer| must be |
| 160 // initialized. |
| 161 Kernel(const std::string& name, const KernelLoadInfo& info, |
| 162 DirectoryChangeDelegate* delegate, |
| 163 const WeakHandle<TransactionObserver>& transaction_observer); |
| 164 |
| 165 ~Kernel(); |
| 166 |
| 167 // Implements ReadTransaction / WriteTransaction using a simple lock. |
| 168 base::Lock transaction_mutex; |
| 169 |
| 170 // Protected by transaction_mutex. Used by WriteTransactions. |
| 171 int64 next_write_transaction_id; |
| 172 |
| 173 // The name of this directory. |
| 174 std::string const name; |
| 175 |
| 176 // Protects all members below. |
| 177 // The mutex effectively protects all the indices, but not the |
| 178 // entries themselves. So once a pointer to an entry is pulled |
| 179 // from the index, the mutex can be unlocked and entry read or written. |
| 180 // |
| 181 // Never hold the mutex and do anything with the database or any |
| 182 // other buffered IO. Violating this rule will result in deadlock. |
| 183 mutable base::Lock mutex; |
| 184 |
| 185 // Entries indexed by metahandle. This container is considered to be the |
| 186 // owner of all EntryKernels, which may be referened by the other |
| 187 // containers. If you remove an EntryKernel from this map, you probably |
| 188 // want to remove it from all other containers and delete it, too. |
| 189 MetahandlesMap metahandles_map; |
| 190 |
| 191 // Entries indexed by id |
| 192 IdsMap ids_map; |
| 193 |
| 194 // Entries indexed by server tag. |
| 195 // This map does not include any entries with non-existent server tags. |
| 196 TagsMap server_tags_map; |
| 197 |
| 198 // Entries indexed by client tag. |
| 199 // This map does not include any entries with non-existent client tags. |
| 200 // IS_DEL items are included. |
| 201 TagsMap client_tags_map; |
| 202 |
| 203 // Contains non-deleted items, indexed according to parent and position |
| 204 // within parent. Protected by the ScopedKernelLock. |
| 205 ParentChildIndex parent_child_index; |
| 206 |
| 207 // This index keeps track of which metahandles refer to a given attachment. |
| 208 // Think of it as the inverse of EntryKernel's AttachmentMetadata Records. |
| 209 // |
| 210 // Because entries can be undeleted (e.g. PutIsDel(false)), entries should |
| 211 // not removed from the index until they are actually deleted from memory. |
| 212 // |
| 213 // All access should go through IsAttachmentLinked, |
| 214 // RemoveFromAttachmentIndex, AddToAttachmentIndex, and |
| 215 // UpdateAttachmentIndex methods to avoid iterator invalidation errors. |
| 216 IndexByAttachmentId index_by_attachment_id; |
| 217 |
| 218 // 3 in-memory indices on bits used extremely frequently by the syncer. |
| 219 // |unapplied_update_metahandles| is keyed by the server model type. |
| 220 MetahandleSet unapplied_update_metahandles[MODEL_TYPE_COUNT]; |
| 221 MetahandleSet unsynced_metahandles; |
| 222 // Contains metahandles that are most likely dirty (though not |
| 223 // necessarily). Dirtyness is confirmed in TakeSnapshotForSaveChanges(). |
| 224 MetahandleSet dirty_metahandles; |
| 225 |
| 226 // When a purge takes place, we remove items from all our indices and stash |
| 227 // them in here so that SaveChanges can persist their permanent deletion. |
| 228 MetahandleSet metahandles_to_purge; |
| 229 |
| 230 KernelShareInfoStatus info_status; |
| 231 |
| 232 // These 3 members are backed in the share_info table, and |
| 233 // their state is marked by the flag above. |
| 234 |
| 235 // A structure containing the Directory state that is written back into the |
| 236 // database on SaveChanges. |
| 237 PersistedKernelInfo persisted_info; |
| 238 |
| 239 // A unique identifier for this account's cache db, used to generate |
| 240 // unique server IDs. No need to lock, only written at init time. |
| 241 const std::string cache_guid; |
| 242 |
| 243 // It doesn't make sense for two threads to run SaveChanges at the same |
| 244 // time; this mutex protects that activity. |
| 245 base::Lock save_changes_mutex; |
| 246 |
| 247 // The next metahandle is protected by kernel mutex. |
| 248 int64 next_metahandle; |
| 249 |
| 250 // The delegate for directory change events. Must not be NULL. |
| 251 DirectoryChangeDelegate* const delegate; |
| 252 |
| 253 // The transaction observer. |
| 254 const WeakHandle<TransactionObserver> transaction_observer; |
| 255 }; |
| 256 |
163 // Does not take ownership of |encryptor|. | 257 // Does not take ownership of |encryptor|. |
164 // |report_unrecoverable_error_function| may be NULL. | 258 // |report_unrecoverable_error_function| may be NULL. |
165 // Takes ownership of |store|. | 259 // Takes ownership of |store|. |
166 Directory( | 260 Directory( |
167 DirectoryBackingStore* store, | 261 DirectoryBackingStore* store, |
168 UnrecoverableErrorHandler* unrecoverable_error_handler, | 262 UnrecoverableErrorHandler* unrecoverable_error_handler, |
169 ReportUnrecoverableErrorFunction | 263 ReportUnrecoverableErrorFunction |
170 report_unrecoverable_error_function, | 264 report_unrecoverable_error_function, |
171 NigoriHandler* nigori_handler, | 265 NigoriHandler* nigori_handler, |
172 Cryptographer* cryptographer); | 266 Cryptographer* cryptographer); |
173 virtual ~Directory(); | 267 virtual ~Directory(); |
174 | 268 |
175 // Does not take ownership of |delegate|, which must not be NULL. | 269 // Does not take ownership of |delegate|, which must not be NULL. |
176 // Starts sending events to |delegate| if the returned result is | 270 // Starts sending events to |delegate| if the returned result is |
177 // OPENED. Note that events to |delegate| may be sent from *any* | 271 // OPENED. Note that events to |delegate| may be sent from *any* |
178 // thread. |transaction_observer| must be initialized. | 272 // thread. |transaction_observer| must be initialized. |
179 DirOpenResult Open(const std::string& name, | 273 DirOpenResult Open(const std::string& name, |
180 DirectoryChangeDelegate* delegate, | 274 DirectoryChangeDelegate* delegate, |
181 const WeakHandle<TransactionObserver>& | 275 const WeakHandle<TransactionObserver>& |
182 transaction_observer); | 276 transaction_observer); |
183 | 277 |
184 // Stops sending events to the delegate and the transaction | |
185 // observer. | |
186 void Close(); | |
187 | |
188 int64 NextMetahandle(); | 278 int64 NextMetahandle(); |
189 // Returns a negative integer unique to this client. | 279 // Returns a negative integer unique to this client. |
190 syncable::Id NextId(); | 280 syncable::Id NextId(); |
191 | 281 |
192 bool good() const { return NULL != kernel_; } | 282 bool good() const { return NULL != kernel_; } |
193 | 283 |
194 // The download progress is an opaque token provided by the sync server | 284 // The download progress is an opaque token provided by the sync server |
195 // to indicate the continuation state of the next GetUpdates operation. | 285 // to indicate the continuation state of the next GetUpdates operation. |
196 void GetDownloadProgress( | 286 void GetDownloadProgress( |
197 ModelType type, | 287 ModelType type, |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 // persist modified entry on disk. e.g. SyncBackupManager uses this to | 506 // persist modified entry on disk. e.g. SyncBackupManager uses this to |
417 // preserve sync preferences in DB on disk. | 507 // preserve sync preferences in DB on disk. |
418 void UnmarkDirtyEntry(WriteTransaction* trans, Entry* entry); | 508 void UnmarkDirtyEntry(WriteTransaction* trans, Entry* entry); |
419 | 509 |
420 // Clears |ids| and fills it with the ids of attachments that need to be | 510 // Clears |ids| and fills it with the ids of attachments that need to be |
421 // uploaded to the sync server. | 511 // uploaded to the sync server. |
422 void GetAttachmentIdsToUpload(BaseTransaction* trans, | 512 void GetAttachmentIdsToUpload(BaseTransaction* trans, |
423 ModelType type, | 513 ModelType type, |
424 AttachmentIdList* ids); | 514 AttachmentIdList* ids); |
425 | 515 |
426 private: | 516 // For new entry creation only. |
427 struct Kernel { | 517 bool InsertEntry(BaseWriteTransaction* trans, EntryKernel* entry); |
428 // |delegate| must not be NULL. |transaction_observer| must be | |
429 // initialized. | |
430 Kernel(const std::string& name, const KernelLoadInfo& info, | |
431 DirectoryChangeDelegate* delegate, | |
432 const WeakHandle<TransactionObserver>& transaction_observer); | |
433 | 518 |
434 ~Kernel(); | 519 // Update the attachment index for |metahandle| removing it from the index |
| 520 // under |old_metadata| entries and add it under |new_metadata| entries. |
| 521 void UpdateAttachmentIndex(const int64 metahandle, |
| 522 const sync_pb::AttachmentMetadata& old_metadata, |
| 523 const sync_pb::AttachmentMetadata& new_metadata); |
435 | 524 |
436 // Implements ReadTransaction / WriteTransaction using a simple lock. | 525 virtual EntryKernel* GetEntryById(const Id& id); |
437 base::Lock transaction_mutex; | 526 virtual EntryKernel* GetEntryByClientTag(const std::string& tag); |
438 | 527 EntryKernel* GetEntryByServerTag(const std::string& tag); |
439 // Protected by transaction_mutex. Used by WriteTransactions. | |
440 int64 next_write_transaction_id; | |
441 | |
442 // The name of this directory. | |
443 std::string const name; | |
444 | |
445 // Protects all members below. | |
446 // The mutex effectively protects all the indices, but not the | |
447 // entries themselves. So once a pointer to an entry is pulled | |
448 // from the index, the mutex can be unlocked and entry read or written. | |
449 // | |
450 // Never hold the mutex and do anything with the database or any | |
451 // other buffered IO. Violating this rule will result in deadlock. | |
452 base::Lock mutex; | |
453 | |
454 // Entries indexed by metahandle. This container is considered to be the | |
455 // owner of all EntryKernels, which may be referened by the other | |
456 // containers. If you remove an EntryKernel from this map, you probably | |
457 // want to remove it from all other containers and delete it, too. | |
458 MetahandlesMap metahandles_map; | |
459 | |
460 // Entries indexed by id | |
461 IdsMap ids_map; | |
462 | |
463 // Entries indexed by server tag. | |
464 // This map does not include any entries with non-existent server tags. | |
465 TagsMap server_tags_map; | |
466 | |
467 // Entries indexed by client tag. | |
468 // This map does not include any entries with non-existent client tags. | |
469 // IS_DEL items are included. | |
470 TagsMap client_tags_map; | |
471 | |
472 // Contains non-deleted items, indexed according to parent and position | |
473 // within parent. Protected by the ScopedKernelLock. | |
474 ParentChildIndex parent_child_index; | |
475 | |
476 // This index keeps track of which metahandles refer to a given attachment. | |
477 // Think of it as the inverse of EntryKernel's AttachmentMetadata Records. | |
478 // | |
479 // Because entries can be undeleted (e.g. PutIsDel(false)), entries should | |
480 // not removed from the index until they are actually deleted from memory. | |
481 // | |
482 // All access should go through IsAttachmentLinked, | |
483 // RemoveFromAttachmentIndex, AddToAttachmentIndex, and | |
484 // UpdateAttachmentIndex methods to avoid iterator invalidation errors. | |
485 IndexByAttachmentId index_by_attachment_id; | |
486 | |
487 // 3 in-memory indices on bits used extremely frequently by the syncer. | |
488 // |unapplied_update_metahandles| is keyed by the server model type. | |
489 MetahandleSet unapplied_update_metahandles[MODEL_TYPE_COUNT]; | |
490 MetahandleSet unsynced_metahandles; | |
491 // Contains metahandles that are most likely dirty (though not | |
492 // necessarily). Dirtyness is confirmed in TakeSnapshotForSaveChanges(). | |
493 MetahandleSet dirty_metahandles; | |
494 | |
495 // When a purge takes place, we remove items from all our indices and stash | |
496 // them in here so that SaveChanges can persist their permanent deletion. | |
497 MetahandleSet metahandles_to_purge; | |
498 | |
499 KernelShareInfoStatus info_status; | |
500 | |
501 // These 3 members are backed in the share_info table, and | |
502 // their state is marked by the flag above. | |
503 | |
504 // A structure containing the Directory state that is written back into the | |
505 // database on SaveChanges. | |
506 PersistedKernelInfo persisted_info; | |
507 | |
508 // A unique identifier for this account's cache db, used to generate | |
509 // unique server IDs. No need to lock, only written at init time. | |
510 const std::string cache_guid; | |
511 | |
512 // It doesn't make sense for two threads to run SaveChanges at the same | |
513 // time; this mutex protects that activity. | |
514 base::Lock save_changes_mutex; | |
515 | |
516 // The next metahandle is protected by kernel mutex. | |
517 int64 next_metahandle; | |
518 | |
519 // The delegate for directory change events. Must not be NULL. | |
520 DirectoryChangeDelegate* const delegate; | |
521 | |
522 // The transaction observer. | |
523 const WeakHandle<TransactionObserver> transaction_observer; | |
524 }; | |
525 | |
526 // You'll notice that some of these methods have two forms. One that takes a | |
527 // ScopedKernelLock and one that doesn't. The general pattern is that those | |
528 // without a ScopedKernelLock parameter construct one internally before | |
529 // calling the form that takes one. | |
530 | 528 |
531 virtual EntryKernel* GetEntryByHandle(int64 handle); | 529 virtual EntryKernel* GetEntryByHandle(int64 handle); |
532 virtual EntryKernel* GetEntryByHandle(const ScopedKernelLock& lock, | |
533 int64 metahandle); | |
534 | |
535 virtual EntryKernel* GetEntryById(const Id& id); | |
536 virtual EntryKernel* GetEntryById(const ScopedKernelLock& lock, const Id& id); | |
537 | |
538 EntryKernel* GetEntryByServerTag(const std::string& tag); | |
539 virtual EntryKernel* GetEntryByClientTag(const std::string& tag); | |
540 | |
541 // For new entry creation only | |
542 bool InsertEntry(BaseWriteTransaction* trans, EntryKernel* entry); | |
543 bool InsertEntry(const ScopedKernelLock& lock, | |
544 BaseWriteTransaction* trans, | |
545 EntryKernel* entry); | |
546 | 530 |
547 bool ReindexId(BaseWriteTransaction* trans, EntryKernel* const entry, | 531 bool ReindexId(BaseWriteTransaction* trans, EntryKernel* const entry, |
548 const Id& new_id); | 532 const Id& new_id); |
549 | 533 |
550 bool ReindexParentId(BaseWriteTransaction* trans, EntryKernel* const entry, | 534 bool ReindexParentId(BaseWriteTransaction* trans, EntryKernel* const entry, |
551 const Id& new_parent_id); | 535 const Id& new_parent_id); |
552 | 536 |
553 // Update the attachment index for |metahandle| removing it from the index | 537 // Accessors for the underlying Kernel. Although these are public methods, the |
554 // under |old_metadata| entries and add it under |new_metadata| entries. | 538 // number of classes that call these should be limited. |
555 void UpdateAttachmentIndex(const int64 metahandle, | 539 Kernel* kernel(); |
556 const sync_pb::AttachmentMetadata& old_metadata, | 540 const Kernel* kernel() const; |
557 const sync_pb::AttachmentMetadata& new_metadata); | 541 |
| 542 private: |
| 543 // You'll notice that some of the methods below are private overloads of the |
| 544 // public ones declared above. The general pattern is that the public overload |
| 545 // constructs a ScopedKernelLock before calling the corresponding private |
| 546 // overload with the held ScopedKernelLock. |
| 547 |
| 548 virtual EntryKernel* GetEntryByHandle(const ScopedKernelLock& lock, |
| 549 int64 metahandle); |
| 550 |
| 551 virtual EntryKernel* GetEntryById(const ScopedKernelLock& lock, const Id& id); |
| 552 |
| 553 bool InsertEntry(const ScopedKernelLock& lock, |
| 554 BaseWriteTransaction* trans, |
| 555 EntryKernel* entry); |
558 | 556 |
559 // Remove each of |metahandle|'s attachment ids from index_by_attachment_id. | 557 // Remove each of |metahandle|'s attachment ids from index_by_attachment_id. |
560 void RemoveFromAttachmentIndex( | 558 void RemoveFromAttachmentIndex( |
561 const ScopedKernelLock& lock, | 559 const ScopedKernelLock& lock, |
562 const int64 metahandle, | 560 const int64 metahandle, |
563 const sync_pb::AttachmentMetadata& attachment_metadata); | 561 const sync_pb::AttachmentMetadata& attachment_metadata); |
564 | 562 |
565 // Add each of |metahandle|'s attachment ids to the index_by_attachment_id. | 563 // Add each of |metahandle|'s attachment ids to the index_by_attachment_id. |
566 void AddToAttachmentIndex( | 564 void AddToAttachmentIndex( |
567 const ScopedKernelLock& lock, | 565 const ScopedKernelLock& lock, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 EntryKernel* entry, | 621 EntryKernel* entry, |
624 EntryKernelSet* entries_to_journal); | 622 EntryKernelSet* entries_to_journal); |
625 | 623 |
626 // A private version of the public GetMetaHandlesOfType for when you already | 624 // A private version of the public GetMetaHandlesOfType for when you already |
627 // have a ScopedKernelLock. | 625 // have a ScopedKernelLock. |
628 void GetMetaHandlesOfType(const ScopedKernelLock& lock, | 626 void GetMetaHandlesOfType(const ScopedKernelLock& lock, |
629 BaseTransaction* trans, | 627 BaseTransaction* trans, |
630 ModelType type, | 628 ModelType type, |
631 std::vector<int64>* result); | 629 std::vector<int64>* result); |
632 | 630 |
| 631 // Stops sending events to the delegate and the transaction |
| 632 // observer. |
| 633 void Close(); |
| 634 |
633 Kernel* kernel_; | 635 Kernel* kernel_; |
634 | 636 |
635 scoped_ptr<DirectoryBackingStore> store_; | 637 scoped_ptr<DirectoryBackingStore> store_; |
636 | 638 |
637 UnrecoverableErrorHandler* const unrecoverable_error_handler_; | 639 UnrecoverableErrorHandler* const unrecoverable_error_handler_; |
638 const ReportUnrecoverableErrorFunction report_unrecoverable_error_function_; | 640 const ReportUnrecoverableErrorFunction report_unrecoverable_error_function_; |
639 bool unrecoverable_error_set_; | 641 bool unrecoverable_error_set_; |
640 | 642 |
641 // Not owned. | 643 // Not owned. |
642 NigoriHandler* const nigori_handler_; | 644 NigoriHandler* const nigori_handler_; |
643 Cryptographer* const cryptographer_; | 645 Cryptographer* const cryptographer_; |
644 | 646 |
645 InvariantCheckLevel invariant_check_level_; | 647 InvariantCheckLevel invariant_check_level_; |
646 | 648 |
647 // Maintain deleted entries not in |kernel_| until it's verified that they | 649 // Maintain deleted entries not in |kernel_| until it's verified that they |
648 // are deleted in native models as well. | 650 // are deleted in native models as well. |
649 scoped_ptr<DeleteJournal> delete_journal_; | 651 scoped_ptr<DeleteJournal> delete_journal_; |
650 | 652 |
651 DISALLOW_COPY_AND_ASSIGN(Directory); | 653 DISALLOW_COPY_AND_ASSIGN(Directory); |
652 }; | 654 }; |
653 | 655 |
654 } // namespace syncable | 656 } // namespace syncable |
655 } // namespace syncer | 657 } // namespace syncer |
656 | 658 |
657 #endif // SYNC_SYNCABLE_DIRECTORY_H_ | 659 #endif // SYNC_SYNCABLE_DIRECTORY_H_ |
OLD | NEW |