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

Side by Side Diff: components/omnibox/browser/shortcuts_database.cc

Issue 1832173002: [sql] Database recovery system for Shortcuts. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: iOS SQLite doesn't support column names in view definition. Created 4 years, 9 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "components/omnibox/browser/shortcuts_database.h" 5 #include "components/omnibox/browser/shortcuts_database.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h"
9 #include "base/guid.h" 10 #include "base/guid.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
12 #include "base/time/time.h" 13 #include "base/time/time.h"
13 #include "components/omnibox/browser/autocomplete_match_type.h" 14 #include "components/omnibox/browser/autocomplete_match_type.h"
14 #include "sql/meta_table.h" 15 #include "sql/meta_table.h"
16 #include "sql/recovery.h"
15 #include "sql/statement.h" 17 #include "sql/statement.h"
16 #include "sql/transaction.h" 18 #include "sql/transaction.h"
17 #include "ui/base/page_transition_types.h" 19 #include "ui/base/page_transition_types.h"
18 20
19 21
20 // Helpers -------------------------------------------------------------------- 22 // Helpers --------------------------------------------------------------------
21 23
22 namespace { 24 namespace {
23 25
24 // Current version number. We write databases at the "current" version number, 26 // Current version number. We write databases at the "current" version number,
(...skipping 23 matching lines...) Expand all
48 bool DeleteShortcut(const char* field_name, 50 bool DeleteShortcut(const char* field_name,
49 const std::string& id, 51 const std::string& id,
50 sql::Connection& db) { 52 sql::Connection& db) {
51 sql::Statement s(db.GetUniqueStatement( 53 sql::Statement s(db.GetUniqueStatement(
52 base::StringPrintf("DELETE FROM omni_box_shortcuts WHERE %s = ?", 54 base::StringPrintf("DELETE FROM omni_box_shortcuts WHERE %s = ?",
53 field_name).c_str())); 55 field_name).c_str()));
54 s.BindString(0, id); 56 s.BindString(0, id);
55 return s.Run(); 57 return s.Run();
56 } 58 }
57 59
60 void DatabaseErrorCallback(sql::Connection* db,
61 const base::FilePath& db_path,
62 int extended_error,
63 sql::Statement* stmt) {
64 // Attempt to fix corrupt databases. SQLITE_CANTOPEN and SQLITE_NOTADB
65 // generally mean that the file doesn't even look like a SQLite database, for
66 // instance if the header is broken, but there are a few cases that can be
67 // recovered. SQLITE_CORRUPT generally means that data within the database
68 // contradicts itself, but SQLite is able to read it.
Mark P 2016/04/07 23:09:43 Do you want this explanation here rather than than
Scott Hess - ex-Googler 2016/04/15 00:38:14 Acknowledged.
69 // TODO(shess): At least some of the SQLITE_IOERR cases might be cleared by
70 // this, too. Probable loss of data, but the disk block is unlikely to fix
71 // itself.
Mark P 2016/04/07 23:09:43 ditto about this TODO
Scott Hess - ex-Googler 2016/04/15 00:38:14 Leftover from when the code checked directly again
72 if (sql::Recovery::ShouldRecoverOrRaze(extended_error)) {
73 // Prevent reentrant calls.
74 db->reset_error_callback();
75
76 // Attempt to recover the database by creating a new database with the
77 // schema from the current database, and copying over as much of the data as
78 // possible. Then restore the new database over the original. If the
79 // database is unreadable, the new database will be empty.
80 //
81 // After this call, the |db| handle is poisoned so that future calls will
82 // return errors until the handle is re-opened.
Mark P 2016/04/07 23:09:43 This comment duplicates much of the comment by the
Scott Hess - ex-Googler 2016/04/15 00:38:14 OK. Leaving the last line, because IMHO it's pert
83 sql::Recovery::RecoverDatabaseOrRaze(db, db_path);
84 }
85
86 // The default handling is to assert on debug and to ignore on release.
87 if (!sql::Connection::ShouldIgnoreSqliteError(extended_error))
Mark P 2016/04/07 23:09:43 Do you still want to run this code / possibly disp
Scott Hess - ex-Googler 2016/04/15 00:38:14 I'll have to think about this. Corruption general
88 DLOG(FATAL) << db->GetErrorMessage();
89 }
90
58 } // namespace 91 } // namespace
59 92
60 // ShortcutsDatabase::Shortcut::MatchCore ------------------------------------- 93 // ShortcutsDatabase::Shortcut::MatchCore -------------------------------------
61 94
62 ShortcutsDatabase::Shortcut::MatchCore::MatchCore( 95 ShortcutsDatabase::Shortcut::MatchCore::MatchCore(
63 const base::string16& fill_into_edit, 96 const base::string16& fill_into_edit,
64 const GURL& destination_url, 97 const GURL& destination_url,
65 const base::string16& contents, 98 const base::string16& contents,
66 const std::string& contents_class, 99 const std::string& contents_class,
67 const base::string16& description, 100 const base::string16& description,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 149
117 // ShortcutsDatabase ---------------------------------------------------------- 150 // ShortcutsDatabase ----------------------------------------------------------
118 151
119 ShortcutsDatabase::ShortcutsDatabase(const base::FilePath& database_path) 152 ShortcutsDatabase::ShortcutsDatabase(const base::FilePath& database_path)
120 : database_path_(database_path) { 153 : database_path_(database_path) {
121 } 154 }
122 155
123 bool ShortcutsDatabase::Init() { 156 bool ShortcutsDatabase::Init() {
124 db_.set_histogram_tag("Shortcuts"); 157 db_.set_histogram_tag("Shortcuts");
125 158
159 // To recover from corruption.
160 db_.set_error_callback(
161 base::Bind(&DatabaseErrorCallback, &db_, database_path_));
162
126 // Set the database page size to something a little larger to give us 163 // Set the database page size to something a little larger to give us
127 // better performance (we're typically seek rather than bandwidth limited). 164 // better performance (we're typically seek rather than bandwidth limited).
128 // This only has an effect before any tables have been created, otherwise 165 // This only has an effect before any tables have been created, otherwise
129 // this is a NOP. Must be a power of 2 and a max of 8192. 166 // this is a NOP. Must be a power of 2 and a max of 8192.
130 db_.set_page_size(4096); 167 db_.set_page_size(4096);
131 168
132 // Run the database in exclusive mode. Nobody else should be accessing the 169 // Run the database in exclusive mode. Nobody else should be accessing the
133 // database while we're running, and this will give somewhat improved perf. 170 // database while we're running, and this will give somewhat improved perf.
134 db_.set_exclusive_locking(); 171 db_.set_exclusive_locking();
135 172
136 // Attach the database to our index file. 173 // Attach the database to our index file.
174 // TODO(shess): The return value is never checked, so failures will never be
175 // addressed. Someone needs to handle invalid schema.
Mark P 2016/04/07 23:09:43 This shouldn't be a comment. File a bug against p
Scott Hess - ex-Googler 2016/04/15 00:38:14 OK. Adding http://crbug.com/603304 about this. I
137 return db_.Open(database_path_) && EnsureTable(); 176 return db_.Open(database_path_) && EnsureTable();
138 } 177 }
139 178
140 bool ShortcutsDatabase::AddShortcut(const Shortcut& shortcut) { 179 bool ShortcutsDatabase::AddShortcut(const Shortcut& shortcut) {
141 sql::Statement s(db_.GetCachedStatement( 180 sql::Statement s(db_.GetCachedStatement(
142 SQL_FROM_HERE, 181 SQL_FROM_HERE,
143 "INSERT INTO omni_box_shortcuts (id, text, fill_into_edit, url, " 182 "INSERT INTO omni_box_shortcuts (id, text, fill_into_edit, url, "
144 "contents, contents_class, description, description_class, " 183 "contents, contents_class, description, description_class, "
145 "transition, type, keyword, last_access_time, number_of_hits) " 184 "transition, type, keyword, last_access_time, number_of_hits) "
146 "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)")); 185 "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 "UPDATE omni_box_shortcuts SET type = %d", 289 "UPDATE omni_box_shortcuts SET type = %d",
251 static_cast<int>(AutocompleteMatchType::HISTORY_TITLE)).c_str()) && 290 static_cast<int>(AutocompleteMatchType::HISTORY_TITLE)).c_str()) &&
252 db_.Execute("ALTER TABLE omni_box_shortcuts " 291 db_.Execute("ALTER TABLE omni_box_shortcuts "
253 "ADD COLUMN keyword VARCHAR") && 292 "ADD COLUMN keyword VARCHAR") &&
254 transaction.Commit())) { 293 transaction.Commit())) {
255 return false; 294 return false;
256 } 295 }
257 } 296 }
258 297
259 if (!sql::MetaTable::DoesTableExist(&db_)) { 298 if (!sql::MetaTable::DoesTableExist(&db_)) {
260 meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber);
261 sql::Transaction transaction(&db_); 299 sql::Transaction transaction(&db_);
262 if (!(transaction.Begin() && 300 if (!(transaction.Begin() &&
263 // Migrate old SEARCH_OTHER_ENGINE values to the new type value. 301 meta_table_.Init(
264 db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts " 302 &db_, kCurrentVersionNumber, kCompatibleVersionNumber) &&
265 "SET type = 13 WHERE type = 9").c_str()) && 303 // Migrate old SEARCH_OTHER_ENGINE values to the new type value.
266 // Migrate old EXTENSION_APP values to the new type value. 304 db_.Execute(
267 db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts " 305 "UPDATE omni_box_shortcuts SET type = 13 WHERE type = 9") &&
268 "SET type = 14 WHERE type = 10").c_str()) && 306 // Migrate old EXTENSION_APP values to the new type value.
269 // Migrate old CONTACT values to the new type value. 307 db_.Execute(
270 db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts " 308 "UPDATE omni_box_shortcuts SET type = 14 WHERE type = 10") &&
271 "SET type = 15 WHERE type = 11").c_str()) && 309 // Migrate old CONTACT values to the new type value.
272 // Migrate old BOOKMARK_TITLE values to the new type value. 310 db_.Execute(
273 db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts " 311 "UPDATE omni_box_shortcuts SET type = 15 WHERE type = 11") &&
274 "SET type = 16 WHERE type = 12").c_str()) && 312 // Migrate old BOOKMARK_TITLE values to the new type value.
275 transaction.Commit())) { 313 db_.Execute(
314 "UPDATE omni_box_shortcuts SET type = 16 WHERE type = 12") &&
315 transaction.Commit())) {
276 return false; 316 return false;
277 } 317 }
278 } 318 }
279 return true; 319 return true;
280 } 320 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698