OLD | NEW |
| (Empty) |
1 // Copyright 2012 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_BACKING_STORE_H_ | |
6 #define SYNC_SYNCABLE_DIRECTORY_BACKING_STORE_H_ | |
7 | |
8 #include <stdint.h> | |
9 | |
10 #include <memory> | |
11 #include <string> | |
12 | |
13 #include "base/gtest_prod_util.h" | |
14 #include "base/macros.h" | |
15 #include "base/threading/non_thread_safe.h" | |
16 #include "sql/connection.h" | |
17 #include "sql/statement.h" | |
18 #include "sync/base/sync_export.h" | |
19 #include "sync/internal_api/public/base/model_type.h" | |
20 #include "sync/syncable/dir_open_result.h" | |
21 #include "sync/syncable/directory.h" | |
22 #include "sync/syncable/metahandle_set.h" | |
23 | |
24 namespace sync_pb { | |
25 class EntitySpecifics; | |
26 } | |
27 | |
28 namespace syncer { | |
29 namespace syncable { | |
30 | |
31 SYNC_EXPORT extern const int32_t kCurrentDBVersion; | |
32 SYNC_EXPORT extern const int32_t kCurrentPageSizeKB; | |
33 | |
34 struct ColumnSpec; | |
35 | |
36 // Interface that provides persistence for a syncable::Directory object. You can | |
37 // load all the persisted data to prime a syncable::Directory on startup by | |
38 // invoking Load. The only other thing you (or more correctly, a Directory) can | |
39 // do here is save any changes that have occurred since calling Load, which can | |
40 // be done periodically as often as desired. | |
41 // | |
42 // The DirectoryBackingStore will own an sqlite lock on its database for most of | |
43 // its lifetime. You must not have two DirectoryBackingStore objects accessing | |
44 // the database simultaneously. Because the lock exists at the database level, | |
45 // not even two separate browser instances would be able to acquire it | |
46 // simultaneously. | |
47 // | |
48 // This class is abstract so that we can extend it in interesting ways for use | |
49 // in tests. The concrete class used in non-test scenarios is | |
50 // OnDiskDirectoryBackingStore. | |
51 class SYNC_EXPORT DirectoryBackingStore : public base::NonThreadSafe { | |
52 public: | |
53 explicit DirectoryBackingStore(const std::string& dir_name); | |
54 virtual ~DirectoryBackingStore(); | |
55 | |
56 // Loads and drops all currently persisted meta entries into |handles_map| | |
57 // and loads appropriate persisted kernel info into |kernel_load_info|. | |
58 // The function determines which entries can be safely dropped and inserts | |
59 // their keys into |metahandles_to_purge|. It is up to the caller to | |
60 // perform the actual cleanup. | |
61 // | |
62 // This function will migrate to the latest database version. | |
63 // | |
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 virtual DirOpenResult Load(Directory::MetahandlesMap* handles_map, | |
67 JournalIndex* delete_journals, | |
68 MetahandleSet* metahandles_to_purge, | |
69 Directory::KernelLoadInfo* kernel_load_info) = 0; | |
70 | |
71 // Updates the on-disk store with the input |snapshot| as a database | |
72 // transaction. Does NOT open any syncable transactions as this would cause | |
73 // opening transactions elsewhere to block on synchronous I/O. | |
74 // DO NOT CALL THIS FROM MORE THAN ONE THREAD EVER. Also, whichever thread | |
75 // calls SaveChanges *must* be the thread that owns/destroys |this|. | |
76 // | |
77 // Returns true if the changes were saved successfully. Returns false if an | |
78 // error (of any kind) occurred. See also |SetCatastrophicErrorHandler| for a | |
79 // systematic way of handling underlying DB errors. | |
80 virtual bool SaveChanges(const Directory::SaveChangesSnapshot& snapshot); | |
81 | |
82 // Set the catastrophic error handler. | |
83 // | |
84 // When a catastrophic error is encountered while accessing the underlying DB, | |
85 // |catastrophic_error_handler| will be invoked (via PostTask) on the thread | |
86 // on which this DirectoryBackingStore object lives. | |
87 // | |
88 // For a definition of what's catastrophic, see sql::IsErrorCatastrophic. | |
89 // | |
90 // |catastrophic_error_handler| must be initialized (i.e. !is_null()). | |
91 // | |
92 // A single operation (like Load or SaveChanges) may result in the | |
93 // |catastrophic_error_handler| being invoked several times. | |
94 // | |
95 // There can be at most one handler. If this method is invoked when there is | |
96 // already a handler, the existing handler is overwritten with | |
97 // |catastrophic_error_handler|. | |
98 virtual void SetCatastrophicErrorHandler( | |
99 const base::Closure& catastrophic_error_handler); | |
100 | |
101 // Returns true on success, false on error. | |
102 bool GetDatabasePageSize(int* page_size); | |
103 | |
104 protected: | |
105 // For test classes. | |
106 DirectoryBackingStore(const std::string& dir_name, | |
107 sql::Connection* connection); | |
108 | |
109 // An accessor for the underlying sql::Connection. Avoid using outside of | |
110 // tests. | |
111 sql::Connection* db(); | |
112 | |
113 // Return true if the DB is open. | |
114 bool IsOpen() const; | |
115 | |
116 // Open the DB at |path|. | |
117 // Return true on success, false on failure. | |
118 bool Open(const base::FilePath& path); | |
119 | |
120 // Open an in memory DB. | |
121 // Return true on success, false on failure. | |
122 bool OpenInMemory(); | |
123 | |
124 // Initialize database tables. Return true on success, false on error. | |
125 bool InitializeTables(); | |
126 | |
127 // Load helpers for entries and attributes. Return true on success, false on | |
128 // error. | |
129 bool LoadEntries(Directory::MetahandlesMap* handles_map, | |
130 MetahandleSet* metahandles_to_purge); | |
131 bool LoadDeleteJournals(JournalIndex* delete_journals); | |
132 bool LoadInfo(Directory::KernelLoadInfo* info); | |
133 | |
134 enum EntryTable { | |
135 METAS_TABLE, | |
136 DELETE_JOURNAL_TABLE, | |
137 }; | |
138 // Removes each entry whose metahandle is in |handles| from the table | |
139 // specified by |from| table. Does synchronous I/O. Returns false on error. | |
140 bool DeleteEntries(EntryTable from, const MetahandleSet& handles); | |
141 | |
142 // Serialization helpers for ModelType. These convert between | |
143 // the ModelType enum and the values we persist in the database to identify | |
144 // a model. We persist a default instance of the specifics protobuf as the | |
145 // ID, rather than the enum value. | |
146 static ModelType ModelIdToModelTypeEnum(const void* data, int length); | |
147 static std::string ModelTypeEnumToModelId(ModelType model_type); | |
148 | |
149 static std::string GenerateCacheGUID(); | |
150 | |
151 // Checks that the references between sync nodes is consistent. | |
152 static bool VerifyReferenceIntegrity( | |
153 const Directory::MetahandlesMap* handles_map); | |
154 | |
155 // Migration utilities. | |
156 bool RefreshColumns(); | |
157 bool SetVersion(int version); | |
158 int GetVersion(); | |
159 | |
160 // Individual version migrations. | |
161 bool MigrateVersion67To68(); | |
162 bool MigrateVersion68To69(); | |
163 bool MigrateVersion69To70(); | |
164 bool MigrateVersion70To71(); | |
165 bool MigrateVersion71To72(); | |
166 bool MigrateVersion72To73(); | |
167 bool MigrateVersion73To74(); | |
168 bool MigrateVersion74To75(); | |
169 bool MigrateVersion75To76(); | |
170 bool MigrateVersion76To77(); | |
171 bool MigrateVersion77To78(); | |
172 bool MigrateVersion78To79(); | |
173 bool MigrateVersion79To80(); | |
174 bool MigrateVersion80To81(); | |
175 bool MigrateVersion81To82(); | |
176 bool MigrateVersion82To83(); | |
177 bool MigrateVersion83To84(); | |
178 bool MigrateVersion84To85(); | |
179 bool MigrateVersion85To86(); | |
180 bool MigrateVersion86To87(); | |
181 bool MigrateVersion87To88(); | |
182 bool MigrateVersion88To89(); | |
183 bool MigrateVersion89To90(); | |
184 | |
185 // Accessor for needs_column_refresh_. Used in tests. | |
186 bool needs_column_refresh() const; | |
187 | |
188 // Destroys the existing Connection and creates a new one. | |
189 void ResetAndCreateConnection(); | |
190 | |
191 private: | |
192 friend class DirectoryBackingStoreTest; | |
193 friend class TestDirectoryBackingStore; | |
194 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, | |
195 IncreaseDatabasePageSizeFrom4KTo32K); | |
196 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, | |
197 CatastrophicErrorHandler_KeptAcrossReset); | |
198 FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, | |
199 CatastrophicErrorHandler_InvocationDuringLoad); | |
200 FRIEND_TEST_ALL_PREFIXES( | |
201 DirectoryBackingStoreTest, | |
202 CatastrophicErrorHandler_InvocationDuringSaveChanges); | |
203 FRIEND_TEST_ALL_PREFIXES(MigrationTest, ToCurrentVersion); | |
204 | |
205 // Drop all tables in preparation for reinitialization. | |
206 void DropAllTables(); | |
207 | |
208 bool SafeToPurgeOnLoading(const EntryKernel& entry) const; | |
209 | |
210 // Drops a table if it exists, harmless if the table did not already exist. | |
211 bool SafeDropTable(const char* table_name); | |
212 | |
213 bool CreateTables(); | |
214 | |
215 // Create 'share_info' or 'temp_share_info' depending on value of | |
216 // is_temporary. Returns true on success, false on error. | |
217 bool CreateShareInfoTable(bool is_temporary); | |
218 bool CreateShareInfoTableVersion71(bool is_temporary); | |
219 | |
220 // Create 'metas' or 'temp_metas' depending on value of is_temporary. Also | |
221 // create a 'deleted_metas' table using same schema. Returns true on success, | |
222 // false on error. | |
223 bool CreateMetasTable(bool is_temporary); | |
224 | |
225 // Returns true on success, false on error. | |
226 bool CreateModelsTable(); | |
227 bool CreateV71ModelsTable(); | |
228 bool CreateV75ModelsTable(); | |
229 bool CreateV81ModelsTable(); | |
230 | |
231 // Returns true on success, false on error. | |
232 bool MigrateToSpecifics(const char* old_columns, | |
233 const char* specifics_column, | |
234 void(*handler_function) ( | |
235 sql::Statement* old_value_query, | |
236 int old_value_column, | |
237 sync_pb::EntitySpecifics* mutable_new_value)); | |
238 | |
239 // Returns true on success, false on error. | |
240 bool Vacuum(); | |
241 | |
242 // Returns true on success, false on error. | |
243 bool UpdatePageSizeIfNecessary(); | |
244 | |
245 // Prepares |save_statement| for saving entries in |table|. | |
246 void PrepareSaveEntryStatement(EntryTable table, | |
247 sql::Statement* save_statement); | |
248 | |
249 const std::string dir_name_; | |
250 const int database_page_size_; | |
251 | |
252 std::unique_ptr<sql::Connection> db_; | |
253 sql::Statement save_meta_statement_; | |
254 sql::Statement save_delete_journal_statement_; | |
255 | |
256 // Set to true if migration left some old columns around that need to be | |
257 // discarded. | |
258 bool needs_metas_column_refresh_; | |
259 bool needs_share_info_column_refresh_; | |
260 | |
261 // We keep a copy of the Closure so we reinstall it when the underlying | |
262 // sql::Connection is destroyed/recreated. | |
263 base::Closure catastrophic_error_handler_; | |
264 | |
265 DISALLOW_COPY_AND_ASSIGN(DirectoryBackingStore); | |
266 }; | |
267 | |
268 } // namespace syncable | |
269 } // namespace syncer | |
270 | |
271 #endif // SYNC_SYNCABLE_DIRECTORY_BACKING_STORE_H_ | |
OLD | NEW |