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_DIRECTORY_BACKING_STORE_H_ 6 #define CHROME_BROWSER_SYNC_SYNCABLE_DIRECTORY_BACKING_STORE_H_ 7 #pragma once 8 9 #include <string> 10 11 #include "base/file_path.h" 12 #include "base/gtest_prod_util.h" 13 #include "chrome/browser/sync/syncable/dir_open_result.h" 14 #include "chrome/browser/sync/syncable/model_type.h" 15 #include "chrome/browser/sync/syncable/syncable.h" 16 17 extern "C" { 18 struct sqlite3; 19 struct sqlite3_stmt; 20 } 21 22 class SQLStatement; 23 24 namespace sync_pb { 25 class EntitySpecifics; 26 } 27 28 namespace syncable { 29 30 struct ColumnSpec; 31 typedef Directory::MetahandlesIndex MetahandlesIndex; 32 33 // Provides sqlite3-based persistence for a syncable::Directory object. You can 34 // load all the persisted data to prime a syncable::Directory on startup by 35 // invoking Load. The only other thing you (or more correctly, a Directory) 36 // can do here is save any changes that have occurred since calling Load, which 37 // can be done periodically as often as desired* 38 // 39 // * If you only ever use a DirectoryBackingStore (DBS) from a single thread 40 // then you can stop reading now. This is implemented using sqlite3, which 41 // requires that each thread accesses a DB via a handle (sqlite3*) opened by 42 // sqlite_open for that thread and only that thread. To avoid complicated TLS 43 // logic to swap handles in-and-out as different threads try to get a hold of a 44 // DBS, the DBS does two things: 45 // 1. Uses a separate handle for Load()ing which is closed as soon as loading 46 // finishes, and 47 // 2. Requires that SaveChanges *only* be called from a single thread, and that 48 // thread *must* be the thread that owns / is responsible for destroying 49 // the DBS. 50 // This way, any thread may open a Directory (which today can be either the 51 // AuthWatcherThread or SyncCoreThread) and Load its DBS. The first time 52 // SaveChanges is called a new sqlite3 handle is created, and it will get closed 53 // when the DBS is destroyed, which is the reason for the requirement that the 54 // thread that "uses" the DBS is the thread that destroys it. 55 class DirectoryBackingStore { 56 public: 57 DirectoryBackingStore(const std::string& dir_name, 58 const FilePath& backing_filepath); 59 60 virtual ~DirectoryBackingStore(); 61 62 // Loads and drops all currently persisted meta entries into |entry_bucket| 63 // and loads appropriate persisted kernel info into |info_bucket|. 64 // NOTE: On success (return value of OPENED), the buckets are populated with 65 // newly allocated items, meaning ownership is bestowed upon the caller. 66 DirOpenResult Load(MetahandlesIndex* entry_bucket, 67 Directory::KernelLoadInfo* kernel_load_info); 68 69 // Updates the on-disk store with the input |snapshot| as a database 70 // transaction. Does NOT open any syncable transactions as this would cause 71 // opening transactions elsewhere to block on synchronous I/O. 72 // DO NOT CALL THIS FROM MORE THAN ONE THREAD EVER. Also, whichever thread 73 // calls SaveChanges *must* be the thread that owns/destroys |this|. 74 virtual bool SaveChanges(const Directory::SaveChangesSnapshot& snapshot); 75 76 private: 77 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion67To68); 78 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion68To69); 79 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion69To70); 80 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion70To71); 81 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion71To72); 82 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion72To73); 83 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion73To74); 84 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion74To75); 85 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, ModelTypeIds); 86 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, Corruption); 87 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, DeleteEntries); 88 FRIEND_TEST_ALL_PREFIXES(MigrationTest, ToCurrentVersion); 89 friend class MigrationTest; 90 91 // General Directory initialization and load helpers. 92 DirOpenResult InitializeTables(); 93 // Returns an sqlite return code, usually SQLITE_DONE. 94 int CreateTables(); 95 96 // Create 'share_info' or 'temp_share_info' depending on value of 97 // is_temporary. Returns an sqlite 98 // return code, SQLITE_DONE on success. 99 int CreateShareInfoTable(bool is_temporary); 100 101 int CreateShareInfoTableVersion71(bool is_temporary); 102 // Create 'metas' or 'temp_metas' depending on value of is_temporary. 103 // Returns an sqlite return code, SQLITE_DONE on success. 104 int CreateMetasTable(bool is_temporary); 105 // Returns an sqlite return code, SQLITE_DONE on success. 106 int CreateModelsTable(); 107 int CreateV71ModelsTable(); 108 109 // We don't need to load any synced and applied deleted entries, we can 110 // in fact just purge them forever on startup. 111 bool DropDeletedEntries(); 112 // Drops a table if it exists, harmless if the table did not already exist. 113 int SafeDropTable(const char* table_name); 114 115 // Load helpers for entries and attributes. 116 bool LoadEntries(MetahandlesIndex* entry_bucket); 117 bool LoadInfo(Directory::KernelLoadInfo* info); 118 119 // Save/update helpers for entries. Return false if sqlite commit fails. 120 bool SaveEntryToDB(const EntryKernel& entry); 121 bool SaveNewEntryToDB(const EntryKernel& entry); 122 bool UpdateEntryToDB(const EntryKernel& entry); 123 124 // Creates a new sqlite3 handle to the backing database. Sets sqlite operation 125 // timeout preferences and registers our overridden sqlite3 operators for 126 // said handle. Returns true on success, false if the sqlite open operation 127 // did not succeed. 128 bool OpenAndConfigureHandleHelper(sqlite3** handle) const; 129 // Initialize and destroy load_dbhandle_. Broken out for testing. 130 bool BeginLoad(); 131 void EndLoad(); 132 DirOpenResult DoLoad(MetahandlesIndex* entry_bucket, 133 Directory::KernelLoadInfo* kernel_load_info); 134 135 // Close save_dbhandle_. Broken out for testing. 136 void EndSave(); 137 138 // Removes each entry whose metahandle is in |handles| from the database. 139 // Does synchronous I/O. Returns false on error. 140 bool DeleteEntries(const MetahandleSet& handles); 141 142 // Lazy creation of save_dbhandle_ for use by SaveChanges code path. 143 sqlite3* LazyGetSaveHandle(); 144 145 // Drop all tables in preparation for reinitialization. 146 void DropAllTables(); 147 148 // Serialization helpers for syncable::ModelType. These convert between 149 // the ModelType enum and the values we persist in the database to identify 150 // a model. We persist a default instance of the specifics protobuf as the 151 // ID, rather than the enum value. 152 static ModelType ModelIdToModelTypeEnum(const void* data, int length); 153 static std::string ModelTypeEnumToModelId(ModelType model_type); 154 155 // Runs an integrity check on the current database. If the 156 // integrity check fails, false is returned and error is populated 157 // with an error message. 158 bool CheckIntegrity(sqlite3* handle, std::string* error) const; 159 160 // Migration utilities. 161 bool AddColumn(const ColumnSpec* column); 162 bool RefreshColumns(); 163 bool SetVersion(int version); 164 int GetVersion(); 165 bool MigrateToSpecifics(const char* old_columns, 166 const char* specifics_column, 167 void(*handler_function) ( 168 SQLStatement* old_value_query, 169 int old_value_column, 170 sync_pb::EntitySpecifics* mutable_new_value)); 171 172 // Individual version migrations. 173 bool MigrateVersion67To68(); 174 bool MigrateVersion68To69(); 175 bool MigrateVersion69To70(); 176 bool MigrateVersion70To71(); 177 bool MigrateVersion71To72(); 178 bool MigrateVersion72To73(); 179 bool MigrateVersion73To74(); 180 bool MigrateVersion74To75(); 181 182 // The handle to our sqlite on-disk store for initialization and loading, and 183 // for saving changes periodically via SaveChanges, respectively. 184 // TODO(timsteele): We should only have one handle here. The reason we need 185 // two at the moment is because the DB can be opened by either the AuthWatcher 186 // or SyncCore threads, but SaveChanges is always called by the latter. We 187 // need to change initialization so the DB is only accessed from one thread. 188 sqlite3* load_dbhandle_; 189 sqlite3* save_dbhandle_; 190 191 std::string dir_name_; 192 FilePath backing_filepath_; 193 194 // Set to true if migration left some old columns around that need to be 195 // discarded. 196 bool needs_column_refresh_; 197 198 DISALLOW_COPY_AND_ASSIGN(DirectoryBackingStore); 199 }; 200 201 } // namespace syncable 202 203 #endif // CHROME_BROWSER_SYNC_SYNCABLE_DIRECTORY_BACKING_STORE_H_ 204