syncable.h revision dc0f95d653279beabeb9817299e2902918ba123e
1// Copyright (c) 2010 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 CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_ 6#define CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_ 7#pragma once 8 9#include <algorithm> 10#include <bitset> 11#include <iosfwd> 12#include <limits> 13#include <set> 14#include <string> 15#include <vector> 16 17#include "base/atomicops.h" 18#include "base/basictypes.h" 19#include "base/file_path.h" 20#include "base/gtest_prod_util.h" 21#include "base/synchronization/lock.h" 22#include "base/time.h" 23#include "chrome/browser/sync/protocol/sync.pb.h" 24#include "chrome/browser/sync/syncable/autofill_migration.h" 25#include "chrome/browser/sync/syncable/blob.h" 26#include "chrome/browser/sync/syncable/dir_open_result.h" 27#include "chrome/browser/sync/syncable/directory_event.h" 28#include "chrome/browser/sync/syncable/syncable_id.h" 29#include "chrome/browser/sync/syncable/model_type.h" 30#include "chrome/browser/sync/util/channel.h" 31#include "chrome/browser/sync/util/dbgq.h" 32#include "chrome/common/deprecated/event_sys.h" 33 34struct PurgeInfo; 35 36namespace sync_api { 37class ReadTransaction; 38class WriteNode; 39class ReadNode; 40} 41 42namespace syncable { 43class Entry; 44 45std::ostream& operator<<(std::ostream& s, const Entry& e); 46 47class DirectoryBackingStore; 48 49static const int64 kInvalidMetaHandle = 0; 50 51enum { 52 BEGIN_FIELDS = 0, 53 INT64_FIELDS_BEGIN = BEGIN_FIELDS 54}; 55 56enum MetahandleField { 57 // Primary key into the table. Keep this as a handle to the meta entry 58 // across transactions. 59 META_HANDLE = INT64_FIELDS_BEGIN 60}; 61 62enum BaseVersion { 63 // After initial upload, the version is controlled by the server, and is 64 // increased whenever the data or metadata changes on the server. 65 BASE_VERSION = META_HANDLE + 1, 66}; 67 68enum Int64Field { 69 SERVER_VERSION = BASE_VERSION + 1, 70 MTIME, 71 SERVER_MTIME, 72 CTIME, 73 SERVER_CTIME, 74 75 // A numeric position value that indicates the relative ordering of 76 // this object among its siblings. 77 SERVER_POSITION_IN_PARENT, 78 79 LOCAL_EXTERNAL_ID, // ID of an item in the external local storage that this 80 // entry is associated with. (such as bookmarks.js) 81 82 INT64_FIELDS_END 83}; 84 85enum { 86 INT64_FIELDS_COUNT = INT64_FIELDS_END, 87 ID_FIELDS_BEGIN = INT64_FIELDS_END, 88}; 89 90enum IdField { 91 // Code in InitializeTables relies on ID being the first IdField value. 92 ID = ID_FIELDS_BEGIN, 93 PARENT_ID, 94 SERVER_PARENT_ID, 95 96 PREV_ID, 97 NEXT_ID, 98 ID_FIELDS_END 99}; 100 101enum { 102 ID_FIELDS_COUNT = ID_FIELDS_END - ID_FIELDS_BEGIN, 103 BIT_FIELDS_BEGIN = ID_FIELDS_END 104}; 105 106enum IndexedBitField { 107 IS_UNSYNCED = BIT_FIELDS_BEGIN, 108 IS_UNAPPLIED_UPDATE, 109 INDEXED_BIT_FIELDS_END, 110}; 111 112enum IsDelField { 113 IS_DEL = INDEXED_BIT_FIELDS_END, 114}; 115 116enum BitField { 117 IS_DIR = IS_DEL + 1, 118 SERVER_IS_DIR, 119 SERVER_IS_DEL, 120 BIT_FIELDS_END 121}; 122 123enum { 124 BIT_FIELDS_COUNT = BIT_FIELDS_END - BIT_FIELDS_BEGIN, 125 STRING_FIELDS_BEGIN = BIT_FIELDS_END 126}; 127 128enum StringField { 129 // Name, will be truncated by server. Can be duplicated in a folder. 130 NON_UNIQUE_NAME = STRING_FIELDS_BEGIN, 131 // The server version of |NON_UNIQUE_NAME|. 132 SERVER_NON_UNIQUE_NAME, 133 134 // A tag string which identifies this node as a particular top-level 135 // permanent object. The tag can be thought of as a unique key that 136 // identifies a singleton instance. 137 UNIQUE_SERVER_TAG, // Tagged by the server 138 UNIQUE_CLIENT_TAG, // Tagged by the client 139 STRING_FIELDS_END, 140}; 141 142enum { 143 STRING_FIELDS_COUNT = STRING_FIELDS_END - STRING_FIELDS_BEGIN, 144 PROTO_FIELDS_BEGIN = STRING_FIELDS_END 145}; 146 147// From looking at the sqlite3 docs, it's not directly stated, but it 148// seems the overhead for storing a NULL blob is very small. 149enum ProtoField { 150 SPECIFICS = PROTO_FIELDS_BEGIN, 151 SERVER_SPECIFICS, 152 PROTO_FIELDS_END, 153}; 154 155enum { 156 PROTO_FIELDS_COUNT = PROTO_FIELDS_END - PROTO_FIELDS_BEGIN 157}; 158 159enum { 160 FIELD_COUNT = PROTO_FIELDS_END, 161 // Past this point we have temporaries, stored in memory only. 162 BEGIN_TEMPS = PROTO_FIELDS_END, 163 BIT_TEMPS_BEGIN = BEGIN_TEMPS, 164}; 165 166enum BitTemp { 167 SYNCING = BIT_TEMPS_BEGIN, 168 BIT_TEMPS_END, 169}; 170 171enum { 172 BIT_TEMPS_COUNT = BIT_TEMPS_END - BIT_TEMPS_BEGIN 173}; 174 175class BaseTransaction; 176class WriteTransaction; 177class ReadTransaction; 178class Directory; 179class ScopedDirLookup; 180 181// Instead of: 182// Entry e = transaction.GetById(id); 183// use: 184// Entry e(transaction, GET_BY_ID, id); 185// 186// Why? The former would require a copy constructor, and it would be difficult 187// to enforce that an entry never outlived its transaction if there were a copy 188// constructor. 189enum GetById { 190 GET_BY_ID 191}; 192 193enum GetByClientTag { 194 GET_BY_CLIENT_TAG 195}; 196 197enum GetByServerTag { 198 GET_BY_SERVER_TAG 199}; 200 201enum GetByHandle { 202 GET_BY_HANDLE 203}; 204 205enum Create { 206 CREATE 207}; 208 209enum CreateNewUpdateItem { 210 CREATE_NEW_UPDATE_ITEM 211}; 212 213typedef std::set<int64> MetahandleSet; 214 215// Why the singular enums? So the code compile-time dispatches instead of 216// runtime dispatches as it would with a single enum and an if() statement. 217 218// The EntryKernel class contains the actual data for an entry. 219struct EntryKernel { 220 private: 221 std::string string_fields[STRING_FIELDS_COUNT]; 222 sync_pb::EntitySpecifics specifics_fields[PROTO_FIELDS_COUNT]; 223 int64 int64_fields[INT64_FIELDS_COUNT]; 224 Id id_fields[ID_FIELDS_COUNT]; 225 std::bitset<BIT_FIELDS_COUNT> bit_fields; 226 std::bitset<BIT_TEMPS_COUNT> bit_temps; 227 228 public: 229 EntryKernel(); 230 ~EntryKernel(); 231 232 // Set the dirty bit, and optionally add this entry's metahandle to 233 // a provided index on dirty bits in |dirty_index|. Parameter may be null, 234 // and will result only in setting the dirty bit of this entry. 235 inline void mark_dirty(syncable::MetahandleSet* dirty_index) { 236 if (!dirty_ && dirty_index) { 237 DCHECK_NE(0, ref(META_HANDLE)); 238 dirty_index->insert(ref(META_HANDLE)); 239 } 240 dirty_ = true; 241 } 242 243 // Clear the dirty bit, and optionally remove this entry's metahandle from 244 // a provided index on dirty bits in |dirty_index|. Parameter may be null, 245 // and will result only in clearing dirty bit of this entry. 246 inline void clear_dirty(syncable::MetahandleSet* dirty_index) { 247 if (dirty_ && dirty_index) { 248 DCHECK_NE(0, ref(META_HANDLE)); 249 dirty_index->erase(ref(META_HANDLE)); 250 } 251 dirty_ = false; 252 } 253 254 inline bool is_dirty() const { 255 return dirty_; 256 } 257 258 // Setters. 259 inline void put(MetahandleField field, int64 value) { 260 int64_fields[field - INT64_FIELDS_BEGIN] = value; 261 } 262 inline void put(Int64Field field, int64 value) { 263 int64_fields[field - INT64_FIELDS_BEGIN] = value; 264 } 265 inline void put(IdField field, const Id& value) { 266 id_fields[field - ID_FIELDS_BEGIN] = value; 267 } 268 inline void put(BaseVersion field, int64 value) { 269 int64_fields[field - INT64_FIELDS_BEGIN] = value; 270 } 271 inline void put(IndexedBitField field, bool value) { 272 bit_fields[field - BIT_FIELDS_BEGIN] = value; 273 } 274 inline void put(IsDelField field, bool value) { 275 bit_fields[field - BIT_FIELDS_BEGIN] = value; 276 } 277 inline void put(BitField field, bool value) { 278 bit_fields[field - BIT_FIELDS_BEGIN] = value; 279 } 280 inline void put(StringField field, const std::string& value) { 281 string_fields[field - STRING_FIELDS_BEGIN] = value; 282 } 283 inline void put(ProtoField field, const sync_pb::EntitySpecifics& value) { 284 specifics_fields[field - PROTO_FIELDS_BEGIN].CopyFrom(value); 285 } 286 inline void put(BitTemp field, bool value) { 287 bit_temps[field - BIT_TEMPS_BEGIN] = value; 288 } 289 290 // Const ref getters. 291 inline int64 ref(MetahandleField field) const { 292 return int64_fields[field - INT64_FIELDS_BEGIN]; 293 } 294 inline int64 ref(Int64Field field) const { 295 return int64_fields[field - INT64_FIELDS_BEGIN]; 296 } 297 inline const Id& ref(IdField field) const { 298 return id_fields[field - ID_FIELDS_BEGIN]; 299 } 300 inline int64 ref(BaseVersion field) const { 301 return int64_fields[field - INT64_FIELDS_BEGIN]; 302 } 303 inline bool ref(IndexedBitField field) const { 304 return bit_fields[field - BIT_FIELDS_BEGIN]; 305 } 306 inline bool ref(IsDelField field) const { 307 return bit_fields[field - BIT_FIELDS_BEGIN]; 308 } 309 inline bool ref(BitField field) const { 310 return bit_fields[field - BIT_FIELDS_BEGIN]; 311 } 312 inline const std::string& ref(StringField field) const { 313 return string_fields[field - STRING_FIELDS_BEGIN]; 314 } 315 inline const sync_pb::EntitySpecifics& ref(ProtoField field) const { 316 return specifics_fields[field - PROTO_FIELDS_BEGIN]; 317 } 318 inline bool ref(BitTemp field) const { 319 return bit_temps[field - BIT_TEMPS_BEGIN]; 320 } 321 322 // Non-const, mutable ref getters for object types only. 323 inline std::string& mutable_ref(StringField field) { 324 return string_fields[field - STRING_FIELDS_BEGIN]; 325 } 326 inline sync_pb::EntitySpecifics& mutable_ref(ProtoField field) { 327 return specifics_fields[field - PROTO_FIELDS_BEGIN]; 328 } 329 inline Id& mutable_ref(IdField field) { 330 return id_fields[field - ID_FIELDS_BEGIN]; 331 } 332 333 private: 334 // Tracks whether this entry needs to be saved to the database. 335 bool dirty_; 336}; 337 338// A read-only meta entry. 339class Entry { 340 friend class Directory; 341 friend std::ostream& operator << (std::ostream& s, const Entry& e); 342 343 public: 344 // After constructing, you must check good() to test whether the Get 345 // succeeded. 346 Entry(BaseTransaction* trans, GetByHandle, int64 handle); 347 Entry(BaseTransaction* trans, GetById, const Id& id); 348 Entry(BaseTransaction* trans, GetByServerTag, const std::string& tag); 349 Entry(BaseTransaction* trans, GetByClientTag, const std::string& tag); 350 351 bool good() const { return 0 != kernel_; } 352 353 BaseTransaction* trans() const { return basetrans_; } 354 355 // Field accessors. 356 inline int64 Get(MetahandleField field) const { 357 DCHECK(kernel_); 358 return kernel_->ref(field); 359 } 360 inline Id Get(IdField field) const { 361 DCHECK(kernel_); 362 return kernel_->ref(field); 363 } 364 inline int64 Get(Int64Field field) const { 365 DCHECK(kernel_); 366 return kernel_->ref(field); 367 } 368 inline int64 Get(BaseVersion field) const { 369 DCHECK(kernel_); 370 return kernel_->ref(field); 371 } 372 inline bool Get(IndexedBitField field) const { 373 DCHECK(kernel_); 374 return kernel_->ref(field); 375 } 376 inline bool Get(IsDelField field) const { 377 DCHECK(kernel_); 378 return kernel_->ref(field); 379 } 380 inline bool Get(BitField field) const { 381 DCHECK(kernel_); 382 return kernel_->ref(field); 383 } 384 const std::string& Get(StringField field) const; 385 inline const sync_pb::EntitySpecifics& Get(ProtoField field) const { 386 DCHECK(kernel_); 387 return kernel_->ref(field); 388 } 389 inline bool Get(BitTemp field) const { 390 DCHECK(kernel_); 391 return kernel_->ref(field); 392 } 393 394 ModelType GetServerModelType() const; 395 ModelType GetModelType() const; 396 397 // If this returns false, we shouldn't bother maintaining 398 // a position value (sibling ordering) for this item. 399 bool ShouldMaintainPosition() const { 400 return GetModelType() == BOOKMARKS; 401 } 402 403 inline bool ExistsOnClientBecauseNameIsNonEmpty() const { 404 DCHECK(kernel_); 405 return !kernel_->ref(NON_UNIQUE_NAME).empty(); 406 } 407 408 inline bool IsRoot() const { 409 DCHECK(kernel_); 410 return kernel_->ref(ID).IsRoot(); 411 } 412 413 Directory* dir() const; 414 415 const EntryKernel GetKernelCopy() const { 416 return *kernel_; 417 } 418 419 // Compute a local predecessor position for |update_item|, based on its 420 // absolute server position. The returned ID will be a valid predecessor 421 // under SERVER_PARENT_ID that is consistent with the 422 // SERVER_POSITION_IN_PARENT ordering. 423 Id ComputePrevIdFromServerPosition(const Id& parent_id) const; 424 425 protected: // Don't allow creation on heap, except by sync API wrappers. 426 friend class sync_api::ReadNode; 427 void* operator new(size_t size) { return (::operator new)(size); } 428 429 inline Entry(BaseTransaction* trans) 430 : basetrans_(trans), 431 kernel_(NULL) { } 432 433 protected: 434 435 BaseTransaction* const basetrans_; 436 437 EntryKernel* kernel_; 438 439 DISALLOW_COPY_AND_ASSIGN(Entry); 440}; 441 442// A mutable meta entry. Changes get committed to the database when the 443// WriteTransaction is destroyed. 444class MutableEntry : public Entry { 445 friend class WriteTransaction; 446 friend class Directory; 447 void Init(WriteTransaction* trans, const Id& parent_id, 448 const std::string& name); 449 public: 450 MutableEntry(WriteTransaction* trans, Create, const Id& parent_id, 451 const std::string& name); 452 MutableEntry(WriteTransaction* trans, CreateNewUpdateItem, const Id& id); 453 MutableEntry(WriteTransaction* trans, GetByHandle, int64); 454 MutableEntry(WriteTransaction* trans, GetById, const Id&); 455 MutableEntry(WriteTransaction* trans, GetByClientTag, const std::string& tag); 456 MutableEntry(WriteTransaction* trans, GetByServerTag, const std::string& tag); 457 458 inline WriteTransaction* write_transaction() const { 459 return write_transaction_; 460 } 461 462 // Field Accessors. Some of them trigger the re-indexing of the entry. 463 // Return true on success, return false on failure, which means 464 // that putting the value would have caused a duplicate in the index. 465 // TODO(chron): Remove some of these unecessary return values. 466 bool Put(Int64Field field, const int64& value); 467 bool Put(IdField field, const Id& value); 468 469 // Do a simple property-only update if the PARENT_ID field. Use with caution. 470 // 471 // The normal Put(IS_PARENT) call will move the item to the front of the 472 // sibling order to maintain the linked list invariants when the parent 473 // changes. That's usually what you want to do, but it's inappropriate 474 // when the caller is trying to change the parent ID of a the whole set 475 // of children (e.g. because the ID changed during a commit). For those 476 // cases, there's this function. It will corrupt the sibling ordering 477 // if you're not careful. 478 void PutParentIdPropertyOnly(const Id& parent_id); 479 480 bool Put(StringField field, const std::string& value); 481 bool Put(BaseVersion field, int64 value); 482 483 bool Put(ProtoField field, const sync_pb::EntitySpecifics& value); 484 inline bool Put(BitField field, bool value) { 485 return PutField(field, value); 486 } 487 inline bool Put(IsDelField field, bool value) { 488 return PutIsDel(value); 489 } 490 bool Put(IndexedBitField field, bool value); 491 492 // Sets the position of this item, and updates the entry kernels of the 493 // adjacent siblings so that list invariants are maintained. Returns false 494 // and fails if |predecessor_id| does not identify a sibling. Pass the root 495 // ID to put the node in first position. 496 bool PutPredecessor(const Id& predecessor_id); 497 498 inline bool Put(BitTemp field, bool value) { 499 return PutTemp(field, value); 500 } 501 502 protected: 503 syncable::MetahandleSet* GetDirtyIndexHelper(); 504 505 template <typename FieldType, typename ValueType> 506 inline bool PutField(FieldType field, const ValueType& value) { 507 DCHECK(kernel_); 508 if (kernel_->ref(field) != value) { 509 kernel_->put(field, value); 510 kernel_->mark_dirty(GetDirtyIndexHelper()); 511 } 512 return true; 513 } 514 515 template <typename TempType, typename ValueType> 516 inline bool PutTemp(TempType field, const ValueType& value) { 517 DCHECK(kernel_); 518 kernel_->put(field, value); 519 return true; 520 } 521 522 bool PutIsDel(bool value); 523 524 private: // Don't allow creation on heap, except by sync API wrappers. 525 friend class sync_api::WriteNode; 526 void* operator new(size_t size) { return (::operator new)(size); } 527 528 bool PutImpl(StringField field, const std::string& value); 529 bool PutUniqueClientTag(const std::string& value); 530 531 // Adjusts the successor and predecessor entries so that they no longer 532 // refer to this entry. 533 void UnlinkFromOrder(); 534 535 // Kind of redundant. We should reduce the number of pointers 536 // floating around if at all possible. Could we store this in Directory? 537 // Scope: Set on construction, never changed after that. 538 WriteTransaction* const write_transaction_; 539 540 protected: 541 MutableEntry(); 542 543 DISALLOW_COPY_AND_ASSIGN(MutableEntry); 544}; 545 546class LessParentIdAndHandle; 547template <typename FieldType, FieldType field_index> 548class LessField; 549class LessEntryMetaHandles { 550 public: 551 inline bool operator()(const syncable::EntryKernel& a, 552 const syncable::EntryKernel& b) const { 553 return a.ref(META_HANDLE) < b.ref(META_HANDLE); 554 } 555}; 556typedef std::set<EntryKernel, LessEntryMetaHandles> OriginalEntries; 557 558// How syncable indices & Indexers work. 559// 560// The syncable Directory maintains several indices on the Entries it tracks. 561// The indices follow a common pattern: 562// (a) The index allows efficient lookup of an Entry* with particular 563// field values. This is done by use of a std::set<> and a custom 564// comparator. 565// (b) There may be conditions for inclusion in the index -- for example, 566// deleted items might not be indexed. 567// (c) Because the index set contains only Entry*, one must be careful 568// to remove Entries from the set before updating the value of 569// an indexed field. 570// The traits of an index are a Comparator (to define the set ordering) and a 571// ShouldInclude function (to define the conditions for inclusion). For each 572// index, the traits are grouped into a class called an Indexer which 573// can be used as a template type parameter. 574 575// Traits type for metahandle index. 576struct MetahandleIndexer { 577 // This index is of the metahandle field values. 578 typedef LessField<MetahandleField, META_HANDLE> Comparator; 579 580 // This index includes all entries. 581 inline static bool ShouldInclude(const EntryKernel* a) { 582 return true; 583 } 584}; 585 586// Traits type for ID field index. 587struct IdIndexer { 588 // This index is of the ID field values. 589 typedef LessField<IdField, ID> Comparator; 590 591 // This index includes all entries. 592 inline static bool ShouldInclude(const EntryKernel* a) { 593 return true; 594 } 595}; 596 597// Traits type for unique client tag index. 598struct ClientTagIndexer { 599 // This index is of the client-tag values. 600 typedef LessField<StringField, UNIQUE_CLIENT_TAG> Comparator; 601 602 // Items are only in this index if they have a non-empty client tag value. 603 static bool ShouldInclude(const EntryKernel* a); 604}; 605 606// This index contains EntryKernels ordered by parent ID and metahandle. 607// It allows efficient lookup of the children of a given parent. 608struct ParentIdAndHandleIndexer { 609 // This index is of the parent ID and metahandle. We use a custom 610 // comparator. 611 class Comparator { 612 public: 613 bool operator() (const syncable::EntryKernel* a, 614 const syncable::EntryKernel* b) const; 615 }; 616 617 // This index does not include deleted items. 618 static bool ShouldInclude(const EntryKernel* a); 619}; 620 621// Given an Indexer providing the semantics of an index, defines the 622// set type used to actually contain the index. 623template <typename Indexer> 624struct Index { 625 typedef std::set<EntryKernel*, typename Indexer::Comparator> Set; 626}; 627 628// a WriteTransaction has a writer tag describing which body of code is doing 629// the write. This is defined up here since DirectoryChangeEvent also contains 630// one. 631enum WriterTag { 632 INVALID, 633 SYNCER, 634 AUTHWATCHER, 635 UNITTEST, 636 VACUUM_AFTER_SAVE, 637 PURGE_ENTRIES, 638 SYNCAPI 639}; 640 641// A separate Event type and channel for very frequent changes, caused 642// by anything, not just the user. 643struct DirectoryChangeEvent { 644 enum { 645 // Means listener should go through list of original entries and 646 // calculate what it needs to notify. It should *not* call any 647 // callbacks or attempt to lock anything because a 648 // WriteTransaction is being held until the listener returns. 649 CALCULATE_CHANGES, 650 // Means the WriteTransaction is ending, and this is the absolute 651 // last chance to perform any read operations in the current transaction. 652 // It is not recommended that the listener perform any writes. 653 TRANSACTION_ENDING, 654 // Means the WriteTransaction has been released and the listener 655 // can now take action on the changes it calculated. 656 TRANSACTION_COMPLETE, 657 // Channel is closing. 658 SHUTDOWN 659 } todo; 660 // These members are only valid for CALCULATE_CHANGES. 661 const OriginalEntries* originals; 662 BaseTransaction* trans; // This is valid also for TRANSACTION_ENDING 663 WriterTag writer; 664 typedef DirectoryChangeEvent EventType; 665 static inline bool IsChannelShutdownEvent(const EventType& e) { 666 return SHUTDOWN == e.todo; 667 } 668}; 669 670// The name Directory in this case means the entire directory 671// structure within a single user account. 672// 673// Sqlite is a little goofy, in that each thread must access a database 674// via its own handle. So, a Directory object should only be accessed 675// from a single thread. Use DirectoryManager's Open() method to 676// always get a directory that has been properly initialized on the 677// current thread. 678// 679// The db is protected against concurrent modification by a reader/ 680// writer lock, negotiated by the ReadTransaction and WriteTransaction 681// friend classes. The in-memory indices are protected against 682// concurrent modification by the kernel lock. 683// 684// All methods which require the reader/writer lock to be held either 685// are protected and only called from friends in a transaction 686// or are public and take a Transaction* argument. 687// 688// All methods which require the kernel lock to be already held take a 689// ScopeKernelLock* argument. 690// 691// To prevent deadlock, the reader writer transaction lock must always 692// be held before acquiring the kernel lock. 693class ScopedKernelLock; 694class IdFilter; 695class DirectoryManager; 696 697class Directory { 698 friend class BaseTransaction; 699 friend class Entry; 700 friend class MutableEntry; 701 friend class ReadTransaction; 702 friend class ReadTransactionWithoutDB; 703 friend class ScopedKernelLock; 704 friend class ScopedKernelUnlock; 705 friend class WriteTransaction; 706 friend class SyncableDirectoryTest; 707 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 708 TakeSnapshotGetsAllDirtyHandlesTest); 709 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 710 TakeSnapshotGetsOnlyDirtyHandlesTest); 711 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, TestPurgeEntriesWithTypeIn); 712 FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, 713 TakeSnapshotGetsMetahandlesToPurge); 714 715 public: 716 class EventListenerHookup; 717 718 // Various data that the Directory::Kernel we are backing (persisting data 719 // for) needs saved across runs of the application. 720 struct PersistedKernelInfo { 721 AutofillMigrationDebugInfo autofill_migration_debug_info; 722 723 PersistedKernelInfo(); 724 ~PersistedKernelInfo(); 725 726 // Set the |download_progress| entry for the given model to a 727 // "first sync" start point. When such a value is sent to the server, 728 // a full download of all objects of the model will be initiated. 729 void reset_download_progress(ModelType model_type); 730 731 // Last sync timestamp fetched from the server. 732 sync_pb::DataTypeProgressMarker download_progress[MODEL_TYPE_COUNT]; 733 // true iff we ever reached the end of the changelog. 734 ModelTypeBitSet initial_sync_ended; 735 // The store birthday we were given by the server. Contents are opaque to 736 // the client. 737 std::string store_birthday; 738 // The next local ID that has not been used with this cache-GUID. 739 int64 next_id; 740 // The persisted notification state. 741 std::string notification_state; 742 743 AutofillMigrationState autofill_migration_state; 744 }; 745 746 // What the Directory needs on initialization to create itself and its Kernel. 747 // Filled by DirectoryBackingStore::Load. 748 struct KernelLoadInfo { 749 PersistedKernelInfo kernel_info; 750 std::string cache_guid; // Created on first initialization, never changes. 751 int64 max_metahandle; // Computed (using sql MAX aggregate) on init. 752 KernelLoadInfo() : max_metahandle(0) { 753 } 754 }; 755 756 // The dirty/clean state of kernel fields backed by the share_info table. 757 // This is public so it can be used in SaveChangesSnapshot for persistence. 758 enum KernelShareInfoStatus { 759 KERNEL_SHARE_INFO_INVALID, 760 KERNEL_SHARE_INFO_VALID, 761 KERNEL_SHARE_INFO_DIRTY 762 }; 763 764 // When the Directory is told to SaveChanges, a SaveChangesSnapshot is 765 // constructed and forms a consistent snapshot of what needs to be sent to 766 // the backing store. 767 struct SaveChangesSnapshot { 768 SaveChangesSnapshot(); 769 ~SaveChangesSnapshot(); 770 771 KernelShareInfoStatus kernel_info_status; 772 PersistedKernelInfo kernel_info; 773 OriginalEntries dirty_metas; 774 MetahandleSet metahandles_to_purge; 775 }; 776 777 Directory(); 778 virtual ~Directory(); 779 780 DirOpenResult Open(const FilePath& file_path, const std::string& name); 781 782 void Close(); 783 784 int64 NextMetahandle(); 785 // Always returns a negative id. Positive client ids are generated 786 // by the server only. 787 Id NextId(); 788 789 const FilePath& file_path() const { return kernel_->db_path; } 790 bool good() const { return NULL != store_; } 791 792 // The download progress is an opaque token provided by the sync server 793 // to indicate the continuation state of the next GetUpdates operation. 794 void GetDownloadProgress( 795 ModelType type, 796 sync_pb::DataTypeProgressMarker* value_out) const; 797 void GetDownloadProgressAsString( 798 ModelType type, 799 std::string* value_out) const; 800 void SetDownloadProgress( 801 ModelType type, 802 const sync_pb::DataTypeProgressMarker& value); 803 804 bool initial_sync_ended_for_type(ModelType type) const; 805 void set_initial_sync_ended_for_type(ModelType type, bool value); 806 AutofillMigrationState get_autofill_migration_state() const; 807 808 AutofillMigrationDebugInfo get_autofill_migration_debug_info() const; 809 810 void set_autofill_migration_state(AutofillMigrationState state); 811 812 void set_autofill_migration_state_debug_info( 813 syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, 814 const syncable::AutofillMigrationDebugInfo& info); 815 816 const std::string& name() const { return kernel_->name; } 817 818 // (Account) Store birthday is opaque to the client, 819 // so we keep it in the format it is in the proto buffer 820 // in case we switch to a binary birthday later. 821 std::string store_birthday() const; 822 void set_store_birthday(std::string store_birthday); 823 824 std::string GetAndClearNotificationState(); 825 void SetNotificationState(const std::string& notification_state); 826 827 // Unique to each account / client pair. 828 std::string cache_guid() const; 829 830 browser_sync::ChannelHookup<DirectoryChangeEvent>* AddChangeObserver( 831 browser_sync::ChannelEventHandler<DirectoryChangeEvent>* observer); 832 833 protected: // for friends, mainly used by Entry constructors 834 virtual EntryKernel* GetEntryByHandle(int64 handle); 835 virtual EntryKernel* GetEntryByHandle(int64 metahandle, 836 ScopedKernelLock* lock); 837 virtual EntryKernel* GetEntryById(const Id& id); 838 EntryKernel* GetEntryByServerTag(const std::string& tag); 839 virtual EntryKernel* GetEntryByClientTag(const std::string& tag); 840 EntryKernel* GetRootEntry(); 841 bool ReindexId(EntryKernel* const entry, const Id& new_id); 842 void ReindexParentId(EntryKernel* const entry, const Id& new_parent_id); 843 void ClearDirtyMetahandles(); 844 845 // These don't do semantic checking. 846 // The semantic checking is implemented higher up. 847 void UnlinkEntryFromOrder(EntryKernel* entry, 848 WriteTransaction* trans, 849 ScopedKernelLock* lock); 850 851 // Overridden by tests. 852 virtual DirectoryBackingStore* CreateBackingStore( 853 const std::string& dir_name, 854 const FilePath& backing_filepath); 855 856 private: 857 // These private versions expect the kernel lock to already be held 858 // before calling. 859 EntryKernel* GetEntryById(const Id& id, ScopedKernelLock* const lock); 860 861 DirOpenResult OpenImpl(const FilePath& file_path, const std::string& name); 862 863 template <class T> void TestAndSet(T* kernel_data, const T* data_to_set); 864 865 struct DirectoryEventTraits { 866 typedef DirectoryEvent EventType; 867 static inline bool IsChannelShutdownEvent(const DirectoryEvent& event) { 868 return DIRECTORY_DESTROYED == event; 869 } 870 }; 871 public: 872 typedef EventChannel<DirectoryEventTraits, base::Lock> Channel; 873 typedef std::vector<int64> ChildHandles; 874 875 // Returns the child meta handles for given parent id. 876 void GetChildHandles(BaseTransaction*, const Id& parent_id, 877 ChildHandles* result); 878 879 // Find the first or last child in the positional ordering under a parent, 880 // and return its id. Returns a root Id if parent has no children. 881 virtual Id GetFirstChildId(BaseTransaction* trans, const Id& parent_id); 882 Id GetLastChildId(BaseTransaction* trans, const Id& parent_id); 883 884 // Compute a local predecessor position for |update_item|. The position 885 // is determined by the SERVER_POSITION_IN_PARENT value of |update_item|, 886 // as well as the SERVER_POSITION_IN_PARENT values of any up-to-date 887 // children of |parent_id|. 888 Id ComputePrevIdFromServerPosition( 889 const EntryKernel* update_item, 890 const syncable::Id& parent_id); 891 892 // SaveChanges works by taking a consistent snapshot of the current Directory 893 // state and indices (by deep copy) under a ReadTransaction, passing this 894 // snapshot to the backing store under no transaction, and finally cleaning 895 // up by either purging entries no longer needed (this part done under a 896 // WriteTransaction) or rolling back the dirty bits. It also uses 897 // internal locking to enforce SaveChanges operations are mutually exclusive. 898 // 899 // WARNING: THIS METHOD PERFORMS SYNCHRONOUS I/O VIA SQLITE. 900 bool SaveChanges(); 901 902 // Returns the number of entities with the unsynced bit set. 903 int64 unsynced_entity_count() const; 904 905 // Get GetUnsyncedMetaHandles should only be called after SaveChanges and 906 // before any new entries have been created. The intention is that the 907 // syncer should call it from its PerformSyncQueries member. 908 typedef std::vector<int64> UnsyncedMetaHandles; 909 void GetUnsyncedMetaHandles(BaseTransaction* trans, 910 UnsyncedMetaHandles* result); 911 912 // Get all the metahandles for unapplied updates 913 typedef std::vector<int64> UnappliedUpdateMetaHandles; 914 void GetUnappliedUpdateMetaHandles(BaseTransaction* trans, 915 UnappliedUpdateMetaHandles* result); 916 917 // Get the channel for post save notification, used by the syncer. 918 inline Channel* channel() const { 919 return kernel_->channel; 920 } 921 922 // Checks tree metadata consistency. 923 // If full_scan is false, the function will avoid pulling any entries from the 924 // db and scan entries currently in ram. 925 // If full_scan is true, all entries will be pulled from the database. 926 // No return value, CHECKs will be triggered if we're given bad 927 // information. 928 void CheckTreeInvariants(syncable::BaseTransaction* trans, 929 bool full_scan); 930 931 void CheckTreeInvariants(syncable::BaseTransaction* trans, 932 const OriginalEntries* originals); 933 934 void CheckTreeInvariants(syncable::BaseTransaction* trans, 935 const MetahandleSet& handles, 936 const IdFilter& idfilter); 937 938 // Purges all data associated with any entries whose ModelType or 939 // ServerModelType is found in |types|, from _both_ memory and disk. 940 // Only valid, "real" model types are allowed in |types| (see model_type.h 941 // for definitions). "Purge" is just meant to distinguish from "deleting" 942 // entries, which means something different in the syncable namespace. 943 // WARNING! This can be real slow, as it iterates over all entries. 944 // WARNING! Performs synchronous I/O. 945 virtual void PurgeEntriesWithTypeIn(const std::set<ModelType>& types); 946 947 private: 948 // Helper to prime ids_index, parent_id_and_names_index, unsynced_metahandles 949 // and unapplied_metahandles from metahandles_index. 950 void InitializeIndices(); 951 952 // Constructs a consistent snapshot of the current Directory state and 953 // indices (by deep copy) under a ReadTransaction for use in |snapshot|. 954 // See SaveChanges() for more information. 955 void TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot); 956 957 // Purges from memory any unused, safe to remove entries that were 958 // successfully deleted on disk as a result of the SaveChanges that processed 959 // |snapshot|. See SaveChanges() for more information. 960 void VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot); 961 962 // Rolls back dirty bits in the event that the SaveChanges that 963 // processed |snapshot| failed, for example, due to no disk space. 964 void HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot); 965 966 // For new entry creation only 967 void InsertEntry(EntryKernel* entry, ScopedKernelLock* lock); 968 void InsertEntry(EntryKernel* entry); 969 970 // Used by CheckTreeInvariants 971 void GetAllMetaHandles(BaseTransaction* trans, MetahandleSet* result); 972 bool SafeToPurgeFromMemory(const EntryKernel* const entry) const; 973 974 // Internal setters that do not acquire a lock internally. These are unsafe 975 // on their own; caller must guarantee exclusive access manually by holding 976 // a ScopedKernelLock. 977 void set_initial_sync_ended_for_type_unsafe(ModelType type, bool x); 978 void SetNotificationStateUnsafe(const std::string& notification_state); 979 980 Directory& operator = (const Directory&); 981 982 public: 983 typedef Index<MetahandleIndexer>::Set MetahandlesIndex; 984 typedef Index<IdIndexer>::Set IdsIndex; 985 // All entries in memory must be in both the MetahandlesIndex and 986 // the IdsIndex, but only non-deleted entries will be the 987 // ParentIdChildIndex. 988 typedef Index<ParentIdAndHandleIndexer>::Set ParentIdChildIndex; 989 990 // Contains both deleted and existing entries with tags. 991 // We can't store only existing tags because the client would create 992 // items that had a duplicated ID in the end, resulting in a DB key 993 // violation. ID reassociation would fail after an attempted commit. 994 typedef Index<ClientTagIndexer>::Set ClientTagIndex; 995 996 protected: 997 // Used by tests. 998 void init_kernel(const std::string& name); 999 1000 private: 1001 1002 struct Kernel { 1003 Kernel(const FilePath& db_path, const std::string& name, 1004 const KernelLoadInfo& info); 1005 1006 ~Kernel(); 1007 1008 void AddRef(); // For convenience. 1009 void Release(); 1010 1011 FilePath const db_path; 1012 // TODO(timsteele): audit use of the member and remove if possible 1013 volatile base::subtle::AtomicWord refcount; 1014 1015 // Implements ReadTransaction / WriteTransaction using a simple lock. 1016 base::Lock transaction_mutex; 1017 1018 // The name of this directory. 1019 std::string const name; 1020 1021 // Protects all members below. 1022 // The mutex effectively protects all the indices, but not the 1023 // entries themselves. So once a pointer to an entry is pulled 1024 // from the index, the mutex can be unlocked and entry read or written. 1025 // 1026 // Never hold the mutex and do anything with the database or any 1027 // other buffered IO. Violating this rule will result in deadlock. 1028 base::Lock mutex; 1029 // Entries indexed by metahandle 1030 MetahandlesIndex* metahandles_index; 1031 // Entries indexed by id 1032 IdsIndex* ids_index; 1033 ParentIdChildIndex* parent_id_child_index; 1034 ClientTagIndex* client_tag_index; 1035 // So we don't have to create an EntryKernel every time we want to 1036 // look something up in an index. Needle in haystack metaphor. 1037 EntryKernel needle; 1038 1039 // 3 in-memory indices on bits used extremely frequently by the syncer. 1040 MetahandleSet* const unapplied_update_metahandles; 1041 MetahandleSet* const unsynced_metahandles; 1042 // Contains metahandles that are most likely dirty (though not 1043 // necessarily). Dirtyness is confirmed in TakeSnapshotForSaveChanges(). 1044 MetahandleSet* const dirty_metahandles; 1045 1046 // When a purge takes place, we remove items from all our indices and stash 1047 // them in here so that SaveChanges can persist their permanent deletion. 1048 MetahandleSet* const metahandles_to_purge; 1049 1050 // TODO(ncarter): Figure out what the hell this is, and comment it. 1051 Channel* const channel; 1052 1053 // The changes channel mutex is explicit because it must be locked 1054 // while holding the transaction mutex and released after 1055 // releasing the transaction mutex. 1056 browser_sync::Channel<DirectoryChangeEvent> changes_channel; 1057 1058 base::Lock changes_channel_mutex; 1059 KernelShareInfoStatus info_status; 1060 1061 // These 3 members are backed in the share_info table, and 1062 // their state is marked by the flag above. 1063 1064 // A structure containing the Directory state that is written back into the 1065 // database on SaveChanges. 1066 PersistedKernelInfo persisted_info; 1067 1068 // A unique identifier for this account's cache db, used to generate 1069 // unique server IDs. No need to lock, only written at init time. 1070 std::string cache_guid; 1071 1072 // It doesn't make sense for two threads to run SaveChanges at the same 1073 // time; this mutex protects that activity. 1074 base::Lock save_changes_mutex; 1075 1076 // The next metahandle is protected by kernel mutex. 1077 int64 next_metahandle; 1078 1079 // Keep a history of recently flushed metahandles for debugging 1080 // purposes. Protected by the save_changes_mutex. 1081 DebugQueue<int64, 1000> flushed_metahandles; 1082 }; 1083 1084 // Helper method used to do searches on |parent_id_child_index|. 1085 ParentIdChildIndex::iterator LocateInParentChildIndex( 1086 const ScopedKernelLock& lock, 1087 const Id& parent_id, 1088 int64 position_in_parent, 1089 const Id& item_id_for_tiebreaking); 1090 1091 // Return an iterator to the beginning of the range of the children of 1092 // |parent_id| in the kernel's parent_id_child_index. 1093 ParentIdChildIndex::iterator GetParentChildIndexLowerBound( 1094 const ScopedKernelLock& lock, 1095 const Id& parent_id); 1096 1097 // Return an iterator to just past the end of the range of the 1098 // children of |parent_id| in the kernel's parent_id_child_index. 1099 ParentIdChildIndex::iterator GetParentChildIndexUpperBound( 1100 const ScopedKernelLock& lock, 1101 const Id& parent_id); 1102 1103 Kernel* kernel_; 1104 1105 DirectoryBackingStore* store_; 1106}; 1107 1108class ScopedKernelLock { 1109 public: 1110 explicit ScopedKernelLock(const Directory*); 1111 ~ScopedKernelLock() {} 1112 1113 base::AutoLock scoped_lock_; 1114 Directory* const dir_; 1115 DISALLOW_COPY_AND_ASSIGN(ScopedKernelLock); 1116}; 1117 1118// Transactions are now processed FIFO with a straight lock 1119class BaseTransaction { 1120 friend class Entry; 1121 public: 1122 inline Directory* directory() const { return directory_; } 1123 inline Id root_id() const { return Id(); } 1124 1125 virtual ~BaseTransaction(); 1126 1127 protected: 1128 BaseTransaction(Directory* directory, const char* name, 1129 const char* source_file, int line, WriterTag writer); 1130 1131 // For unit testing. Everything will be mocked out no point initializing. 1132 explicit BaseTransaction(Directory* directory); 1133 1134 void UnlockAndLog(OriginalEntries* entries); 1135 bool NotifyTransactionChangingAndEnding(OriginalEntries* entries); 1136 virtual void NotifyTransactionComplete(); 1137 1138 Directory* const directory_; 1139 Directory::Kernel* const dirkernel_; // for brevity 1140 const char* const name_; 1141 base::TimeTicks time_acquired_; 1142 const char* const source_file_; 1143 const int line_; 1144 WriterTag writer_; 1145 1146 private: 1147 void Lock(); 1148 1149 DISALLOW_COPY_AND_ASSIGN(BaseTransaction); 1150}; 1151 1152// Locks db in constructor, unlocks in destructor. 1153class ReadTransaction : public BaseTransaction { 1154 public: 1155 ReadTransaction(Directory* directory, const char* source_file, 1156 int line); 1157 ReadTransaction(const ScopedDirLookup& scoped_dir, 1158 const char* source_file, int line); 1159 1160 virtual ~ReadTransaction(); 1161 1162 protected: // Don't allow creation on heap, except by sync API wrapper. 1163 friend class sync_api::ReadTransaction; 1164 void* operator new(size_t size) { return (::operator new)(size); } 1165 1166 DISALLOW_COPY_AND_ASSIGN(ReadTransaction); 1167}; 1168 1169// Locks db in constructor, unlocks in destructor. 1170class WriteTransaction : public BaseTransaction { 1171 friend class MutableEntry; 1172 public: 1173 explicit WriteTransaction(Directory* directory, WriterTag writer, 1174 const char* source_file, int line); 1175 explicit WriteTransaction(const ScopedDirLookup& directory, 1176 WriterTag writer, const char* source_file, 1177 int line); 1178 virtual ~WriteTransaction(); 1179 1180 void SaveOriginal(EntryKernel* entry); 1181 1182 protected: 1183 // Before an entry gets modified, we copy the original into a list 1184 // so that we can issue change notifications when the transaction 1185 // is done. 1186 OriginalEntries* const originals_; 1187 1188 explicit WriteTransaction(Directory *directory); 1189 1190 DISALLOW_COPY_AND_ASSIGN(WriteTransaction); 1191}; 1192 1193bool IsLegalNewParent(BaseTransaction* trans, const Id& id, const Id& parentid); 1194 1195int64 Now(); 1196 1197// This function sets only the flags needed to get this entry to sync. 1198void MarkForSyncing(syncable::MutableEntry* e); 1199 1200// This is not a reset. It just sets the numeric fields which are not 1201// initialized by the constructor to zero. 1202void ZeroFields(EntryKernel* entry, int first_field); 1203 1204} // namespace syncable 1205 1206std::ostream& operator <<(std::ostream&, const syncable::Blob&); 1207 1208#endif // CHROME_BROWSER_SYNC_SYNCABLE_SYNCABLE_H_ 1209