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 "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 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 // detected. So this database is a good test subject. | 376 // detected. So this database is a good test subject. |
377 void RecoverDatabaseOrRaze(sql::Connection* db, const base::FilePath& db_path) { | 377 void RecoverDatabaseOrRaze(sql::Connection* db, const base::FilePath& db_path) { |
378 // NOTE(shess): This code is currently specific to the version | 378 // NOTE(shess): This code is currently specific to the version |
379 // number. I am working on simplifying things to loosen the | 379 // number. I am working on simplifying things to loosen the |
380 // dependency, meanwhile contact me if you need to bump the version. | 380 // dependency, meanwhile contact me if you need to bump the version. |
381 DCHECK_EQ(7, kCurrentVersionNumber); | 381 DCHECK_EQ(7, kCurrentVersionNumber); |
382 | 382 |
383 // TODO(shess): Reset back after? | 383 // TODO(shess): Reset back after? |
384 db->reset_error_callback(); | 384 db->reset_error_callback(); |
385 | 385 |
| 386 // For histogram purposes. |
| 387 size_t favicons_rows_recovered = 0; |
| 388 size_t favicon_bitmaps_rows_recovered = 0; |
| 389 size_t icon_mapping_rows_recovered = 0; |
| 390 int64 original_size = 0; |
| 391 file_util::GetFileSize(db_path, &original_size); |
| 392 |
386 scoped_ptr<sql::Recovery> recovery = sql::Recovery::Begin(db, db_path); | 393 scoped_ptr<sql::Recovery> recovery = sql::Recovery::Begin(db, db_path); |
387 if (!recovery) { | 394 if (!recovery) { |
388 // TODO(shess): Unable to create recovery connection. This | 395 // TODO(shess): Unable to create recovery connection. This |
389 // implies something substantial is wrong. At this point |db| has | 396 // implies something substantial is wrong. At this point |db| has |
390 // been poisoned so there is nothing really to do. | 397 // been poisoned so there is nothing really to do. |
391 // | 398 // |
392 // Possible responses are unclear. If the failure relates to a | 399 // Possible responses are unclear. If the failure relates to a |
393 // problem somehow specific to the temporary file used to back the | 400 // problem somehow specific to the temporary file used to back the |
394 // database, then an in-memory database could possibly be used. | 401 // database, then an in-memory database could possibly be used. |
395 // This could potentially allow recovering the main database, and | 402 // This could potentially allow recovering the main database, and |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 // issues with the tables? | 604 // issues with the tables? |
598 // - icon_mapping.icon_id maps to no favicons.id | 605 // - icon_mapping.icon_id maps to no favicons.id |
599 // - favicon_bitmaps.icon_id maps to no favicons.id | 606 // - favicon_bitmaps.icon_id maps to no favicons.id |
600 // - favicons.id is referenced by no icon_mapping.icon_id | 607 // - favicons.id is referenced by no icon_mapping.icon_id |
601 // - favicons.id is referenced by no favicon_bitmaps.icon_id | 608 // - favicons.id is referenced by no favicon_bitmaps.icon_id |
602 // This step is possibly not worth the effort necessary to develop | 609 // This step is possibly not worth the effort necessary to develop |
603 // and sequence the statements, as it is basically a form of garbage | 610 // and sequence the statements, as it is basically a form of garbage |
604 // collection. | 611 // collection. |
605 | 612 |
606 ignore_result(sql::Recovery::Recovered(recovery.Pass())); | 613 ignore_result(sql::Recovery::Recovered(recovery.Pass())); |
| 614 |
| 615 // Track the size of the recovered database relative to the size of |
| 616 // the input database. The size should almost always be smaller, |
| 617 // unless the input database was empty to start with. If the |
| 618 // percentage results are very low, something is awry. |
| 619 int64 final_size = 0; |
| 620 if (original_size > 0 && |
| 621 file_util::GetFileSize(db_path, &final_size) && |
| 622 final_size > 0) { |
| 623 int percentage = static_cast<int>(original_size * 100 / final_size); |
| 624 UMA_HISTOGRAM_PERCENTAGE("History.FaviconsRecoveredPercentage", |
| 625 std::max(100, percentage)); |
| 626 } |
| 627 |
| 628 // Using 10,000 because these cases mostly care about "none |
| 629 // recovered" and "lots recovered". More than 10,000 rows recovered |
| 630 // probably means there's something wrong with the profile. |
| 631 UMA_HISTOGRAM_COUNTS_10000("History.FaviconsRecoveredRowsFavicons", |
| 632 favicons_rows_recovered); |
| 633 UMA_HISTOGRAM_COUNTS_10000("History.FaviconsRecoveredRowsFaviconBitmaps", |
| 634 favicon_bitmaps_rows_recovered); |
| 635 UMA_HISTOGRAM_COUNTS_10000("History.FaviconsRecoveredRowsIconMapping", |
| 636 icon_mapping_rows_recovered); |
| 637 |
607 if (version == 6) { | 638 if (version == 6) { |
608 RecordRecoveryEvent(RECOVERY_EVENT_RECOVERED_VERSION6); | 639 RecordRecoveryEvent(RECOVERY_EVENT_RECOVERED_VERSION6); |
609 } else { | 640 } else { |
610 RecordRecoveryEvent(RECOVERY_EVENT_RECOVERED); | 641 RecordRecoveryEvent(RECOVERY_EVENT_RECOVERED); |
611 } | 642 } |
612 } | 643 } |
613 | 644 |
614 void DatabaseErrorCallback(sql::Connection* db, | 645 void DatabaseErrorCallback(sql::Connection* db, |
615 const base::FilePath& db_path, | 646 const base::FilePath& db_path, |
616 size_t startup_kb, | 647 size_t startup_kb, |
617 int extended_error, | 648 int extended_error, |
618 sql::Statement* stmt) { | 649 sql::Statement* stmt) { |
619 // TODO(shess): Assert that this is running on a safe thread. | 650 // TODO(shess): Assert that this is running on a safe thread. |
620 // AFAICT, should be the history thread, but at this level I can't | 651 // AFAICT, should be the history thread, but at this level I can't |
621 // see how to reach that. | 652 // see how to reach that. |
622 | 653 |
623 // TODO(shess): For now, don't report on beta or stable so as not to | 654 // TODO(shess): For now, don't report on beta or stable so as not to |
624 // overwhelm the crash server. Once the big fish are fried, | 655 // overwhelm the crash server. Once the big fish are fried, |
625 // consider reporting at a reduced rate on the bigger channels. | 656 // consider reporting at a reduced rate on the bigger channels. |
626 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); | 657 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
627 if (channel != chrome::VersionInfo::CHANNEL_STABLE && | 658 if (channel != chrome::VersionInfo::CHANNEL_STABLE && |
628 channel != chrome::VersionInfo::CHANNEL_BETA) { | 659 channel != chrome::VersionInfo::CHANNEL_BETA) { |
629 GenerateDiagnostics(db, startup_kb, extended_error); | 660 GenerateDiagnostics(db, startup_kb, extended_error); |
630 } | 661 } |
631 | 662 |
632 // Attempt to recover corrupt databases. | 663 // Attempt to recover corrupt databases. |
633 // TODO(shess): Remove the channel restriction once it becomes clear | 664 int error = (extended_error & 0xFF); |
634 // that the recovery code fails gracefully. | 665 if (error == SQLITE_CORRUPT || |
635 if (channel != chrome::VersionInfo::CHANNEL_STABLE && | 666 error == SQLITE_CANTOPEN || |
636 channel != chrome::VersionInfo::CHANNEL_BETA) { | 667 error == SQLITE_NOTADB) { |
637 int error = (extended_error & 0xFF); | 668 RecoverDatabaseOrRaze(db, db_path); |
638 if (error == SQLITE_CORRUPT || | |
639 error == SQLITE_CANTOPEN || | |
640 error == SQLITE_NOTADB) { | |
641 RecoverDatabaseOrRaze(db, db_path); | |
642 } | |
643 } | 669 } |
644 | 670 |
645 // The default handling is to assert on debug and to ignore on release. | 671 // The default handling is to assert on debug and to ignore on release. |
646 if (!sql::Connection::ShouldIgnoreSqliteError(extended_error)) | 672 if (!sql::Connection::ShouldIgnoreSqliteError(extended_error)) |
647 DLOG(FATAL) << db->GetErrorMessage(); | 673 DLOG(FATAL) << db->GetErrorMessage(); |
648 } | 674 } |
649 | 675 |
650 } // namespace | 676 } // namespace |
651 | 677 |
652 namespace history { | 678 namespace history { |
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 meta_table_.SetVersionNumber(7); | 1418 meta_table_.SetVersionNumber(7); |
1393 meta_table_.SetCompatibleVersionNumber(std::min(7, kCompatibleVersionNumber)); | 1419 meta_table_.SetCompatibleVersionNumber(std::min(7, kCompatibleVersionNumber)); |
1394 return true; | 1420 return true; |
1395 } | 1421 } |
1396 | 1422 |
1397 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { | 1423 bool ThumbnailDatabase::IsFaviconDBStructureIncorrect() { |
1398 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); | 1424 return !db_.IsSQLValid("SELECT id, url, icon_type FROM favicons"); |
1399 } | 1425 } |
1400 | 1426 |
1401 } // namespace history | 1427 } // namespace history |
OLD | NEW |