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 3 // found in the LICENSE file. 4 5 #ifndef SYNC_SYNCABLE_DIRECTORY_H_ 6 #define SYNC_SYNCABLE_DIRECTORY_H_ 7 8 #include <deque> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "base/basictypes.h" 14 #include "base/containers/hash_tables.h" 15 #include "base/file_util.h" 16 #include "base/gtest_prod_util.h" 17 #include "sync/base/sync_export.h" 18 #include "sync/internal_api/public/util/report_unrecoverable_error_function.h" 19 #include "sync/internal_api/public/util/weak_handle.h" 20 #include "sync/syncable/dir_open_result.h" 21 #include "sync/syncable/entry_kernel.h" 22 #include "sync/syncable/metahandle_set.h" 23 #include "sync/syncable/parent_child_index.h" 24 #include "sync/syncable/syncable_delete_journal.h" 25 26 namespace syncer { 27 28 class Cryptographer; 29 class TestUserShare; 30 class UnrecoverableErrorHandler; 31 32 namespace syncable { 33 34 class BaseTransaction; 35 class DirectoryChangeDelegate; 36 class DirectoryBackingStore; 37 class NigoriHandler; 38 class ScopedKernelLock; 39 class TransactionObserver; 40 class WriteTransaction; 41 42 enum InvariantCheckLevel { 43 OFF = 0, // No checking. 44 VERIFY_CHANGES = 1, // Checks only mutated entries. Does not check hierarchy. 45 FULL_DB_VERIFICATION = 2 // Check every entry. This can be expensive. 46 }; 47 48 class SYNC_EXPORT Directory { 49 friend class BaseTransaction; 50 friend class Entry; 51 friend class MutableEntry; 52 friend class ReadTransaction; 53 friend class ScopedKernelLock; 54 friend class WriteTransaction; 55 friend class SyncableDirectoryTest; 56 friend class syncer::TestUserShare; 57 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, ManageDeleteJournals); 58 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 59 TakeSnapshotGetsAllDirtyHandlesTest); 60 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 61 TakeSnapshotGetsOnlyDirtyHandlesTest); 62 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 63 TakeSnapshotGetsMetahandlesToPurge); 64 65 public: 66 typedef std::vector<int64> Metahandles; 67 68 // Be careful when using these hash_map containers. According to the spec, 69 // inserting into them may invalidate all iterators. 70 // 71 // It gets worse, though. The Anroid STL library has a bug that means it may 72 // invalidate all iterators when you erase from the map, too. That means that 73 // you can't iterate while erasing. STLDeleteElements(), std::remove_if(), 74 // and other similar functions are off-limits too, until this bug is fixed. 75 // 76 // See http://sourceforge.net/p/stlport/bugs/239/. 77 typedef base::hash_map<int64, EntryKernel*> MetahandlesMap; 78 typedef base::hash_map<std::string, EntryKernel*> IdsMap; 79 typedef base::hash_map<std::string, EntryKernel*> TagsMap; 80 81 static const base::FilePath::CharType kSyncDatabaseFilename[]; 82 83 // The dirty/clean state of kernel fields backed by the share_info table. 84 // This is public so it can be used in SaveChangesSnapshot for persistence. 85 enum KernelShareInfoStatus { 86 KERNEL_SHARE_INFO_INVALID, 87 KERNEL_SHARE_INFO_VALID, 88 KERNEL_SHARE_INFO_DIRTY 89 }; 90 91 // Various data that the Directory::Kernel we are backing (persisting data 92 // for) needs saved across runs of the application. 93 struct SYNC_EXPORT_PRIVATE PersistedKernelInfo { 94 PersistedKernelInfo(); 95 ~PersistedKernelInfo(); 96 97 // Set the |download_progress| entry for the given model to a 98 // "first sync" start point. When such a value is sent to the server, 99 // a full download of all objects of the model will be initiated. 100 void reset_download_progress(ModelType model_type); 101 102 // Last sync timestamp fetched from the server. 103 sync_pb::DataTypeProgressMarker download_progress[MODEL_TYPE_COUNT]; 104 // Sync-side transaction version per data type. Monotonically incremented 105 // when updating native model. A copy is also saved in native model. 106 // Later out-of-sync models can be detected and fixed by comparing 107 // transaction versions of sync model and native model. 108 // TODO(hatiaol): implement detection and fixing of out-of-sync models. 109 // Bug 154858. 110 int64 transaction_version[MODEL_TYPE_COUNT]; 111 // The store birthday we were given by the server. Contents are opaque to 112 // the client. 113 std::string store_birthday; 114 // The next local ID that has not been used with this cache-GUID. 115 int64 next_id; 116 // The serialized bag of chips we were given by the server. Contents are 117 // opaque to the client. This is the serialization of a message of type 118 // ChipBag defined in sync.proto. It can contains NULL characters. 119 std::string bag_of_chips; 120 }; 121 122 // What the Directory needs on initialization to create itself and its Kernel. 123 // Filled by DirectoryBackingStore::Load. 124 struct KernelLoadInfo { 125 PersistedKernelInfo kernel_info; 126 std::string cache_guid; // Created on first initialization, never changes. 127 int64 max_metahandle; // Computed (using sql MAX aggregate) on init. 128 KernelLoadInfo() : max_metahandle(0) { 129 } 130 }; 131 132 // When the Directory is told to SaveChanges, a SaveChangesSnapshot is 133 // constructed and forms a consistent snapshot of what needs to be sent to 134 // the backing store. 135 struct SYNC_EXPORT_PRIVATE SaveChangesSnapshot { 136 SaveChangesSnapshot(); 137 ~SaveChangesSnapshot(); 138 139 KernelShareInfoStatus kernel_info_status; 140 PersistedKernelInfo kernel_info; 141 EntryKernelSet dirty_metas; 142 MetahandleSet metahandles_to_purge; 143 EntryKernelSet delete_journals; 144 MetahandleSet delete_journals_to_purge; 145 }; 146 147 // Does not take ownership of |encryptor|. 148 // |report_unrecoverable_error_function| may be NULL. 149 // Takes ownership of |store|. 150 Directory( 151 DirectoryBackingStore* store, 152 UnrecoverableErrorHandler* unrecoverable_error_handler, 153 ReportUnrecoverableErrorFunction 154 report_unrecoverable_error_function, 155 NigoriHandler* nigori_handler, 156 Cryptographer* cryptographer); 157 virtual ~Directory(); 158 159 // Does not take ownership of |delegate|, which must not be NULL. 160 // Starts sending events to |delegate| if the returned result is 161 // OPENED. Note that events to |delegate| may be sent from *any* 162 // thread. |transaction_observer| must be initialized. 163 DirOpenResult Open(const std::string& name, 164 DirectoryChangeDelegate* delegate, 165 const WeakHandle<TransactionObserver>& 166 transaction_observer); 167 168 // Stops sending events to the delegate and the transaction 169 // observer. 170 void Close(); 171 172 int64 NextMetahandle(); 173 // Returns a negative integer unique to this client. 174 syncable::Id NextId(); 175 176 bool good() const { return NULL != kernel_; } 177 178 // The download progress is an opaque token provided by the sync server 179 // to indicate the continuation state of the next GetUpdates operation. 180 void GetDownloadProgress( 181 ModelType type, 182 sync_pb::DataTypeProgressMarker* value_out) const; 183 void GetDownloadProgressAsString( 184 ModelType type, 185 std::string* value_out) const; 186 size_t GetEntriesCount() const; 187 void SetDownloadProgress( 188 ModelType type, 189 const sync_pb::DataTypeProgressMarker& value); 190 191 // Gets/Increments transaction version of a model type. Must be called when 192 // holding kernel mutex. 193 int64 GetTransactionVersion(ModelType type) const; 194 void IncrementTransactionVersion(ModelType type); 195 196 ModelTypeSet InitialSyncEndedTypes(); 197 bool InitialSyncEndedForType(ModelType type); 198 bool InitialSyncEndedForType(BaseTransaction* trans, ModelType type); 199 200 const std::string& name() const { return kernel_->name; } 201 202 // (Account) Store birthday is opaque to the client, so we keep it in the 203 // format it is in the proto buffer in case we switch to a binary birthday 204 // later. 205 std::string store_birthday() const; 206 void set_store_birthday(const std::string& store_birthday); 207 208 // (Account) Bag of chip is an opaque state used by the server to track the 209 // client. 210 std::string bag_of_chips() const; 211 void set_bag_of_chips(const std::string& bag_of_chips); 212 213 // Unique to each account / client pair. 214 std::string cache_guid() const; 215 216 // Returns a pointer to our Nigori node handler. 217 NigoriHandler* GetNigoriHandler(); 218 219 // Returns a pointer to our cryptographer. Does not transfer ownership. 220 // Not thread safe, so should only be accessed while holding a transaction. 221 Cryptographer* GetCryptographer(const BaseTransaction* trans); 222 223 // Returns true if the directory had encountered an unrecoverable error. 224 // Note: Any function in |Directory| that can be called without holding a 225 // transaction need to check if the Directory already has an unrecoverable 226 // error on it. 227 bool unrecoverable_error_set(const BaseTransaction* trans) const; 228 229 // Called to immediately report an unrecoverable error (but don't 230 // propagate it up). 231 void ReportUnrecoverableError() { 232 if (report_unrecoverable_error_function_) { 233 report_unrecoverable_error_function_(); 234 } 235 } 236 237 // Called to set the unrecoverable error on the directory and to propagate 238 // the error to upper layers. 239 void OnUnrecoverableError(const BaseTransaction* trans, 240 const tracked_objects::Location& location, 241 const std::string & message); 242 243 DeleteJournal* delete_journal(); 244 245 // Returns the child meta handles (even those for deleted/unlinked 246 // nodes) for given parent id. Clears |result| if there are no 247 // children. 248 bool GetChildHandlesById(BaseTransaction*, const Id& parent_id, 249 Metahandles* result); 250 251 // Returns the child meta handles (even those for deleted/unlinked 252 // nodes) for given meta handle. Clears |result| if there are no 253 // children. 254 bool GetChildHandlesByHandle(BaseTransaction*, int64 handle, 255 Metahandles* result); 256 257 // Counts all items under the given node, including the node itself. 258 int GetTotalNodeCount(BaseTransaction*, EntryKernel* kernel_) const; 259 260 // Returns this item's position within its parent folder. 261 // The left-most item is 0, second left-most is 1, etc. 262 int GetPositionIndex(BaseTransaction*, EntryKernel* kernel_) const; 263 264 // Returns true iff |id| has children. 265 bool HasChildren(BaseTransaction* trans, const Id& id); 266 267 // Find the first child in the positional ordering under a parent, 268 // and fill in |*first_child_id| with its id. Fills in a root Id if 269 // parent has no children. Returns true if the first child was 270 // successfully found, or false if an error was encountered. 271 Id GetFirstChildId(BaseTransaction* trans, const EntryKernel* parent); 272 273 // These functions allow one to fetch the next or previous item under 274 // the same folder. Returns the "root" ID if there is no predecessor 275 // or successor. 276 // 277 // TODO(rlarocque): These functions are used mainly for tree traversal. We 278 // should replace these with an iterator API. See crbug.com/178275. 279 syncable::Id GetPredecessorId(EntryKernel*); 280 syncable::Id GetSuccessorId(EntryKernel*); 281 282 // Places |e| as a successor to |predecessor|. If |predecessor| is NULL, 283 // |e| will be placed as the left-most item in its folder. 284 // 285 // Both |e| and |predecessor| must be valid entries under the same parent. 286 // 287 // TODO(rlarocque): This function includes limited support for placing items 288 // with valid positions (ie. Bookmarks) as siblings of items that have no set 289 // ordering (ie. Autofill items). This support is required only for tests, 290 // and should be removed. See crbug.com/178282. 291 void PutPredecessor(EntryKernel* e, EntryKernel* predecessor); 292 293 // SaveChanges works by taking a consistent snapshot of the current Directory 294 // state and indices (by deep copy) under a ReadTransaction, passing this 295 // snapshot to the backing store under no transaction, and finally cleaning 296 // up by either purging entries no longer needed (this part done under a 297 // WriteTransaction) or rolling back the dirty bits. It also uses 298 // internal locking to enforce SaveChanges operations are mutually exclusive. 299 // 300 // WARNING: THIS METHOD PERFORMS SYNCHRONOUS I/O VIA SQLITE. 301 bool SaveChanges(); 302 303 // Fill in |result| with all entry kernels. 304 void GetAllEntryKernels(BaseTransaction* trans, 305 std::vector<const EntryKernel*>* result); 306 307 // Returns the number of entities with the unsynced bit set. 308 int64 unsynced_entity_count() const; 309 310 // Get GetUnsyncedMetaHandles should only be called after SaveChanges and 311 // before any new entries have been created. The intention is that the 312 // syncer should call it from its PerformSyncQueries member. 313 void GetUnsyncedMetaHandles(BaseTransaction* trans, 314 Metahandles* result); 315 316 // Returns all server types with unapplied updates. A subset of 317 // those types can then be passed into 318 // GetUnappliedUpdateMetaHandles() below. 319 FullModelTypeSet GetServerTypesWithUnappliedUpdates( 320 BaseTransaction* trans) const; 321 322 // Get all the metahandles for unapplied updates for a given set of 323 // server types. 324 void GetUnappliedUpdateMetaHandles(BaseTransaction* trans, 325 FullModelTypeSet server_types, 326 std::vector<int64>* result); 327 328 // Get metahandle counts for various criteria to show on the 329 // about:sync page. The information is computed on the fly 330 // each time. If this results in a significant performance hit, 331 // additional data structures can be added to cache results. 332 void CollectMetaHandleCounts(std::vector<int>* num_entries_by_type, 333 std::vector<int>* num_to_delete_entries_by_type); 334 335 // Sets the level of invariant checking performed after transactions. 336 void SetInvariantCheckLevel(InvariantCheckLevel check_level); 337 338 // Checks tree metadata consistency following a transaction. It is intended 339 // to provide a reasonable tradeoff between performance and comprehensiveness 340 // and may be used in release code. 341 bool CheckInvariantsOnTransactionClose( 342 syncable::BaseTransaction* trans, 343 const EntryKernelMutationMap& mutations); 344 345 // Forces a full check of the directory. This operation may be slow and 346 // should not be invoked outside of tests. 347 bool FullyCheckTreeInvariants(BaseTransaction *trans); 348 349 // Purges data associated with any entries whose ModelType or ServerModelType 350 // is found in |disabled_types|, from sync directory _both_ in memory and on 351 // disk. Only valid, "real" model types are allowed in |disabled_types| (see 352 // model_type.h for definitions). 353 // 1. Data associated with |types_to_journal| is saved in the delete journal 354 // to help prevent back-from-dead problem due to offline delete in the next 355 // sync session. |types_to_journal| must be a subset of |disabled_types|. 356 // 2. Data associated with |types_to_unapply| is reset to an "unapplied" 357 // state, wherein all local data is deleted and IS_UNAPPLIED is set to true. 358 // This is useful when there's no benefit in discarding the currently 359 // downloaded state, such as when there are cryptographer errors. 360 // |types_to_unapply| must be a subset of |disabled_types|. 361 // 3. All other data is purged entirely. 362 // Note: "Purge" is just meant to distinguish from "deleting" entries, which 363 // means something different in the syncable namespace. 364 // WARNING! This can be real slow, as it iterates over all entries. 365 // WARNING! Performs synchronous I/O. 366 // Returns: true on success, false if an error was encountered. 367 virtual bool PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, 368 ModelTypeSet types_to_journal, 369 ModelTypeSet types_to_unapply); 370 371 protected: // for friends, mainly used by Entry constructors 372 virtual EntryKernel* GetEntryByHandle(int64 handle); 373 virtual EntryKernel* GetEntryByHandle(int64 metahandle, 374 ScopedKernelLock* lock); 375 virtual EntryKernel* GetEntryById(const Id& id); 376 EntryKernel* GetEntryByServerTag(const std::string& tag); 377 virtual EntryKernel* GetEntryByClientTag(const std::string& tag); 378 EntryKernel* GetRootEntry(); 379 bool ReindexId(WriteTransaction* trans, EntryKernel* const entry, 380 const Id& new_id); 381 bool ReindexParentId(WriteTransaction* trans, EntryKernel* const entry, 382 const Id& new_parent_id); 383 void ClearDirtyMetahandles(); 384 385 DirOpenResult OpenImpl( 386 const std::string& name, 387 DirectoryChangeDelegate* delegate, 388 const WeakHandle<TransactionObserver>& transaction_observer); 389 390 private: 391 struct Kernel { 392 // |delegate| must not be NULL. |transaction_observer| must be 393 // initialized. 394 Kernel(const std::string& name, const KernelLoadInfo& info, 395 DirectoryChangeDelegate* delegate, 396 const WeakHandle<TransactionObserver>& transaction_observer); 397 398 ~Kernel(); 399 400 // Implements ReadTransaction / WriteTransaction using a simple lock. 401 base::Lock transaction_mutex; 402 403 // Protected by transaction_mutex. Used by WriteTransactions. 404 int64 next_write_transaction_id; 405 406 // The name of this directory. 407 std::string const name; 408 409 // Protects all members below. 410 // The mutex effectively protects all the indices, but not the 411 // entries themselves. So once a pointer to an entry is pulled 412 // from the index, the mutex can be unlocked and entry read or written. 413 // 414 // Never hold the mutex and do anything with the database or any 415 // other buffered IO. Violating this rule will result in deadlock. 416 base::Lock mutex; 417 418 // Entries indexed by metahandle. This container is considered to be the 419 // owner of all EntryKernels, which may be referened by the other 420 // containers. If you remove an EntryKernel from this map, you probably 421 // want to remove it from all other containers and delete it, too. 422 MetahandlesMap metahandles_map; 423 424 // Entries indexed by id 425 IdsMap ids_map; 426 427 // Entries indexed by server tag. 428 // This map does not include any entries with non-existent server tags. 429 TagsMap server_tags_map; 430 431 // Entries indexed by client tag. 432 // This map does not include any entries with non-existent client tags. 433 // IS_DEL items are included. 434 TagsMap client_tags_map; 435 436 // Contains non-deleted items, indexed according to parent and position 437 // within parent. Protected by the ScopedKernelLock. 438 ParentChildIndex parent_child_index; 439 440 // 3 in-memory indices on bits used extremely frequently by the syncer. 441 // |unapplied_update_metahandles| is keyed by the server model type. 442 MetahandleSet unapplied_update_metahandles[MODEL_TYPE_COUNT]; 443 MetahandleSet unsynced_metahandles; 444 // Contains metahandles that are most likely dirty (though not 445 // necessarily). Dirtyness is confirmed in TakeSnapshotForSaveChanges(). 446 MetahandleSet dirty_metahandles; 447 448 // When a purge takes place, we remove items from all our indices and stash 449 // them in here so that SaveChanges can persist their permanent deletion. 450 MetahandleSet metahandles_to_purge; 451 452 KernelShareInfoStatus info_status; 453 454 // These 3 members are backed in the share_info table, and 455 // their state is marked by the flag above. 456 457 // A structure containing the Directory state that is written back into the 458 // database on SaveChanges. 459 PersistedKernelInfo persisted_info; 460 461 // A unique identifier for this account's cache db, used to generate 462 // unique server IDs. No need to lock, only written at init time. 463 const std::string cache_guid; 464 465 // It doesn't make sense for two threads to run SaveChanges at the same 466 // time; this mutex protects that activity. 467 base::Lock save_changes_mutex; 468 469 // The next metahandle is protected by kernel mutex. 470 int64 next_metahandle; 471 472 // The delegate for directory change events. Must not be NULL. 473 DirectoryChangeDelegate* const delegate; 474 475 // The transaction observer. 476 const WeakHandle<TransactionObserver> transaction_observer; 477 }; 478 479 // These private versions expect the kernel lock to already be held 480 // before calling. 481 EntryKernel* GetEntryById(const Id& id, ScopedKernelLock* const lock); 482 483 // A helper that implements the logic of checking tree invariants. 484 bool CheckTreeInvariants(syncable::BaseTransaction* trans, 485 const MetahandleSet& handles); 486 487 // Helper to prime metahandles_map, ids_map, parent_child_index, 488 // unsynced_metahandles, unapplied_update_metahandles, server_tags_map and 489 // client_tags_map from metahandles_index. The input |handles_map| will be 490 // cleared during the initialization process. 491 void InitializeIndices(MetahandlesMap* handles_map); 492 493 // Constructs a consistent snapshot of the current Directory state and 494 // indices (by deep copy) under a ReadTransaction for use in |snapshot|. 495 // See SaveChanges() for more information. 496 void TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot); 497 498 // Purges from memory any unused, safe to remove entries that were 499 // successfully deleted on disk as a result of the SaveChanges that processed 500 // |snapshot|. See SaveChanges() for more information. 501 bool VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot); 502 503 // Rolls back dirty bits in the event that the SaveChanges that 504 // processed |snapshot| failed, for example, due to no disk space. 505 void HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot); 506 507 // For new entry creation only 508 bool InsertEntry(WriteTransaction* trans, 509 EntryKernel* entry, ScopedKernelLock* lock); 510 bool InsertEntry(WriteTransaction* trans, EntryKernel* entry); 511 512 // Used by CheckTreeInvariants 513 void GetAllMetaHandles(BaseTransaction* trans, MetahandleSet* result); 514 bool SafeToPurgeFromMemory(WriteTransaction* trans, 515 const EntryKernel* const entry) const; 516 517 // A helper used by GetTotalNodeCount. 518 void GetChildSetForKernel( 519 BaseTransaction*, 520 EntryKernel* kernel_, 521 std::deque<const OrderedChildSet*>* child_sets) const; 522 523 // Append the handles of the children of |parent_id| to |result|. 524 void AppendChildHandles( 525 const ScopedKernelLock& lock, 526 const Id& parent_id, Directory::Metahandles* result); 527 528 // Helper methods used by PurgeDisabledTypes. 529 void UnapplyEntry(EntryKernel* entry); 530 void DeleteEntry(bool save_to_journal, 531 EntryKernel* entry, 532 EntryKernelSet* entries_to_journal); 533 534 Kernel* kernel_; 535 536 scoped_ptr<DirectoryBackingStore> store_; 537 538 UnrecoverableErrorHandler* const unrecoverable_error_handler_; 539 const ReportUnrecoverableErrorFunction report_unrecoverable_error_function_; 540 bool unrecoverable_error_set_; 541 542 // Not owned. 543 NigoriHandler* const nigori_handler_; 544 Cryptographer* const cryptographer_; 545 546 InvariantCheckLevel invariant_check_level_; 547 548 // Maintain deleted entries not in |kernel_| until it's verified that they 549 // are deleted in native models as well. 550 scoped_ptr<DeleteJournal> delete_journal_; 551 552 DISALLOW_COPY_AND_ASSIGN(Directory); 553 }; 554 555 } // namespace syncable 556 } // namespace syncer 557 558 #endif // SYNC_SYNCABLE_DIRECTORY_H_ 559