| OLD | NEW |
| 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/history/core/browser/thumbnail_database.h" | 5 #include "components/history/core/browser/thumbnail_database.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 namespace { | 75 namespace { |
| 76 | 76 |
| 77 // For this database, schema migrations are deprecated after two | 77 // For this database, schema migrations are deprecated after two |
| 78 // years. This means that the oldest non-deprecated version should be | 78 // years. This means that the oldest non-deprecated version should be |
| 79 // two years old or greater (thus the migrations to get there are | 79 // two years old or greater (thus the migrations to get there are |
| 80 // older). Databases containing deprecated versions will be cleared | 80 // older). Databases containing deprecated versions will be cleared |
| 81 // at startup. Since this database is a cache, losing old data is not | 81 // at startup. Since this database is a cache, losing old data is not |
| 82 // fatal (in fact, very old data may be expired immediately at startup | 82 // fatal (in fact, very old data may be expired immediately at startup |
| 83 // anyhow). | 83 // anyhow). |
| 84 | 84 |
| 85 // Version 8: ???????? by rogerm@chromium.org on 2015-??-?? | 85 // Version 8: 982ef2c1/r323176 by rogerm@chromium.org on 2015-03-31 |
| 86 // Version 7: 911a634d/r209424 by qsr@chromium.org on 2013-07-01 | 86 // Version 7: 911a634d/r209424 by qsr@chromium.org on 2013-07-01 |
| 87 // Version 6: 610f923b/r152367 by pkotwicz@chromium.org on 2012-08-20 | 87 // Version 6: 610f923b/r152367 by pkotwicz@chromium.org on 2012-08-20 (depr.) |
| 88 // Version 5: e2ee8ae9/r105004 by groby@chromium.org on 2011-10-12 (deprecated) | 88 // Version 5: e2ee8ae9/r105004 by groby@chromium.org on 2011-10-12 (deprecated) |
| 89 // Version 4: 5f104d76/r77288 by sky@chromium.org on 2011-03-08 (deprecated) | 89 // Version 4: 5f104d76/r77288 by sky@chromium.org on 2011-03-08 (deprecated) |
| 90 // Version 3: 09911bf3/r15 by initial.commit on 2008-07-26 (deprecated) | 90 // Version 3: 09911bf3/r15 by initial.commit on 2008-07-26 (deprecated) |
| 91 | 91 |
| 92 // Version number of the database. | 92 // Version number of the database. |
| 93 // NOTE(shess): When changing the version, add a new golden file for | 93 // NOTE(shess): When changing the version, add a new golden file for |
| 94 // the new version and a test to verify that Init() works with it. | 94 // the new version and a test to verify that Init() works with it. |
| 95 const int kCurrentVersionNumber = 8; | 95 const int kCurrentVersionNumber = 8; |
| 96 const int kCompatibleVersionNumber = 8; | 96 const int kCompatibleVersionNumber = 8; |
| 97 const int kDeprecatedVersionNumber = 5; // and earlier. | 97 const int kDeprecatedVersionNumber = 6; // and earlier. |
| 98 | 98 |
| 99 void FillIconMapping(const sql::Statement& statement, | 99 void FillIconMapping(const sql::Statement& statement, |
| 100 const GURL& page_url, | 100 const GURL& page_url, |
| 101 IconMapping* icon_mapping) { | 101 IconMapping* icon_mapping) { |
| 102 icon_mapping->mapping_id = statement.ColumnInt64(0); | 102 icon_mapping->mapping_id = statement.ColumnInt64(0); |
| 103 icon_mapping->icon_id = statement.ColumnInt64(1); | 103 icon_mapping->icon_id = statement.ColumnInt64(1); |
| 104 icon_mapping->icon_type = | 104 icon_mapping->icon_type = |
| 105 static_cast<favicon_base::IconType>(statement.ColumnInt(2)); | 105 static_cast<favicon_base::IconType>(statement.ColumnInt(2)); |
| 106 icon_mapping->icon_url = GURL(statement.ColumnString(3)); | 106 icon_mapping->icon_url = GURL(statement.ColumnString(3)); |
| 107 icon_mapping->page_url = page_url; | 107 icon_mapping->page_url = page_url; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 // TODO(shess): If this could be related to the time in the channel, then the | 139 // TODO(shess): If this could be related to the time in the channel, then the |
| 140 // rate could ramp up over time. Perhaps could remember the timestamp the | 140 // rate could ramp up over time. Perhaps could remember the timestamp the |
| 141 // first time upload is considered, and ramp up 1% per day? | 141 // first time upload is considered, and ramp up 1% per day? |
| 142 static const uint64_t kReportPercent = 5; | 142 static const uint64_t kReportPercent = 5; |
| 143 uint64_t rand = base::RandGenerator(100); | 143 uint64_t rand = base::RandGenerator(100); |
| 144 if (rand <= kReportPercent) | 144 if (rand <= kReportPercent) |
| 145 db->ReportDiagnosticInfo(extended_error, stmt); | 145 db->ReportDiagnosticInfo(extended_error, stmt); |
| 146 } | 146 } |
| 147 | 147 |
| 148 // NOTE(shess): Schema modifications must consider initial creation in | 148 // NOTE(shess): Schema modifications must consider initial creation in |
| 149 // |InitImpl()|, recovery in |RecoverDatabaseOrRaze()|, and history pruning in | 149 // |InitImpl()| and history pruning in |RetainDataForPageUrls()|. |
| 150 // |RetainDataForPageUrls()|. | |
| 151 bool InitTables(sql::Connection* db) { | 150 bool InitTables(sql::Connection* db) { |
| 152 const char kIconMappingSql[] = | 151 const char kIconMappingSql[] = |
| 153 "CREATE TABLE IF NOT EXISTS icon_mapping" | 152 "CREATE TABLE IF NOT EXISTS icon_mapping" |
| 154 "(" | 153 "(" |
| 155 "id INTEGER PRIMARY KEY," | 154 "id INTEGER PRIMARY KEY," |
| 156 "page_url LONGVARCHAR NOT NULL," | 155 "page_url LONGVARCHAR NOT NULL," |
| 157 "icon_id INTEGER" | 156 "icon_id INTEGER" |
| 158 ")"; | 157 ")"; |
| 159 if (!db->Execute(kIconMappingSql)) | 158 if (!db->Execute(kIconMappingSql)) |
| 160 return false; | 159 return false; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 183 // the same layout. | 182 // the same layout. |
| 184 "last_requested INTEGER DEFAULT 0" | 183 "last_requested INTEGER DEFAULT 0" |
| 185 ")"; | 184 ")"; |
| 186 if (!db->Execute(kFaviconBitmapsSql)) | 185 if (!db->Execute(kFaviconBitmapsSql)) |
| 187 return false; | 186 return false; |
| 188 | 187 |
| 189 return true; | 188 return true; |
| 190 } | 189 } |
| 191 | 190 |
| 192 // NOTE(shess): Schema modifications must consider initial creation in | 191 // NOTE(shess): Schema modifications must consider initial creation in |
| 193 // |InitImpl()|, recovery in |RecoverDatabaseOrRaze()|, and history pruning in | 192 // |InitImpl()| and history pruning in |RetainDataForPageUrls()|. |
| 194 // |RetainDataForPageUrls()|. | |
| 195 bool InitIndices(sql::Connection* db) { | 193 bool InitIndices(sql::Connection* db) { |
| 196 const char kIconMappingUrlIndexSql[] = | 194 const char kIconMappingUrlIndexSql[] = |
| 197 "CREATE INDEX IF NOT EXISTS icon_mapping_page_url_idx" | 195 "CREATE INDEX IF NOT EXISTS icon_mapping_page_url_idx" |
| 198 " ON icon_mapping(page_url)"; | 196 " ON icon_mapping(page_url)"; |
| 199 const char kIconMappingIdIndexSql[] = | 197 const char kIconMappingIdIndexSql[] = |
| 200 "CREATE INDEX IF NOT EXISTS icon_mapping_icon_id_idx" | 198 "CREATE INDEX IF NOT EXISTS icon_mapping_icon_id_idx" |
| 201 " ON icon_mapping(icon_id)"; | 199 " ON icon_mapping(icon_id)"; |
| 202 if (!db->Execute(kIconMappingUrlIndexSql) || | 200 if (!db->Execute(kIconMappingUrlIndexSql) || |
| 203 !db->Execute(kIconMappingIdIndexSql)) { | 201 !db->Execute(kIconMappingIdIndexSql)) { |
| 204 return false; | 202 return false; |
| 205 } | 203 } |
| 206 | 204 |
| 207 const char kFaviconsIndexSql[] = | 205 const char kFaviconsIndexSql[] = |
| 208 "CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)"; | 206 "CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)"; |
| 209 if (!db->Execute(kFaviconsIndexSql)) | 207 if (!db->Execute(kFaviconsIndexSql)) |
| 210 return false; | 208 return false; |
| 211 | 209 |
| 212 const char kFaviconBitmapsIndexSql[] = | 210 const char kFaviconBitmapsIndexSql[] = |
| 213 "CREATE INDEX IF NOT EXISTS favicon_bitmaps_icon_id ON " | 211 "CREATE INDEX IF NOT EXISTS favicon_bitmaps_icon_id ON " |
| 214 "favicon_bitmaps(icon_id)"; | 212 "favicon_bitmaps(icon_id)"; |
| 215 if (!db->Execute(kFaviconBitmapsIndexSql)) | 213 if (!db->Execute(kFaviconBitmapsIndexSql)) |
| 216 return false; | 214 return false; |
| 217 | 215 |
| 218 return true; | 216 return true; |
| 219 } | 217 } |
| 220 | 218 |
| 221 enum RecoveryEventType { | |
| 222 RECOVERY_EVENT_RECOVERED = 0, | |
| 223 RECOVERY_EVENT_FAILED_SCOPER, | |
| 224 RECOVERY_EVENT_FAILED_META_VERSION_ERROR, // obsolete | |
| 225 RECOVERY_EVENT_FAILED_META_VERSION_NONE, // obsolete | |
| 226 RECOVERY_EVENT_FAILED_META_WRONG_VERSION6, // obsolete | |
| 227 RECOVERY_EVENT_FAILED_META_WRONG_VERSION5, // obsolete | |
| 228 RECOVERY_EVENT_FAILED_META_WRONG_VERSION, | |
| 229 RECOVERY_EVENT_FAILED_RECOVER_META, // obsolete | |
| 230 RECOVERY_EVENT_FAILED_META_INSERT, // obsolete | |
| 231 RECOVERY_EVENT_FAILED_INIT, | |
| 232 RECOVERY_EVENT_FAILED_RECOVER_FAVICONS, // obsolete | |
| 233 RECOVERY_EVENT_FAILED_FAVICONS_INSERT, // obsolete | |
| 234 RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS, // obsolete | |
| 235 RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT, // obsolete | |
| 236 RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING, // obsolete | |
| 237 RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT, // obsolete | |
| 238 RECOVERY_EVENT_RECOVERED_VERSION6, // obsolete | |
| 239 RECOVERY_EVENT_FAILED_META_INIT, | |
| 240 RECOVERY_EVENT_FAILED_META_VERSION, | |
| 241 RECOVERY_EVENT_DEPRECATED, | |
| 242 RECOVERY_EVENT_FAILED_V5_INITSCHEMA, // obsolete | |
| 243 RECOVERY_EVENT_FAILED_V5_AUTORECOVER_FAVICONS, // obsolete | |
| 244 RECOVERY_EVENT_FAILED_V5_AUTORECOVER_ICON_MAPPING, // obsolete | |
| 245 RECOVERY_EVENT_RECOVERED_VERSION5, // obsolete | |
| 246 RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICONS, | |
| 247 RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICON_BITMAPS, | |
| 248 RECOVERY_EVENT_FAILED_AUTORECOVER_ICON_MAPPING, | |
| 249 RECOVERY_EVENT_FAILED_COMMIT, | |
| 250 | |
| 251 // Always keep this at the end. | |
| 252 RECOVERY_EVENT_MAX, | |
| 253 }; | |
| 254 | |
| 255 void RecordRecoveryEvent(RecoveryEventType recovery_event) { | |
| 256 UMA_HISTOGRAM_ENUMERATION("History.FaviconsRecovery", | |
| 257 recovery_event, RECOVERY_EVENT_MAX); | |
| 258 } | |
| 259 | |
| 260 // Recover the database to the extent possible, razing it if recovery | |
| 261 // is not possible. | |
| 262 // TODO(shess): This is mostly just a safe proof of concept. In the | |
| 263 // real world, this database is probably not worthwhile recovering, as | |
| 264 // opposed to just razing it and starting over whenever corruption is | |
| 265 // detected. So this database is a good test subject. | |
| 266 void RecoverDatabaseOrRaze(sql::Connection* db, const base::FilePath& db_path) { | |
| 267 // NOTE(shess): This code is currently specific to the version | |
| 268 // number. I am working on simplifying things to loosen the | |
| 269 // dependency, meanwhile contact me if you need to bump the version. | |
| 270 DCHECK_EQ(8, kCurrentVersionNumber); | |
| 271 | |
| 272 // TODO(shess): Reset back after? | |
| 273 db->reset_error_callback(); | |
| 274 | |
| 275 // For histogram purposes. | |
| 276 size_t favicons_rows_recovered = 0; | |
| 277 size_t favicon_bitmaps_rows_recovered = 0; | |
| 278 size_t icon_mapping_rows_recovered = 0; | |
| 279 int64_t original_size = 0; | |
| 280 base::GetFileSize(db_path, &original_size); | |
| 281 | |
| 282 std::unique_ptr<sql::Recovery> recovery = sql::Recovery::Begin(db, db_path); | |
| 283 if (!recovery) { | |
| 284 // TODO(shess): Unable to create recovery connection. This | |
| 285 // implies something substantial is wrong. At this point |db| has | |
| 286 // been poisoned so there is nothing really to do. | |
| 287 // | |
| 288 // Possible responses are unclear. If the failure relates to a | |
| 289 // problem somehow specific to the temporary file used to back the | |
| 290 // database, then an in-memory database could possibly be used. | |
| 291 // This could potentially allow recovering the main database, and | |
| 292 // might be simple to implement w/in Begin(). | |
| 293 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_SCOPER); | |
| 294 return; | |
| 295 } | |
| 296 | |
| 297 // Setup the meta recovery table and fetch the version number from | |
| 298 // the corrupt database. | |
| 299 int version = 0; | |
| 300 if (!recovery->SetupMeta() || !recovery->GetMetaVersionNumber(&version)) { | |
| 301 // TODO(shess): Prior histograms indicate all failures are in | |
| 302 // creating the recover virtual table for corrupt.meta. The table | |
| 303 // may not exist, or the database may be too far gone. Either | |
| 304 // way, unclear how to resolve. | |
| 305 sql::Recovery::Rollback(std::move(recovery)); | |
| 306 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION); | |
| 307 return; | |
| 308 } | |
| 309 | |
| 310 // This code may be able to fetch version information that the regular | |
| 311 // deprecation path cannot. | |
| 312 // NOTE(shess,rogerm): v6 is not currently deprecated in the normal Init() | |
| 313 // path, but is deprecated in the recovery path in the interest of keeping | |
| 314 // the code simple. http://crbug.com/327485 for numbers. | |
| 315 DCHECK_LE(kDeprecatedVersionNumber, 6); | |
| 316 if (version <= 6) { | |
| 317 sql::Recovery::Unrecoverable(std::move(recovery)); | |
| 318 RecordRecoveryEvent(RECOVERY_EVENT_DEPRECATED); | |
| 319 return; | |
| 320 } | |
| 321 | |
| 322 // Earlier versions have been handled or deprecated. | |
| 323 if (version < 7) { | |
| 324 sql::Recovery::Unrecoverable(std::move(recovery)); | |
| 325 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION); | |
| 326 return; | |
| 327 } | |
| 328 | |
| 329 // Recover to current schema version. | |
| 330 sql::MetaTable recover_meta_table; | |
| 331 if (!recover_meta_table.Init(recovery->db(), kCurrentVersionNumber, | |
| 332 kCompatibleVersionNumber)) { | |
| 333 sql::Recovery::Rollback(std::move(recovery)); | |
| 334 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_INIT); | |
| 335 return; | |
| 336 } | |
| 337 | |
| 338 // Create a fresh version of the database. The recovery code uses | |
| 339 // conflict-resolution to handle duplicates, so the indices are | |
| 340 // necessary. | |
| 341 if (!InitTables(recovery->db()) || !InitIndices(recovery->db())) { | |
| 342 // TODO(shess): Unable to create the new schema in the new | |
| 343 // database. The new database should be a temporary file, so | |
| 344 // being unable to work with it is pretty unclear. | |
| 345 // | |
| 346 // What are the potential responses, even? The recovery database | |
| 347 // could be opened as in-memory. If the temp database had a | |
| 348 // filesystem problem and the temp filesystem differs from the | |
| 349 // main database, then that could fix it. | |
| 350 sql::Recovery::Rollback(std::move(recovery)); | |
| 351 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_INIT); | |
| 352 return; | |
| 353 } | |
| 354 | |
| 355 if (!recovery->AutoRecoverTable("favicons", &favicons_rows_recovered)) { | |
| 356 sql::Recovery::Rollback(std::move(recovery)); | |
| 357 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICONS); | |
| 358 return; | |
| 359 } | |
| 360 if (!recovery->AutoRecoverTable("favicon_bitmaps", | |
| 361 &favicon_bitmaps_rows_recovered)) { | |
| 362 sql::Recovery::Rollback(std::move(recovery)); | |
| 363 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICON_BITMAPS); | |
| 364 return; | |
| 365 } | |
| 366 if (!recovery->AutoRecoverTable("icon_mapping", | |
| 367 &icon_mapping_rows_recovered)) { | |
| 368 sql::Recovery::Rollback(std::move(recovery)); | |
| 369 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_ICON_MAPPING); | |
| 370 return; | |
| 371 } | |
| 372 | |
| 373 // TODO(shess): Is it possible/likely to have broken foreign-key | |
| 374 // issues with the tables? | |
| 375 // - icon_mapping.icon_id maps to no favicons.id | |
| 376 // - favicon_bitmaps.icon_id maps to no favicons.id | |
| 377 // - favicons.id is referenced by no icon_mapping.icon_id | |
| 378 // - favicons.id is referenced by no favicon_bitmaps.icon_id | |
| 379 // This step is possibly not worth the effort necessary to develop | |
| 380 // and sequence the statements, as it is basically a form of garbage | |
| 381 // collection. | |
| 382 | |
| 383 if (!sql::Recovery::Recovered(std::move(recovery))) { | |
| 384 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_COMMIT); | |
| 385 return; | |
| 386 } | |
| 387 | |
| 388 // Track the size of the recovered database relative to the size of | |
| 389 // the input database. The size should almost always be smaller, | |
| 390 // unless the input database was empty to start with. If the | |
| 391 // percentage results are very low, something is awry. | |
| 392 int64_t final_size = 0; | |
| 393 if (original_size > 0 && | |
| 394 base::GetFileSize(db_path, &final_size) && | |
| 395 final_size > 0) { | |
| 396 int percentage = static_cast<int>(original_size * 100 / final_size); | |
| 397 UMA_HISTOGRAM_PERCENTAGE("History.FaviconsRecoveredPercentage", | |
| 398 std::max(100, percentage)); | |
| 399 } | |
| 400 | |
| 401 // Using 10,000 because these cases mostly care about "none | |
| 402 // recovered" and "lots recovered". More than 10,000 rows recovered | |
| 403 // probably means there's something wrong with the profile. | |
| 404 UMA_HISTOGRAM_COUNTS_10000("History.FaviconsRecoveredRowsFavicons", | |
| 405 static_cast<int>(favicons_rows_recovered)); | |
| 406 UMA_HISTOGRAM_COUNTS_10000("History.FaviconsRecoveredRowsFaviconBitmaps", | |
| 407 static_cast<int>(favicon_bitmaps_rows_recovered)); | |
| 408 UMA_HISTOGRAM_COUNTS_10000("History.FaviconsRecoveredRowsIconMapping", | |
| 409 static_cast<int>(icon_mapping_rows_recovered)); | |
| 410 | |
| 411 RecordRecoveryEvent(RECOVERY_EVENT_RECOVERED); | |
| 412 } | |
| 413 | |
| 414 void DatabaseErrorCallback(sql::Connection* db, | 219 void DatabaseErrorCallback(sql::Connection* db, |
| 415 const base::FilePath& db_path, | 220 const base::FilePath& db_path, |
| 416 HistoryBackendClient* backend_client, | 221 HistoryBackendClient* backend_client, |
| 417 int extended_error, | 222 int extended_error, |
| 418 sql::Statement* stmt) { | 223 sql::Statement* stmt) { |
| 419 // TODO(shess): Assert that this is running on a safe thread. | 224 // TODO(shess): Assert that this is running on a safe thread. |
| 420 // AFAICT, should be the history thread, but at this level I can't | 225 // AFAICT, should be the history thread, but at this level I can't |
| 421 // see how to reach that. | 226 // see how to reach that. |
| 422 | 227 |
| 423 if (backend_client && backend_client->ShouldReportDatabaseError()) { | 228 if (backend_client && backend_client->ShouldReportDatabaseError()) { |
| 424 GenerateDiagnostics(db, extended_error, stmt); | 229 GenerateDiagnostics(db, extended_error, stmt); |
| 425 } | 230 } |
| 426 | 231 |
| 427 // Attempt to recover corrupt databases. | 232 // Attempt to recover corrupt databases. |
| 428 int error = (extended_error & 0xFF); | 233 if (sql::Recovery::ShouldRecover(extended_error)) { |
| 429 if (error == SQLITE_CORRUPT || | 234 // NOTE(shess): This approach is valid as of version 8. When bumping the |
| 430 error == SQLITE_CANTOPEN || | 235 // version, it will PROBABLY remain valid, but consider whether any schema |
| 431 error == SQLITE_NOTADB) { | 236 // changes might break automated recovery. |
| 432 RecoverDatabaseOrRaze(db, db_path); | 237 DCHECK_EQ(8, kCurrentVersionNumber); |
| 238 |
| 239 // Prevent reentrant calls. |
| 240 db->reset_error_callback(); |
| 241 |
| 242 // TODO(shess): Is it possible/likely to have broken foreign-key |
| 243 // issues with the tables? |
| 244 // - icon_mapping.icon_id maps to no favicons.id |
| 245 // - favicon_bitmaps.icon_id maps to no favicons.id |
| 246 // - favicons.id is referenced by no icon_mapping.icon_id |
| 247 // - favicons.id is referenced by no favicon_bitmaps.icon_id |
| 248 // This step is possibly not worth the effort necessary to develop |
| 249 // and sequence the statements, as it is basically a form of garbage |
| 250 // collection. |
| 251 |
| 252 // After this call, the |db| handle is poisoned so that future calls will |
| 253 // return errors until the handle is re-opened. |
| 254 sql::Recovery::RecoverDatabaseWithMetaVersion(db, db_path); |
| 255 |
| 256 // The DLOG(FATAL) below is intended to draw immediate attention to errors |
| 257 // in newly-written code. Database corruption is generally a result of OS |
| 258 // or hardware issues, not coding errors at the client level, so displaying |
| 259 // the error would probably lead to confusion. The ignored call signals the |
| 260 // test-expectation framework that the error was handled. |
| 261 ignore_result(sql::Connection::IsExpectedSqliteError(extended_error)); |
| 262 return; |
| 433 } | 263 } |
| 434 | 264 |
| 435 // The default handling is to assert on debug and to ignore on release. | 265 // The default handling is to assert on debug and to ignore on release. |
| 436 if (!sql::Connection::IsExpectedSqliteError(extended_error)) | 266 if (!sql::Connection::IsExpectedSqliteError(extended_error)) |
| 437 DLOG(FATAL) << db->GetErrorMessage(); | 267 DLOG(FATAL) << db->GetErrorMessage(); |
| 438 } | 268 } |
| 439 | 269 |
| 440 } // namespace | 270 } // namespace |
| 441 | 271 |
| 442 ThumbnailDatabase::IconMappingEnumerator::IconMappingEnumerator() { | 272 ThumbnailDatabase::IconMappingEnumerator::IconMappingEnumerator() { |
| (...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1237 meta_table_.SetVersionNumber(8); | 1067 meta_table_.SetVersionNumber(8); |
| 1238 meta_table_.SetCompatibleVersionNumber(std::min(8, kCompatibleVersionNumber)); | 1068 meta_table_.SetCompatibleVersionNumber(std::min(8, kCompatibleVersionNumber)); |
| 1239 return true; | 1069 return true; |
| 1240 } | 1070 } |
| 1241 | 1071 |
| 1242 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { | 1072 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { |
| 1243 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); | 1073 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); |
| 1244 } | 1074 } |
| 1245 | 1075 |
| 1246 } // namespace history | 1076 } // namespace history |
| OLD | NEW |