blob: e832da600147004cbcc5cb80d06db04cc977695a [file] [log] [blame]
[email protected]8d409412013-07-19 18:25:301// 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 SQL_RECOVERY_H_
6#define SQL_RECOVERY_H_
7
8#include "base/basictypes.h"
9
10#include "sql/connection.h"
11
12namespace base {
13class FilePath;
14}
15
16namespace sql {
17
18// Recovery module for sql/. The basic idea is to create a fresh
19// database and populate it with the recovered contents of the
20// original database. If recovery is successful, the recovered
21// database is backed up over the original database. If recovery is
22// not successful, the original database is razed. In either case,
23// the original handle is poisoned so that operations on the stack do
24// not accidentally disrupt the restored data.
25//
26// {
27// scoped_ptr<sql::Recovery> r =
28// sql::Recovery::Begin(orig_db, orig_db_path);
29// if (r) {
30// if (r.db()->Execute(kCreateSchemaSql) &&
31// r.db()->Execute(kCopyDataFromOrigSql)) {
32// sql::Recovery::Recovered(r.Pass());
33// }
34// }
35// }
36//
37// If Recovered() is not called, then RazeAndClose() is called on
38// orig_db.
39
40class SQL_EXPORT Recovery {
41 public:
42 ~Recovery();
43
44 // Begin the recovery process by opening a temporary database handle
45 // and attach the existing database to it at "corrupt". To prevent
46 // deadlock, all transactions on |connection| are rolled back.
47 //
48 // Returns NULL in case of failure, with no cleanup done on the
49 // original connection (except for breaking the transactions). The
50 // caller should Raze() or otherwise cleanup as appropriate.
51 //
52 // TODO(shess): Later versions of SQLite allow extracting the path
53 // from the connection.
54 // TODO(shess): Allow specifying the connection point?
55 static scoped_ptr<Recovery> Begin(
56 Connection* connection,
57 const base::FilePath& db_path) WARN_UNUSED_RESULT;
58
59 // Mark recovery completed by replicating the recovery database over
60 // the original database, then closing the recovery database. The
61 // original database handle is poisoned, causing future calls
62 // against it to fail.
63 //
64 // If Recovered() is not called, the destructor will call
65 // Unrecoverable().
66 //
[email protected]74cdede2013-09-25 05:39:5767 // TODO(shess): At this time, this function can fail while leaving
[email protected]8d409412013-07-19 18:25:3068 // the original database intact. Figure out which failure cases
69 // should go to RazeAndClose() instead.
70 static bool Recovered(scoped_ptr<Recovery> r) WARN_UNUSED_RESULT;
71
72 // Indicate that the database is unrecoverable. The original
73 // database is razed, and the handle poisoned.
74 static void Unrecoverable(scoped_ptr<Recovery> r);
75
[email protected]74cdede2013-09-25 05:39:5776 // When initially developing recovery code, sometimes the possible
77 // database states are not well-understood without further
78 // diagnostics. Abandon recovery but do not raze the original
79 // database.
80 // NOTE(shess): Only call this when adding recovery support. In the
81 // steady state, all databases should progress to recovered or razed.
82 static void Rollback(scoped_ptr<Recovery> r);
83
[email protected]8d409412013-07-19 18:25:3084 // Handle to the temporary recovery database.
85 sql::Connection* db() { return &recover_db_; }
86
87 private:
88 explicit Recovery(Connection* connection);
89
90 // Setup the recovery database handle for Begin(). Returns false in
91 // case anything failed.
92 bool Init(const base::FilePath& db_path) WARN_UNUSED_RESULT;
93
94 // Copy the recovered database over the original database.
95 bool Backup() WARN_UNUSED_RESULT;
96
97 // Close the recovery database, and poison the original handle.
98 // |raze| controls whether the original database is razed or just
99 // poisoned.
100 enum Disposition {
101 RAZE_AND_POISON,
102 POISON,
103 };
104 void Shutdown(Disposition raze);
105
106 Connection* db_; // Original database connection.
107 Connection recover_db_; // Recovery connection.
108
109 DISALLOW_COPY_AND_ASSIGN(Recovery);
110};
111
112} // namespace sql
113
114#endif // SQL_RECOVERY_H_