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/top_sites_database.h" | 5 #include "components/history/core/browser/top_sites_database.h" |
6 | 6 |
7 #include "base/files/file_util.h" | 7 #include "base/files/file_util.h" |
8 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "chrome/browser/history/top_sites.h" | |
13 #include "components/history/core/browser/history_types.h" | 12 #include "components/history/core/browser/history_types.h" |
| 13 #include "components/history/core/browser/top_sites.h" |
14 #include "components/history/core/common/thumbnail_score.h" | 14 #include "components/history/core/common/thumbnail_score.h" |
15 #include "sql/connection.h" | 15 #include "sql/connection.h" |
16 #include "sql/recovery.h" | 16 #include "sql/recovery.h" |
17 #include "sql/statement.h" | 17 #include "sql/statement.h" |
18 #include "sql/transaction.h" | 18 #include "sql/transaction.h" |
19 #include "third_party/sqlite/sqlite3.h" | 19 #include "third_party/sqlite/sqlite3.h" |
20 | 20 |
21 // Description of database table: | 21 // Description of database table: |
22 // | 22 // |
23 // thumbnails | 23 // thumbnails |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 // Track invariants resolved by FixThumbnailsTable(). | 129 // Track invariants resolved by FixThumbnailsTable(). |
130 RECOVERY_EVENT_INVARIANT_RANK, | 130 RECOVERY_EVENT_INVARIANT_RANK, |
131 RECOVERY_EVENT_INVARIANT_REDIRECT, | 131 RECOVERY_EVENT_INVARIANT_REDIRECT, |
132 RECOVERY_EVENT_INVARIANT_CONTIGUOUS, | 132 RECOVERY_EVENT_INVARIANT_CONTIGUOUS, |
133 | 133 |
134 // Always keep this at the end. | 134 // Always keep this at the end. |
135 RECOVERY_EVENT_MAX, | 135 RECOVERY_EVENT_MAX, |
136 }; | 136 }; |
137 | 137 |
138 void RecordRecoveryEvent(RecoveryEventType recovery_event) { | 138 void RecordRecoveryEvent(RecoveryEventType recovery_event) { |
139 UMA_HISTOGRAM_ENUMERATION("History.TopSitesRecovery", | 139 UMA_HISTOGRAM_ENUMERATION("History.TopSitesRecovery", recovery_event, |
140 recovery_event, RECOVERY_EVENT_MAX); | 140 RECOVERY_EVENT_MAX); |
141 } | 141 } |
142 | 142 |
143 // Most corruption comes down to atomic updates between pages being broken | 143 // Most corruption comes down to atomic updates between pages being broken |
144 // somehow. This can result in either missing data, or overlapping data, | 144 // somehow. This can result in either missing data, or overlapping data, |
145 // depending on the operation broken. This table has large rows, which will use | 145 // depending on the operation broken. This table has large rows, which will use |
146 // overflow pages, so it is possible (though unlikely) that a chain could fit | 146 // overflow pages, so it is possible (though unlikely) that a chain could fit |
147 // together and yield a row with errors. | 147 // together and yield a row with errors. |
148 void FixThumbnailsTable(sql::Connection* db) { | 148 void FixThumbnailsTable(sql::Connection* db) { |
149 // Enforce invariant separating forced and non-forced thumbnails. | 149 // Enforce invariant separating forced and non-forced thumbnails. |
150 const char kFixRankSql[] = | 150 const char kFixRankSql[] = |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 // insight. | 288 // insight. |
289 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_COMMIT); | 289 RecordRecoveryEvent(RECOVERY_EVENT_FAILED_COMMIT); |
290 return; | 290 return; |
291 } | 291 } |
292 | 292 |
293 // Track the size of the recovered database relative to the size of the input | 293 // Track the size of the recovered database relative to the size of the input |
294 // database. The size should almost always be smaller, unless the input | 294 // database. The size should almost always be smaller, unless the input |
295 // database was empty to start with. If the percentage results are very low, | 295 // database was empty to start with. If the percentage results are very low, |
296 // something is awry. | 296 // something is awry. |
297 int64 final_size = 0; | 297 int64 final_size = 0; |
298 if (original_size > 0 && | 298 if (original_size > 0 && base::GetFileSize(db_path, &final_size) && |
299 base::GetFileSize(db_path, &final_size) && | |
300 final_size > 0) { | 299 final_size > 0) { |
301 UMA_HISTOGRAM_PERCENTAGE("History.TopSitesRecoveredPercentage", | 300 UMA_HISTOGRAM_PERCENTAGE("History.TopSitesRecoveredPercentage", |
302 final_size * 100 / original_size); | 301 final_size * 100 / original_size); |
303 } | 302 } |
304 | 303 |
305 // Using 10,000 because these cases mostly care about "none recovered" and | 304 // Using 10,000 because these cases mostly care about "none recovered" and |
306 // "lots recovered". More than 10,000 rows recovered probably means there's | 305 // "lots recovered". More than 10,000 rows recovered probably means there's |
307 // something wrong with the profile. | 306 // something wrong with the profile. |
308 UMA_HISTOGRAM_COUNTS_10000("History.TopSitesRecoveredRowsThumbnails", | 307 UMA_HISTOGRAM_COUNTS_10000("History.TopSitesRecoveredRowsThumbnails", |
309 thumbnails_recovered); | 308 thumbnails_recovered); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 if (rank == kRankOfNonExistingURL) { | 491 if (rank == kRankOfNonExistingURL) { |
493 AddPageThumbnail(url, new_rank, thumbnail); | 492 AddPageThumbnail(url, new_rank, thumbnail); |
494 } else { | 493 } else { |
495 UpdatePageRankNoTransaction(url, new_rank); | 494 UpdatePageRankNoTransaction(url, new_rank); |
496 UpdatePageThumbnail(url, thumbnail); | 495 UpdatePageThumbnail(url, thumbnail); |
497 } | 496 } |
498 | 497 |
499 transaction.Commit(); | 498 transaction.Commit(); |
500 } | 499 } |
501 | 500 |
502 bool TopSitesDatabase::UpdatePageThumbnail( | 501 bool TopSitesDatabase::UpdatePageThumbnail(const MostVisitedURL& url, |
503 const MostVisitedURL& url, const Images& thumbnail) { | 502 const Images& thumbnail) { |
504 sql::Statement statement(db_->GetCachedStatement( | 503 sql::Statement statement(db_->GetCachedStatement( |
505 SQL_FROM_HERE, | 504 SQL_FROM_HERE, |
506 "UPDATE thumbnails SET " | 505 "UPDATE thumbnails SET " |
507 "title = ?, thumbnail = ?, redirects = ?, " | 506 "title = ?, thumbnail = ?, redirects = ?, " |
508 "boring_score = ?, good_clipping = ?, at_top = ?, last_updated = ?, " | 507 "boring_score = ?, good_clipping = ?, at_top = ?, last_updated = ?, " |
509 "load_completed = ?, last_forced = ?" | 508 "load_completed = ?, last_forced = ?" |
510 "WHERE url = ? ")); | 509 "WHERE url = ? ")); |
511 statement.BindString16(0, url.title); | 510 statement.BindString16(0, url.title); |
512 if (thumbnail.thumbnail.get() && thumbnail.thumbnail->front()) { | 511 if (thumbnail.thumbnail.get() && thumbnail.thumbnail->front()) { |
513 statement.BindBlob(1, thumbnail.thumbnail->front(), | 512 statement.BindBlob(1, thumbnail.thumbnail->front(), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 << "opposite."; | 554 << "opposite."; |
556 statement.BindInt64(10, last_forced); | 555 statement.BindInt64(10, last_forced); |
557 if (!statement.Run()) | 556 if (!statement.Run()) |
558 return; | 557 return; |
559 | 558 |
560 // Update rank if this is not a forced thumbnail. | 559 // Update rank if this is not a forced thumbnail. |
561 if (new_rank != kRankOfForcedURL) | 560 if (new_rank != kRankOfForcedURL) |
562 UpdatePageRankNoTransaction(url, new_rank); | 561 UpdatePageRankNoTransaction(url, new_rank); |
563 } | 562 } |
564 | 563 |
565 void TopSitesDatabase::UpdatePageRank(const MostVisitedURL& url, | 564 void TopSitesDatabase::UpdatePageRank(const MostVisitedURL& url, int new_rank) { |
566 int new_rank) { | |
567 DCHECK((url.last_forced_time.ToInternalValue() == 0) == | 565 DCHECK((url.last_forced_time.ToInternalValue() == 0) == |
568 (new_rank != kRankOfForcedURL)) | 566 (new_rank != kRankOfForcedURL)) |
569 << "Thumbnail without a forced time stamp has a forced rank, or the " | 567 << "Thumbnail without a forced time stamp has a forced rank, or the " |
570 << "opposite."; | 568 << "opposite."; |
571 sql::Transaction transaction(db_.get()); | 569 sql::Transaction transaction(db_.get()); |
572 transaction.Begin(); | 570 transaction.Begin(); |
573 UpdatePageRankNoTransaction(url, new_rank); | 571 UpdatePageRankNoTransaction(url, new_rank); |
574 transaction.Commit(); | 572 transaction.Commit(); |
575 } | 573 } |
576 | 574 |
577 // Caller should have a transaction open. | 575 // Caller should have a transaction open. |
578 void TopSitesDatabase::UpdatePageRankNoTransaction( | 576 void TopSitesDatabase::UpdatePageRankNoTransaction(const MostVisitedURL& url, |
579 const MostVisitedURL& url, int new_rank) { | 577 int new_rank) { |
580 DCHECK_GT(db_->transaction_nesting(), 0); | 578 DCHECK_GT(db_->transaction_nesting(), 0); |
581 DCHECK((url.last_forced_time.is_null()) == (new_rank != kRankOfForcedURL)) | 579 DCHECK((url.last_forced_time.is_null()) == (new_rank != kRankOfForcedURL)) |
582 << "Thumbnail without a forced time stamp has a forced rank, or the " | 580 << "Thumbnail without a forced time stamp has a forced rank, or the " |
583 << "opposite."; | 581 << "opposite."; |
584 | 582 |
585 int prev_rank = GetURLRank(url); | 583 int prev_rank = GetURLRank(url); |
586 if (prev_rank == kRankOfNonExistingURL) { | 584 if (prev_rank == kRankOfNonExistingURL) { |
587 LOG(WARNING) << "Updating rank of an unknown URL: " << url.url.spec(); | 585 LOG(WARNING) << "Updating rank of an unknown URL: " << url.url.spec(); |
588 return; | 586 return; |
589 } | 587 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 SQL_FROM_HERE, | 645 SQL_FROM_HERE, |
648 "UPDATE thumbnails " | 646 "UPDATE thumbnails " |
649 "SET url_rank = ?, last_forced = ? " | 647 "SET url_rank = ?, last_forced = ? " |
650 "WHERE url == ?")); | 648 "WHERE url == ?")); |
651 set_statement.BindInt(0, new_rank); | 649 set_statement.BindInt(0, new_rank); |
652 set_statement.BindInt64(1, url.last_forced_time.ToInternalValue()); | 650 set_statement.BindInt64(1, url.last_forced_time.ToInternalValue()); |
653 set_statement.BindString(2, url.url.spec()); | 651 set_statement.BindString(2, url.url.spec()); |
654 set_statement.Run(); | 652 set_statement.Run(); |
655 } | 653 } |
656 | 654 |
657 bool TopSitesDatabase::GetPageThumbnail(const GURL& url, | 655 bool TopSitesDatabase::GetPageThumbnail(const GURL& url, Images* thumbnail) { |
658 Images* thumbnail) { | |
659 sql::Statement statement(db_->GetCachedStatement( | 656 sql::Statement statement(db_->GetCachedStatement( |
660 SQL_FROM_HERE, | 657 SQL_FROM_HERE, |
661 "SELECT thumbnail, boring_score, good_clipping, at_top, last_updated " | 658 "SELECT thumbnail, boring_score, good_clipping, at_top, last_updated " |
662 "FROM thumbnails WHERE url=?")); | 659 "FROM thumbnails WHERE url=?")); |
663 statement.BindString(0, url.spec()); | 660 statement.BindString(0, url.spec()); |
664 if (!statement.Step()) | 661 if (!statement.Step()) |
665 return false; | 662 return false; |
666 | 663 |
667 std::vector<unsigned char> data; | 664 std::vector<unsigned char> data; |
668 statement.ColumnBlobAsVector(0, &data); | 665 statement.ColumnBlobAsVector(0, &data); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 if (!delete_statement.Run()) | 713 if (!delete_statement.Run()) |
717 return false; | 714 return false; |
718 | 715 |
719 return transaction.Commit(); | 716 return transaction.Commit(); |
720 } | 717 } |
721 | 718 |
722 sql::Connection* TopSitesDatabase::CreateDB(const base::FilePath& db_name) { | 719 sql::Connection* TopSitesDatabase::CreateDB(const base::FilePath& db_name) { |
723 scoped_ptr<sql::Connection> db(new sql::Connection()); | 720 scoped_ptr<sql::Connection> db(new sql::Connection()); |
724 // Settings copied from ThumbnailDatabase. | 721 // Settings copied from ThumbnailDatabase. |
725 db->set_histogram_tag("TopSites"); | 722 db->set_histogram_tag("TopSites"); |
726 db->set_error_callback(base::Bind(&DatabaseErrorCallback, | 723 db->set_error_callback(base::Bind(&DatabaseErrorCallback, db.get(), db_name)); |
727 db.get(), db_name)); | |
728 db->set_page_size(4096); | 724 db->set_page_size(4096); |
729 db->set_cache_size(32); | 725 db->set_cache_size(32); |
730 | 726 |
731 if (!db->Open(db_name)) | 727 if (!db->Open(db_name)) |
732 return NULL; | 728 return NULL; |
733 return db.release(); | 729 return db.release(); |
734 } | 730 } |
735 | 731 |
736 } // namespace history | 732 } // namespace history |
OLD | NEW |