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

Unified Diff: components/history/core/browser/history_database.cc

Issue 2954593002: History init: add metrics and skip migration. (Closed)
Patch Set: Fixes Created 3 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: components/history/core/browser/history_database.cc
diff --git a/components/history/core/browser/history_database.cc b/components/history/core/browser/history_database.cc
index a61e2901850d931402cae480de62880fb4c91e3f..becb18852192ae2c64f5ad063d55f8f4bca82da3 100644
--- a/components/history/core/browser/history_database.cc
+++ b/components/history/core/browser/history_database.cc
@@ -42,6 +42,37 @@ const int kCompatibleVersionNumber = 16;
const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
const int kMaxHostsInMemory = 10000;
+// Logs a migration failure to UMA and logging. The return value will be
+// what to return from ::Init (to simplify the call sites). Migration failures
+// are almost always fatal since the database can be in an inconsistent state.
+sql::InitStatus LogMigrationFailure(int from_version) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("History.MigrateFailureFromVersion",
+ from_version);
+ LOG(ERROR) << "History failed to migrate from version " << from_version
+ << ". History will be disabled.";
+ return sql::INIT_FAILURE;
+}
+
+// Reasons for initialization to fail. These are logged to UMA. It corresponds
+// to the HistoryInitStep enum in enums.xml.
+//
+// DO NOT CHANGE THE VALUES. Leave holes if anything is removed and add only
+// to the end.
+enum class InitStep {
+ OPEN = 0,
+ TRANSACTION_BEGIN,
+ META_TABLE_INIT,
+ CREATE_TABLES,
+ VERSION,
+ COMMIT,
+};
+
+sql::InitStatus LogInitFailure(InitStep what) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("History.InitializationFailureStep",
+ static_cast<int>(what));
+ return sql::INIT_FAILURE;
+}
+
} // namespace
HistoryDatabase::HistoryDatabase(
@@ -74,13 +105,13 @@ sql::InitStatus HistoryDatabase::Init(const base::FilePath& history_name) {
// mode to start out for the in-memory backend to read the data).
if (!db_.Open(history_name))
- return sql::INIT_FAILURE;
+ return LogInitFailure(InitStep::OPEN);
// Wrap the rest of init in a tranaction. This will prevent the database from
// getting corrupted if we crash in the middle of initialization or migration.
sql::Transaction committer(&db_);
if (!committer.Begin())
- return sql::INIT_FAILURE;
+ return LogInitFailure(InitStep::TRANSACTION_BEGIN);
#if defined(OS_MACOSX) && !defined(OS_IOS)
// Exclude the history file from backups.
@@ -94,11 +125,11 @@ sql::InitStatus HistoryDatabase::Init(const base::FilePath& history_name) {
// NOTE: If you add something here, also add it to
// RecreateAllButStarAndURLTables.
if (!meta_table_.Init(&db_, GetCurrentVersion(), kCompatibleVersionNumber))
- return sql::INIT_FAILURE;
+ return LogInitFailure(InitStep::META_TABLE_INIT);
if (!CreateURLTable(false) || !InitVisitTable() ||
!InitKeywordSearchTermsTable() || !InitDownloadTable() ||
!InitSegmentTables() || !InitSyncTable())
- return sql::INIT_FAILURE;
+ return LogInitFailure(InitStep::CREATE_TABLES);
CreateMainURLIndex();
CreateKeywordSearchTermsIndices();
@@ -107,10 +138,14 @@ sql::InitStatus HistoryDatabase::Init(const base::FilePath& history_name) {
// Version check.
sql::InitStatus version_status = EnsureCurrentVersion();
- if (version_status != sql::INIT_OK)
+ if (version_status != sql::INIT_OK) {
+ LogInitFailure(InitStep::VERSION);
return version_status;
+ }
- return committer.Commit() ? sql::INIT_OK : sql::INIT_FAILURE;
+ if (!committer.Commit())
+ return LogInitFailure(InitStep::COMMIT);
+ return sql::INIT_OK;
}
void HistoryDatabase::ComputeDatabaseMetrics(
@@ -383,10 +418,8 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
// Put migration code here
if (cur_version == 15) {
- if (!db_.Execute("DROP TABLE starred") || !DropStarredIDFromURLs()) {
- LOG(WARNING) << "Unable to update history database to version 16.";
- return sql::INIT_FAILURE;
- }
+ if (!db_.Execute("DROP TABLE starred") || !DropStarredIDFromURLs())
+ return LogMigrationFailure(15);
++cur_version;
meta_table_.SetVersionNumber(cur_version);
meta_table_.SetCompatibleVersionNumber(
@@ -430,10 +463,8 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
if (cur_version == 20) {
// This is the version prior to adding the visit_duration field in visits
// database. We need to migrate the database.
- if (!MigrateVisitsWithoutDuration()) {
- LOG(WARNING) << "Unable to update history database to version 21.";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateVisitsWithoutDuration())
+ return LogMigrationFailure(20);
++cur_version;
meta_table_.SetVersionNumber(cur_version);
}
@@ -441,102 +472,79 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
if (cur_version == 21) {
// The android_urls table's data schemal was changed in version 21.
#if defined(OS_ANDROID)
- if (!MigrateToVersion22()) {
- LOG(WARNING) << "Unable to migrate the android_urls table to version 22";
- }
+ if (!MigrateToVersion22())
+ return LogMigrationFailure(21);
#endif
++cur_version;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 22) {
- if (!MigrateDownloadsState()) {
- LOG(WARNING) << "Unable to fix invalid downloads state values";
- // Invalid state values may cause crashes.
- return sql::INIT_FAILURE;
- }
+ if (!MigrateDownloadsState())
+ return LogMigrationFailure(22);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 23) {
- if (!MigrateDownloadsReasonPathsAndDangerType()) {
- LOG(WARNING) << "Unable to upgrade download interrupt reason and paths";
- // Invalid state values may cause crashes.
- return sql::INIT_FAILURE;
- }
+ if (!MigrateDownloadsReasonPathsAndDangerType())
+ return LogMigrationFailure(23);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 24) {
- if (!MigratePresentationIndex()) {
- LOG(WARNING) << "Unable to migrate history to version 25";
- return sql::INIT_FAILURE;
- }
+ if (!MigratePresentationIndex())
+ return LogMigrationFailure(24);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 25) {
- if (!MigrateReferrer()) {
- LOG(WARNING) << "Unable to migrate history to version 26";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateReferrer())
+ return LogMigrationFailure(25);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 26) {
- if (!MigrateDownloadedByExtension()) {
- LOG(WARNING) << "Unable to migrate history to version 27";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateDownloadedByExtension())
+ return LogMigrationFailure(26);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 27) {
- if (!MigrateDownloadValidators()) {
- LOG(WARNING) << "Unable to migrate history to version 28";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateDownloadValidators())
+ return LogMigrationFailure(27);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 28) {
- if (!MigrateMimeType()) {
- LOG(WARNING) << "Unable to migrate history to version 29";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateMimeType())
+ return LogMigrationFailure(28);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 29) {
- if (!MigrateHashHttpMethodAndGenerateGuids()) {
- LOG(WARNING) << "Unable to migrate history to version 30";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateHashHttpMethodAndGenerateGuids())
+ return LogMigrationFailure(29);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 30) {
- if (!MigrateDownloadTabUrl()) {
- LOG(WARNING) << "Unable to migrate history to version 31";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateDownloadTabUrl())
+ return LogMigrationFailure(30);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 31) {
- if (!MigrateDownloadSiteInstanceUrl()) {
- LOG(WARNING) << "Unable to migrate history to version 32";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateDownloadSiteInstanceUrl())
+ return LogMigrationFailure(31);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
@@ -548,37 +556,57 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
}
if (cur_version == 33) {
- if (!MigrateDownloadLastAccessTime()) {
- LOG(WARNING) << "Unable to migrate to version 34";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateDownloadLastAccessTime())
+ return LogMigrationFailure(33);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 34) {
+ /*
+ This code is commented out because we suspect the additional disk storage
+ requirements of duplicating the URL table to update the schema cause
+ some devices to run out of storage. Errors during initialization are
+ very disruptive to the user experience.
+
+ TODO(https://crbug.com/736136) figure out how to update users to use
+ AUTOINCREMENT.
+
// AUTOINCREMENT is added to urls table PRIMARY KEY(id), need to recreate a
// new table and copy all contents over. favicon_id is removed from urls
// table since we never use it. Also typed_url_sync_metadata and
// autofill_model_type_state tables are introduced, no migration needed for
// those two tables.
- if (!RecreateURLTableWithAllContents()) {
- LOG(WARNING) << "Unable to update history database to version 35.";
- return sql::INIT_FAILURE;
- }
+ if (!RecreateURLTableWithAllContents())
+ return LogMigrationFailure(34);
+ */
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
if (cur_version == 35) {
- if (!MigrateDownloadTransient()) {
- LOG(WARNING) << "Unable to migrate to version 36";
- return sql::INIT_FAILURE;
- }
+ if (!MigrateDownloadTransient())
+ return LogMigrationFailure(35);
cur_version++;
meta_table_.SetVersionNumber(cur_version);
}
+ // ========================= ^^ new migration code goes here ^^
+ // ADDING NEW MIGRATION CODE
+ // =========================
+ //
+ // Add new migration code above here. It's important to use as little space
+ // as possible during migration. Many phones are very near their storage
+ // limit, so anything that recreates or duplicates large history tables can
+ // easily push them over that limit.
+ //
+ // When failures happen during initialization, history is not loaded. This
+ // causes all components related to the history database file to fail
+ // completely, including autocomplete and downloads. Devices near their
+ // storage limit are likely to fail doing some update later, but those
+ // operations will then just be skipped which is not nearly as disruptive.
+ // See https://crbug.com/734194.
+
// When the version is too old, we just try to continue anyway, there should
// not be a released product that makes a database too old for us to handle.
LOG_IF(WARNING, cur_version < GetCurrentVersion()) <<

Powered by Google App Engine
This is Rietveld 408576698