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

Side by Side Diff: trunk/src/chrome/browser/history/thumbnail_database.cc

Issue 74933002: Revert 235492 "[sql] Recover Favicons v5 databases, with more re..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | trunk/src/chrome/browser/history/thumbnail_database_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "chrome/browser/history/thumbnail_database.h" 5 #include "chrome/browser/history/thumbnail_database.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 // want once-only handling? Sqlite.Error.Thumbnail shows 268 // want once-only handling? Sqlite.Error.Thumbnail shows
269 // CORRUPT and READONLY as almost 95% of all reports on these 269 // CORRUPT and READONLY as almost 95% of all reports on these
270 // channels, so probably easier to just harvest from the field. 270 // channels, so probably easier to just harvest from the field.
271 if (rand < kReportsPerMillion) { 271 if (rand < kReportsPerMillion) {
272 reported = true; 272 reported = true;
273 ReportError(db, extended_error); 273 ReportError(db, extended_error);
274 } 274 }
275 } 275 }
276 } 276 }
277 277
278 // Create v5 schema for recovery code.
279 bool InitSchemaV5(sql::Connection* db) {
280 // This schema was derived from the strings used when v5 was in
281 // force. The [favicons] index and the [icon_mapping] items were
282 // copied from the current strings, after verifying that the
283 // resulting schema exactly matches the schema created by the
284 // original versions of those strings. This allows the linker to
285 // share the strings if they match, while preferring correctness of
286 // the current versions change.
287
288 const char kFaviconsV5[] =
289 "CREATE TABLE IF NOT EXISTS favicons("
290 "id INTEGER PRIMARY KEY,"
291 "url LONGVARCHAR NOT NULL,"
292 "last_updated INTEGER DEFAULT 0,"
293 "image_data BLOB,"
294 "icon_type INTEGER DEFAULT 1,"
295 "sizes LONGVARCHAR"
296 ")";
297 const char kFaviconsIndexV5[] =
298 "CREATE INDEX IF NOT EXISTS favicons_url ON favicons(url)";
299 if (!db->Execute(kFaviconsV5) || !db->Execute(kFaviconsIndexV5))
300 return false;
301
302 const char kIconMappingV5[] =
303 "CREATE TABLE IF NOT EXISTS icon_mapping"
304 "("
305 "id INTEGER PRIMARY KEY,"
306 "page_url LONGVARCHAR NOT NULL,"
307 "icon_id INTEGER"
308 ")";
309 const char kIconMappingUrlIndexV5[] =
310 "CREATE INDEX IF NOT EXISTS icon_mapping_page_url_idx"
311 " ON icon_mapping(page_url)";
312 const char kIconMappingIdIndexV5[] =
313 "CREATE INDEX IF NOT EXISTS icon_mapping_icon_id_idx"
314 " ON icon_mapping(icon_id)";
315 if (!db->Execute(kIconMappingV5) ||
316 !db->Execute(kIconMappingUrlIndexV5) ||
317 !db->Execute(kIconMappingIdIndexV5)) {
318 return false;
319 }
320
321 return true;
322 }
323
324 // TODO(shess): Consider InitSchemaV7(). InitSchemaV5() is worthwhile
325 // because there appear to be 10s of thousands of marooned v5
326 // databases in the wild. Once recovery reaches stable, the number of
327 // corrupt-but-recoverable databases should drop, possibly to the
328 // point where it is not worthwhile to maintain previous-version
329 // recovery code.
330 // TODO(shess): Alternately, think on a way to more cleanly represent
331 // versioned schema going forward.
332 bool InitTables(sql::Connection* db) { 278 bool InitTables(sql::Connection* db) {
333 const char kIconMappingSql[] = 279 const char kIconMappingSql[] =
334 "CREATE TABLE IF NOT EXISTS icon_mapping" 280 "CREATE TABLE IF NOT EXISTS icon_mapping"
335 "(" 281 "("
336 "id INTEGER PRIMARY KEY," 282 "id INTEGER PRIMARY KEY,"
337 "page_url LONGVARCHAR NOT NULL," 283 "page_url LONGVARCHAR NOT NULL,"
338 "icon_id INTEGER" 284 "icon_id INTEGER"
339 ")"; 285 ")";
340 if (!db->Execute(kIconMappingSql)) 286 if (!db->Execute(kIconMappingSql))
341 return false; 287 return false;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 "favicon_bitmaps(icon_id)"; 335 "favicon_bitmaps(icon_id)";
390 if (!db->Execute(kFaviconBitmapsIndexSql)) 336 if (!db->Execute(kFaviconBitmapsIndexSql))
391 return false; 337 return false;
392 338
393 return true; 339 return true;
394 } 340 }
395 341
396 enum RecoveryEventType { 342 enum RecoveryEventType {
397 RECOVERY_EVENT_RECOVERED = 0, 343 RECOVERY_EVENT_RECOVERED = 0,
398 RECOVERY_EVENT_FAILED_SCOPER, 344 RECOVERY_EVENT_FAILED_SCOPER,
399 RECOVERY_EVENT_FAILED_META_VERSION_ERROR, // obsolete 345 RECOVERY_EVENT_FAILED_META_VERSION_ERROR,
400 RECOVERY_EVENT_FAILED_META_VERSION_NONE, // obsolete 346 RECOVERY_EVENT_FAILED_META_VERSION_NONE,
401 RECOVERY_EVENT_FAILED_META_WRONG_VERSION6, // obsolete 347 RECOVERY_EVENT_FAILED_META_WRONG_VERSION6, // obsolete
402 RECOVERY_EVENT_FAILED_META_WRONG_VERSION5, // obsolete 348 RECOVERY_EVENT_FAILED_META_WRONG_VERSION5,
403 RECOVERY_EVENT_FAILED_META_WRONG_VERSION, 349 RECOVERY_EVENT_FAILED_META_WRONG_VERSION,
404 RECOVERY_EVENT_FAILED_RECOVER_META, // obsolete 350 RECOVERY_EVENT_FAILED_RECOVER_META,
405 RECOVERY_EVENT_FAILED_META_INSERT, // obsolete 351 RECOVERY_EVENT_FAILED_META_INSERT, // obsolete
406 RECOVERY_EVENT_FAILED_INIT, 352 RECOVERY_EVENT_FAILED_INIT,
407 RECOVERY_EVENT_FAILED_RECOVER_FAVICONS, // obsolete 353 RECOVERY_EVENT_FAILED_RECOVER_FAVICONS,
408 RECOVERY_EVENT_FAILED_FAVICONS_INSERT, // obsolete 354 RECOVERY_EVENT_FAILED_FAVICONS_INSERT,
409 RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS, // obsolete 355 RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS,
410 RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT, // obsolete 356 RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT,
411 RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING, // obsolete 357 RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING,
412 RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT, // obsolete 358 RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT,
413 RECOVERY_EVENT_RECOVERED_VERSION6, 359 RECOVERY_EVENT_RECOVERED_VERSION6,
414 RECOVERY_EVENT_FAILED_META_INIT, 360 RECOVERY_EVENT_FAILED_META_INIT,
415 RECOVERY_EVENT_FAILED_META_VERSION,
416 RECOVERY_EVENT_DEPRECATED,
417 RECOVERY_EVENT_FAILED_V5_INITSCHEMA,
418 RECOVERY_EVENT_FAILED_V5_AUTORECOVER_FAVICONS,
419 RECOVERY_EVENT_FAILED_V5_AUTORECOVER_ICON_MAPPING,
420 RECOVERY_EVENT_RECOVERED_VERSION5,
421 RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICONS,
422 RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICON_BITMAPS,
423 RECOVERY_EVENT_FAILED_AUTORECOVER_ICON_MAPPING,
424 361
425 // Always keep this at the end. 362 // Always keep this at the end.
426 RECOVERY_EVENT_MAX, 363 RECOVERY_EVENT_MAX,
427 }; 364 };
428 365
429 void RecordRecoveryEvent(RecoveryEventType recovery_event) { 366 void RecordRecoveryEvent(RecoveryEventType recovery_event) {
430 UMA_HISTOGRAM_ENUMERATION("History.FaviconsRecovery", 367 UMA_HISTOGRAM_ENUMERATION("History.FaviconsRecovery",
431 recovery_event, RECOVERY_EVENT_MAX); 368 recovery_event, RECOVERY_EVENT_MAX);
432 } 369 }
433 370
(...skipping 27 matching lines...) Expand all
461 // 398 //
462 // Possible responses are unclear. If the failure relates to a 399 // Possible responses are unclear. If the failure relates to a
463 // problem somehow specific to the temporary file used to back the 400 // problem somehow specific to the temporary file used to back the
464 // database, then an in-memory database could possibly be used. 401 // database, then an in-memory database could possibly be used.
465 // This could potentially allow recovering the main database, and 402 // This could potentially allow recovering the main database, and
466 // might be simple to implement w/in Begin(). 403 // might be simple to implement w/in Begin().
467 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_SCOPER); 404 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_SCOPER);
468 return; 405 return;
469 } 406 }
470 407
471 // Setup the meta recovery table and fetch the version number from 408 // Setup the meta recovery table, and check that the version number
472 // the corrupt database. 409 // is covered by the recovery code.
473 int version = 0; 410 // TODO(shess): sql::Recovery should provide a helper to handle meta.
474 if (!recovery->SetupMeta() || !recovery->GetMetaVersionNumber(&version)) { 411 int version = 0; // For reporting which version was recovered.
475 // TODO(shess): Prior histograms indicate all failures are in 412 {
476 // creating the recover virtual table for corrupt.meta. The table 413 const char kRecoverySql[] =
477 // may not exist, or the database may be too far gone. Either 414 "CREATE VIRTUAL TABLE temp.recover_meta USING recover"
478 // way, unclear how to resolve. 415 "("
479 sql::Recovery::Rollback(recovery.Pass()); 416 "corrupt.meta,"
480 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION); 417 "key TEXT NOT NULL,"
481 return; 418 "value TEXT" // Really? Never int?
482 } 419 ")";
420 if (!recovery->db()->Execute(kRecoverySql)) {
421 // TODO(shess): Failure to create the recover_meta table could
422 // mean that the main database is too corrupt to access, or that
423 // the meta table doesn't exist.
424 sql::Recovery::Rollback(recovery.Pass());
425 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_META);
426 return;
427 }
483 428
484 // Recover v5 database to v5 schema. Next pass through Init() will 429 {
485 // migrate to v7. 430 const char kRecoveryVersionSql[] =
486 if (version == 5) { 431 "SELECT value FROM recover_meta WHERE key = 'version'";
432 sql::Statement recovery_version(
433 recovery->db()->GetUniqueStatement(kRecoveryVersionSql));
434 if (!recovery_version.Step()) {
435 if (!recovery_version.Succeeded()) {
436 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION_ERROR);
437 // TODO(shess): An error while processing the statement is
438 // probably not recoverable.
439 } else {
440 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_VERSION_NONE);
441 // TODO(shess): If a positive version lock cannot be achieved,
442 // the database could still be recovered by optimistically
443 // attempting to copy things. In the limit, the schema found
444 // could be inspected. Less clear is whether optimistic
445 // recovery really makes sense.
446 }
447 recovery_version.Clear();
448 sql::Recovery::Rollback(recovery.Pass());
449 return;
450 }
451 version = recovery_version.ColumnInt(0);
452
453 // Recovery code is generally schema-dependent. Version 7 and
454 // version 6 are very similar, so can be handled together.
455 // Track version 5, to see whether it's worth writing recovery
456 // code for.
457 if (version != 7 && version != 6) {
458 if (version == 5) {
459 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION5);
460 } else {
461 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION);
462 }
463 recovery_version.Clear();
464 sql::Recovery::Rollback(recovery.Pass());
465 return;
466 }
467 }
468
469 // Either version 6 or version 7 recovers to current.
487 sql::MetaTable recover_meta_table; 470 sql::MetaTable recover_meta_table;
488 if (!recover_meta_table.Init(recovery->db(), version, version)) { 471 if (!recover_meta_table.Init(recovery->db(), kCurrentVersionNumber,
472 kCompatibleVersionNumber)) {
489 sql::Recovery::Rollback(recovery.Pass()); 473 sql::Recovery::Rollback(recovery.Pass());
490 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_INIT); 474 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_INIT);
491 return; 475 return;
492 } 476 }
493
494 // TODO(shess): These tests are separate for histogram purposes,
495 // but once things look stable it can be tightened up.
496 if (!InitSchemaV5(recovery->db())) {
497 sql::Recovery::Rollback(recovery.Pass());
498 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_V5_INITSCHEMA);
499 return;
500 }
501
502 if (!recovery->AutoRecoverTable("favicons", 0, &favicons_rows_recovered)) {
503 sql::Recovery::Rollback(recovery.Pass());
504 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_V5_AUTORECOVER_FAVICONS);
505 return;
506 }
507
508 if (!recovery->AutoRecoverTable("icon_mapping", 0,
509 &icon_mapping_rows_recovered)) {
510 sql::Recovery::Rollback(recovery.Pass());
511 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_V5_AUTORECOVER_ICON_MAPPING);
512 return;
513 }
514
515 ignore_result(sql::Recovery::Recovered(recovery.Pass()));
516
517 // TODO(shess): Could this code be shared with the v6/7 code
518 // without requiring too much state to be carried?
519
520 // Track the size of the recovered database relative to the size of
521 // the input database. The size should almost always be smaller,
522 // unless the input database was empty to start with. If the
523 // percentage results are very low, something is awry.
524 int64 final_size = 0;
525 if (original_size > 0 &&
526 file_util::GetFileSize(db_path, &final_size) &&
527 final_size > 0) {
528 int percentage = static_cast<int>(original_size * 100 / final_size);
529 UMA_HISTOGRAM_PERCENTAGE("History.FaviconsRecoveredPercentage",
530 std::max(100, percentage));
531 }
532
533 // Using 10,000 because these cases mostly care about "none
534 // recovered" and "lots recovered". More than 10,000 rows recovered
535 // probably means there's something wrong with the profile.
536 UMA_HISTOGRAM_COUNTS_10000("History.FaviconsRecoveredRowsFavicons",
537 favicons_rows_recovered);
538 UMA_HISTOGRAM_COUNTS_10000("History.FaviconsRecoveredRowsIconMapping",
539 icon_mapping_rows_recovered);
540
541 RecordRecoveryEvent(RECOVERY_EVENT_RECOVERED_VERSION5);
542 return;
543 }
544
545 // This code may be able to fetch versions that the regular
546 // deprecation path cannot.
547 if (version <= kDeprecatedVersionNumber) {
548 sql::Recovery::Unrecoverable(recovery.Pass());
549 RecordRecoveryEvent(RECOVERY_EVENT_DEPRECATED);
550 return;
551 }
552
553 // TODO(shess): Earlier versions have been handled or deprecated,
554 // later versions should be impossible. Unrecoverable() seems
555 // reasonable.
556 if (version != 6 && version != 7) {
557 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_WRONG_VERSION);
558 sql::Recovery::Rollback(recovery.Pass());
559 return;
560 }
561
562 // Both v6 and v7 recover to current schema version.
563 sql::MetaTable recover_meta_table;
564 if (!recover_meta_table.Init(recovery->db(), kCurrentVersionNumber,
565 kCompatibleVersionNumber)) {
566 sql::Recovery::Rollback(recovery.Pass());
567 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_META_INIT);
568 return;
569 } 477 }
570 478
571 // Create a fresh version of the database. The recovery code uses 479 // Create a fresh version of the database. The recovery code uses
572 // conflict-resolution to handle duplicates, so the indices are 480 // conflict-resolution to handle duplicates, so the indices are
573 // necessary. 481 // necessary.
574 if (!InitTables(recovery->db()) || !InitIndices(recovery->db())) { 482 if (!InitTables(recovery->db()) || !InitIndices(recovery->db())) {
575 // TODO(shess): Unable to create the new schema in the new 483 // TODO(shess): Unable to create the new schema in the new
576 // database. The new database should be a temporary file, so 484 // database. The new database should be a temporary file, so
577 // being unable to work with it is pretty unclear. 485 // being unable to work with it is pretty unclear.
578 // 486 //
579 // What are the potential responses, even? The recovery database 487 // What are the potential responses, even? The recovery database
580 // could be opened as in-memory. If the temp database had a 488 // could be opened as in-memory. If the temp database had a
581 // filesystem problem and the temp filesystem differs from the 489 // filesystem problem and the temp filesystem differs from the
582 // main database, then that could fix it. 490 // main database, then that could fix it.
583 sql::Recovery::Rollback(recovery.Pass()); 491 sql::Recovery::Rollback(recovery.Pass());
584 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_INIT); 492 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_INIT);
585 return; 493 return;
586 } 494 }
587 495
588 // [favicons] differs because v6 had an unused [sizes] column which 496 // Setup favicons table.
589 // was removed in v7. 497 {
590 if (!recovery->AutoRecoverTable("favicons", 1, &favicons_rows_recovered)) { 498 // Version 6 had the |sizes| column, version 7 removed it. The
591 sql::Recovery::Rollback(recovery.Pass()); 499 // recover virtual table treats more columns than expected as an
592 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICONS); 500 // error, but if _fewer_ columns are present, they can be treated
593 return; 501 // as NULL. SQLite requires this because ALTER TABLE adds columns
502 // to the schema, but not to the actual table storage.
503 const char kRecoverySql[] =
504 "CREATE VIRTUAL TABLE temp.recover_favicons USING recover"
505 "("
506 "corrupt.favicons,"
507 "id ROWID,"
508 "url TEXT NOT NULL,"
509 "icon_type INTEGER,"
510 "sizes TEXT"
511 ")";
512 if (!recovery->db()->Execute(kRecoverySql)) {
513 // TODO(shess): Failure to create the recovery table probably
514 // means unrecoverable.
515 sql::Recovery::Rollback(recovery.Pass());
516 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_FAVICONS);
517 return;
518 }
519
520 // TODO(shess): Check if the DEFAULT 1 will just cover the
521 // COALESCE(). Either way, the new code has a literal 1 rather
522 // than a NULL, right?
523 const char kCopySql[] =
524 "INSERT OR REPLACE INTO main.favicons "
525 "SELECT id, url, COALESCE(icon_type, 1) FROM recover_favicons";
526 if (!recovery->db()->Execute(kCopySql)) {
527 // TODO(shess): The recover_favicons table should mask problems
528 // with the source file, so this implies failure to write to the
529 // recovery database.
530 sql::Recovery::Rollback(recovery.Pass());
531 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_FAVICONS_INSERT);
532 return;
533 }
534 favicons_rows_recovered = recovery->db()->GetLastChangeCount();
594 } 535 }
595 if (!recovery->AutoRecoverTable("favicon_bitmaps", 0, 536
596 &favicon_bitmaps_rows_recovered)) { 537 // Setup favicons_bitmaps table.
597 sql::Recovery::Rollback(recovery.Pass()); 538 {
598 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_FAVICON_BITMAPS); 539 const char kRecoverySql[] =
599 return; 540 "CREATE VIRTUAL TABLE temp.recover_favicons_bitmaps USING recover"
541 "("
542 "corrupt.favicon_bitmaps,"
543 "id ROWID,"
544 "icon_id INTEGER STRICT NOT NULL,"
545 "last_updated INTEGER,"
546 "image_data BLOB,"
547 "width INTEGER,"
548 "height INTEGER"
549 ")";
550 if (!recovery->db()->Execute(kRecoverySql)) {
551 // TODO(shess): Failure to create the recovery table probably
552 // means unrecoverable.
553 sql::Recovery::Rollback(recovery.Pass());
554 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_FAVICON_BITMAPS);
555 return;
556 }
557
558 const char kCopySql[] =
559 "INSERT OR REPLACE INTO main.favicon_bitmaps "
560 "SELECT id, icon_id, COALESCE(last_updated, 0), image_data, "
561 " COALESCE(width, 0), COALESCE(height, 0) "
562 "FROM recover_favicons_bitmaps";
563 if (!recovery->db()->Execute(kCopySql)) {
564 // TODO(shess): The recover_faviconbitmaps table should mask
565 // problems with the source file, so this implies failure to
566 // write to the recovery database.
567 sql::Recovery::Rollback(recovery.Pass());
568 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_FAVICON_BITMAPS_INSERT);
569 return;
570 }
571 favicon_bitmaps_rows_recovered = recovery->db()->GetLastChangeCount();
600 } 572 }
601 if (!recovery->AutoRecoverTable("icon_mapping", 0, 573
602 &icon_mapping_rows_recovered)) { 574 // Setup icon_mapping table.
603 sql::Recovery::Rollback(recovery.Pass()); 575 {
604 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_AUTORECOVER_ICON_MAPPING); 576 const char kRecoverySql[] =
605 return; 577 "CREATE VIRTUAL TABLE temp.recover_icon_mapping USING recover"
578 "("
579 "corrupt.icon_mapping,"
580 "id ROWID,"
581 "page_url TEXT STRICT NOT NULL,"
582 "icon_id INTEGER STRICT"
583 ")";
584 if (!recovery->db()->Execute(kRecoverySql)) {
585 // TODO(shess): Failure to create the recovery table probably
586 // means unrecoverable.
587 sql::Recovery::Rollback(recovery.Pass());
588 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_RECOVER_ICON_MAPPING);
589 return;
590 }
591
592 const char kCopySql[] =
593 "INSERT OR REPLACE INTO main.icon_mapping "
594 "SELECT id, page_url, icon_id FROM recover_icon_mapping";
595 if (!recovery->db()->Execute(kCopySql)) {
596 // TODO(shess): The recover_icon_mapping table should mask
597 // problems with the source file, so this implies failure to
598 // write to the recovery database.
599 sql::Recovery::Rollback(recovery.Pass());
600 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_ICON_MAPPING_INSERT);
601 return;
602 }
603 icon_mapping_rows_recovered = recovery->db()->GetLastChangeCount();
606 } 604 }
607 605
608 // TODO(shess): Is it possible/likely to have broken foreign-key 606 // TODO(shess): Is it possible/likely to have broken foreign-key
609 // issues with the tables? 607 // issues with the tables?
610 // - icon_mapping.icon_id maps to no favicons.id 608 // - icon_mapping.icon_id maps to no favicons.id
611 // - favicon_bitmaps.icon_id maps to no favicons.id 609 // - favicon_bitmaps.icon_id maps to no favicons.id
612 // - favicons.id is referenced by no icon_mapping.icon_id 610 // - favicons.id is referenced by no icon_mapping.icon_id
613 // - favicons.id is referenced by no favicon_bitmaps.icon_id 611 // - favicons.id is referenced by no favicon_bitmaps.icon_id
614 // This step is possibly not worth the effort necessary to develop 612 // This step is possibly not worth the effort necessary to develop
615 // and sequence the statements, as it is basically a form of garbage 613 // and sequence the statements, as it is basically a form of garbage
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 meta_table_.SetVersionNumber(7); 1421 meta_table_.SetVersionNumber(7);
1424 meta_table_.SetCompatibleVersionNumber(std::min(7, kCompatibleVersionNumber)); 1422 meta_table_.SetCompatibleVersionNumber(std::min(7, kCompatibleVersionNumber));
1425 return true; 1423 return true;
1426 } 1424 }
1427 1425
1428 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { 1426 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() {
1429 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); 1427 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons");
1430 } 1428 }
1431 1429
1432 } // namespace history 1430 } // namespace history
OLDNEW
« no previous file with comments | « no previous file | trunk/src/chrome/browser/history/thumbnail_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698