Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: sql/recovery.h

Issue 1832173002: [sql] Database recovery system for Shortcuts. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address review comments from #9 and #10. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 SQL_RECOVERY_H_ 5 #ifndef SQL_RECOVERY_H_
6 #define SQL_RECOVERY_H_ 6 #define SQL_RECOVERY_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <memory> 10 #include <memory>
11 11
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "sql/connection.h" 13 #include "sql/connection.h"
14 14
15 namespace base { 15 namespace base {
16 class FilePath; 16 class FilePath;
17 } 17 }
18 18
19 namespace sql { 19 namespace sql {
20 20
21 // Recovery module for sql/. The basic idea is to create a fresh 21 // Recovery module for sql/. The basic idea is to create a fresh database and
22 // database and populate it with the recovered contents of the 22 // populate it with the recovered contents of the original database. If
23 // original database. If recovery is successful, the recovered 23 // recovery is successful, the recovered database is backed up over the original
24 // database is backed up over the original database. If recovery is 24 // database. If recovery is not successful, the original database is razed. In
25 // not successful, the original database is razed. In either case, 25 // either case, the original handle is poisoned so that operations on the stack
26 // the original handle is poisoned so that operations on the stack do 26 // do not accidentally disrupt the restored data.
27 // not accidentally disrupt the restored data. 27 //
28 // RecoverDatabaseOrRaze() automates this, including recoverying the schema of
29 // from the suspect database. If a database requires special handling, such as
30 // recovering between different schema, or tables requiring post-processing,
31 // then the module can be used manually like:
28 // 32 //
29 // { 33 // {
30 // std::unique_ptr<sql::Recovery> r = 34 // std::unique_ptr<sql::Recovery> r =
31 // sql::Recovery::Begin(orig_db, orig_db_path); 35 // sql::Recovery::Begin(orig_db, orig_db_path);
32 // if (r) { 36 // if (r) {
33 // // Create the schema to recover to. On failure, clear the 37 // // Create the schema to recover to. On failure, clear the
34 // // database. 38 // // database.
35 // if (!r.db()->Execute(kCreateSchemaSql)) { 39 // if (!r.db()->Execute(kCreateSchemaSql)) {
36 // sql::Recovery::Unrecoverable(std::move(r)); 40 // sql::Recovery::Unrecoverable(std::move(r));
37 // return; 41 // return;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 // and attach the existing database to it at "corrupt". To prevent 79 // and attach the existing database to it at "corrupt". To prevent
76 // deadlock, all transactions on |connection| are rolled back. 80 // deadlock, all transactions on |connection| are rolled back.
77 // 81 //
78 // Returns NULL in case of failure, with no cleanup done on the 82 // Returns NULL in case of failure, with no cleanup done on the
79 // original connection (except for breaking the transactions). The 83 // original connection (except for breaking the transactions). The
80 // caller should Raze() or otherwise cleanup as appropriate. 84 // caller should Raze() or otherwise cleanup as appropriate.
81 // 85 //
82 // TODO(shess): Later versions of SQLite allow extracting the path 86 // TODO(shess): Later versions of SQLite allow extracting the path
83 // from the connection. 87 // from the connection.
84 // TODO(shess): Allow specifying the connection point? 88 // TODO(shess): Allow specifying the connection point?
85 static std::unique_ptr<Recovery> Begin(Connection* connection, 89 static std::unique_ptr<Recovery> Begin(Connection* connection,
Mark P 2016/04/19 23:34:28 I'm surprised that you're changing the type of thi
Scott Hess - ex-Googler 2016/05/13 21:24:36 The change from base::scoped_ptr<> to std::unique_
86 const base::FilePath& db_path) 90 const base::FilePath& db_path)
87 WARN_UNUSED_RESULT; 91 WARN_UNUSED_RESULT;
88 92
89 // Mark recovery completed by replicating the recovery database over 93 // Mark recovery completed by replicating the recovery database over
90 // the original database, then closing the recovery database. The 94 // the original database, then closing the recovery database. The
91 // original database handle is poisoned, causing future calls 95 // original database handle is poisoned, causing future calls
92 // against it to fail. 96 // against it to fail.
93 // 97 //
94 // If Recovered() is not called, the destructor will call 98 // If Recovered() is not called, the destructor will call
95 // Unrecoverable(). 99 // Unrecoverable().
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 // table as needed. 148 // table as needed.
145 bool SetupMeta(); 149 bool SetupMeta();
146 150
147 // Fetch the version number from temp.recover_meta. Returns false 151 // Fetch the version number from temp.recover_meta. Returns false
148 // if the query fails, or if there is no version row. Otherwise 152 // if the query fails, or if there is no version row. Otherwise
149 // returns true, with the version in |*version_number|. 153 // returns true, with the version in |*version_number|.
150 // 154 //
151 // Only valid to call after successful SetupMeta(). 155 // Only valid to call after successful SetupMeta().
152 bool GetMetaVersionNumber(int* version_number); 156 bool GetMetaVersionNumber(int* version_number);
153 157
158 // Attempt to recover the database by creating a new database with schema from
159 // |db|, then copying over as much data as possible. If the database is
160 // entirely unreadable, the new database will be empty. After this call, the
161 // |db| handle will be poisoned so that future calls will return errors until
162 // the handle is re-opened.
163 //
164 // The "OrRaze" portion means that if recovery fails due to errors, the
165 // database can be razed or deleted. The goal is for this function to make
166 // every possible effort to leave behind a correctly operating database file.
167 //
168 // If a corrupt database contains tables without unique indices, the resulting
169 // table may contain duplication. If this is not acceptable, the client
170 // should use the manual process as described in the example at the top of the
171 // file, cleaning up data at the appropriate points.
172 static void RecoverDatabaseOrRaze(Connection* db,
Mark P 2016/04/19 23:34:28 Thanks for the long response. Fundamentally, my c
Scott Hess - ex-Googler 2016/05/13 21:24:36 Done.
173 const base::FilePath& db_path);
174
175 // Returns true for SQLite errors which RecoverDatabaseOrRaze() can recover,
176 // or which cannot plausibly be recovered (and should be razed). This does
Mark P 2016/04/19 23:34:28 nit: or which -> versus You don't mean "or", at le
Scott Hess - ex-Googler 2016/05/13 21:24:36 Just removed the comparison clause entirely.
177 // not guarantee that RecoverDatabaseOrRaze() will successfully recover any
178 // data. Returning false means the error is not related to the contents of
179 // the database (such as SQLITE_BUSY or SQLITE_MISUSE), or is not verified to
180 // be handled correctly (such as SQLITE_IOERR or SQLITE_FULL).
181 static bool ShouldRecoverOrRaze(int extended_error);
182
154 private: 183 private:
155 explicit Recovery(Connection* connection); 184 explicit Recovery(Connection* connection);
156 185
157 // Setup the recovery database handle for Begin(). Returns false in 186 // Setup the recovery database handle for Begin(). Returns false in
158 // case anything failed. 187 // case anything failed.
159 bool Init(const base::FilePath& db_path) WARN_UNUSED_RESULT; 188 bool Init(const base::FilePath& db_path) WARN_UNUSED_RESULT;
160 189
161 // Copy the recovered database over the original database. 190 // Copy the recovered database over the original database.
162 bool Backup() WARN_UNUSED_RESULT; 191 bool Backup() WARN_UNUSED_RESULT;
163 192
164 // Close the recovery database, and poison the original handle. 193 // Close the recovery database, and poison the original handle.
165 // |raze| controls whether the original database is razed or just 194 // |raze| controls whether the original database is razed or just
166 // poisoned. 195 // poisoned.
167 enum Disposition { 196 enum Disposition {
168 RAZE_AND_POISON, 197 RAZE_AND_POISON,
169 POISON, 198 POISON,
170 }; 199 };
171 void Shutdown(Disposition raze); 200 void Shutdown(Disposition raze);
172 201
173 Connection* db_; // Original database connection. 202 Connection* db_; // Original database connection.
174 Connection recover_db_; // Recovery connection. 203 Connection recover_db_; // Recovery connection.
175 204
176 DISALLOW_COPY_AND_ASSIGN(Recovery); 205 DISALLOW_COPY_AND_ASSIGN(Recovery);
177 }; 206 };
178 207
179 } // namespace sql 208 } // namespace sql
180 209
181 #endif // SQL_RECOVERY_H_ 210 #endif // SQL_RECOVERY_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698