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

Side by Side 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 unified diff | Download patch
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 "components/history/core/browser/history_database.h" 5 #include "components/history/core/browser/history_database.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <set> 10 #include <set>
(...skipping 24 matching lines...) Expand all
35 namespace { 35 namespace {
36 36
37 // Current version number. We write databases at the "current" version number, 37 // Current version number. We write databases at the "current" version number,
38 // but any previous version that can read the "compatible" one can make do with 38 // but any previous version that can read the "compatible" one can make do with
39 // our database without *too* many bad effects. 39 // our database without *too* many bad effects.
40 const int kCurrentVersionNumber = 36; 40 const int kCurrentVersionNumber = 36;
41 const int kCompatibleVersionNumber = 16; 41 const int kCompatibleVersionNumber = 16;
42 const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold"; 42 const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
43 const int kMaxHostsInMemory = 10000; 43 const int kMaxHostsInMemory = 10000;
44 44
45 // Logs a migration failure to UMA and logging. The return value will be
46 // what to return from ::Init (to simplify the call sites). Migration failures
47 // are almost always fatal since the database can be in an inconsistent state.
48 sql::InitStatus LogMigrationFailure(int from_version) {
49 UMA_HISTOGRAM_SPARSE_SLOWLY("History.MigrateFailureFromVersion",
50 from_version);
51 LOG(ERROR) << "History failed to migrate from version " << from_version
52 << ". History will be disabled.";
53 return sql::INIT_FAILURE;
54 }
55
56 // Reasons for initialization to fail. These are logged to UMA. It corresponds
57 // to the HistoryInitStep enum in enums.xml.
58 //
59 // DO NOT CHANGE THE VALUES. Leave holes if anything is removed and add only
60 // to the end.
61 enum class InitStep {
62 OPEN = 0,
63 TRANSACTION_BEGIN,
64 META_TABLE_INIT,
65 CREATE_TABLES,
66 VERSION,
67 COMMIT,
68 };
69
70 sql::InitStatus LogInitFailure(InitStep what) {
71 UMA_HISTOGRAM_SPARSE_SLOWLY("History.InitializationFailureStep",
72 static_cast<int>(what));
73 return sql::INIT_FAILURE;
74 }
75
45 } // namespace 76 } // namespace
46 77
47 HistoryDatabase::HistoryDatabase( 78 HistoryDatabase::HistoryDatabase(
48 DownloadInterruptReason download_interrupt_reason_none, 79 DownloadInterruptReason download_interrupt_reason_none,
49 DownloadInterruptReason download_interrupt_reason_crash) 80 DownloadInterruptReason download_interrupt_reason_crash)
50 : DownloadDatabase(download_interrupt_reason_none, 81 : DownloadDatabase(download_interrupt_reason_none,
51 download_interrupt_reason_crash) { 82 download_interrupt_reason_crash) {
52 } 83 }
53 84
54 HistoryDatabase::~HistoryDatabase() { 85 HistoryDatabase::~HistoryDatabase() {
(...skipping 12 matching lines...) Expand all
67 // value, tells us how much memory the cache will use maximum. 98 // value, tells us how much memory the cache will use maximum.
68 // 1000 * 4kB = 4MB 99 // 1000 * 4kB = 4MB
69 // TODO(brettw) scale this value to the amount of available memory. 100 // TODO(brettw) scale this value to the amount of available memory.
70 db_.set_cache_size(1000); 101 db_.set_cache_size(1000);
71 102
72 // Note that we don't set exclusive locking here. That's done by 103 // Note that we don't set exclusive locking here. That's done by
73 // BeginExclusiveMode below which is called later (we have to be in shared 104 // BeginExclusiveMode below which is called later (we have to be in shared
74 // mode to start out for the in-memory backend to read the data). 105 // mode to start out for the in-memory backend to read the data).
75 106
76 if (!db_.Open(history_name)) 107 if (!db_.Open(history_name))
77 return sql::INIT_FAILURE; 108 return LogInitFailure(InitStep::OPEN);
78 109
79 // Wrap the rest of init in a tranaction. This will prevent the database from 110 // Wrap the rest of init in a tranaction. This will prevent the database from
80 // getting corrupted if we crash in the middle of initialization or migration. 111 // getting corrupted if we crash in the middle of initialization or migration.
81 sql::Transaction committer(&db_); 112 sql::Transaction committer(&db_);
82 if (!committer.Begin()) 113 if (!committer.Begin())
83 return sql::INIT_FAILURE; 114 return LogInitFailure(InitStep::TRANSACTION_BEGIN);
84 115
85 #if defined(OS_MACOSX) && !defined(OS_IOS) 116 #if defined(OS_MACOSX) && !defined(OS_IOS)
86 // Exclude the history file from backups. 117 // Exclude the history file from backups.
87 base::mac::SetFileBackupExclusion(history_name); 118 base::mac::SetFileBackupExclusion(history_name);
88 #endif 119 #endif
89 120
90 // Prime the cache. 121 // Prime the cache.
91 db_.Preload(); 122 db_.Preload();
92 123
93 // Create the tables and indices. 124 // Create the tables and indices.
94 // NOTE: If you add something here, also add it to 125 // NOTE: If you add something here, also add it to
95 // RecreateAllButStarAndURLTables. 126 // RecreateAllButStarAndURLTables.
96 if (!meta_table_.Init(&db_, GetCurrentVersion(), kCompatibleVersionNumber)) 127 if (!meta_table_.Init(&db_, GetCurrentVersion(), kCompatibleVersionNumber))
97 return sql::INIT_FAILURE; 128 return LogInitFailure(InitStep::META_TABLE_INIT);
98 if (!CreateURLTable(false) || !InitVisitTable() || 129 if (!CreateURLTable(false) || !InitVisitTable() ||
99 !InitKeywordSearchTermsTable() || !InitDownloadTable() || 130 !InitKeywordSearchTermsTable() || !InitDownloadTable() ||
100 !InitSegmentTables() || !InitSyncTable()) 131 !InitSegmentTables() || !InitSyncTable())
101 return sql::INIT_FAILURE; 132 return LogInitFailure(InitStep::CREATE_TABLES);
102 CreateMainURLIndex(); 133 CreateMainURLIndex();
103 CreateKeywordSearchTermsIndices(); 134 CreateKeywordSearchTermsIndices();
104 135
105 // TODO(benjhayden) Remove at some point. 136 // TODO(benjhayden) Remove at some point.
106 meta_table_.DeleteKey("next_download_id"); 137 meta_table_.DeleteKey("next_download_id");
107 138
108 // Version check. 139 // Version check.
109 sql::InitStatus version_status = EnsureCurrentVersion(); 140 sql::InitStatus version_status = EnsureCurrentVersion();
110 if (version_status != sql::INIT_OK) 141 if (version_status != sql::INIT_OK) {
142 LogInitFailure(InitStep::VERSION);
111 return version_status; 143 return version_status;
144 }
112 145
113 return committer.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; 146 if (!committer.Commit())
147 return LogInitFailure(InitStep::COMMIT);
148 return sql::INIT_OK;
114 } 149 }
115 150
116 void HistoryDatabase::ComputeDatabaseMetrics( 151 void HistoryDatabase::ComputeDatabaseMetrics(
117 const base::FilePath& history_name) { 152 const base::FilePath& history_name) {
118 base::TimeTicks start_time = base::TimeTicks::Now(); 153 base::TimeTicks start_time = base::TimeTicks::Now();
119 int64_t file_size = 0; 154 int64_t file_size = 0;
120 if (!base::GetFileSize(history_name, &file_size)) 155 if (!base::GetFileSize(history_name, &file_size))
121 return; 156 return;
122 int file_mb = static_cast<int>(file_size / (1024 * 1024)); 157 int file_mb = static_cast<int>(file_size / (1024 * 1024));
123 UMA_HISTOGRAM_MEMORY_MB("History.DatabaseFileMB", file_mb); 158 UMA_HISTOGRAM_MEMORY_MB("History.DatabaseFileMB", file_mb);
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { 411 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
377 LOG(WARNING) << "History database is too new."; 412 LOG(WARNING) << "History database is too new.";
378 return sql::INIT_TOO_NEW; 413 return sql::INIT_TOO_NEW;
379 } 414 }
380 415
381 int cur_version = meta_table_.GetVersionNumber(); 416 int cur_version = meta_table_.GetVersionNumber();
382 417
383 // Put migration code here 418 // Put migration code here
384 419
385 if (cur_version == 15) { 420 if (cur_version == 15) {
386 if (!db_.Execute("DROP TABLE starred") || !DropStarredIDFromURLs()) { 421 if (!db_.Execute("DROP TABLE starred") || !DropStarredIDFromURLs())
387 LOG(WARNING) << "Unable to update history database to version 16."; 422 return LogMigrationFailure(15);
388 return sql::INIT_FAILURE;
389 }
390 ++cur_version; 423 ++cur_version;
391 meta_table_.SetVersionNumber(cur_version); 424 meta_table_.SetVersionNumber(cur_version);
392 meta_table_.SetCompatibleVersionNumber( 425 meta_table_.SetCompatibleVersionNumber(
393 std::min(cur_version, kCompatibleVersionNumber)); 426 std::min(cur_version, kCompatibleVersionNumber));
394 } 427 }
395 428
396 if (cur_version == 16) { 429 if (cur_version == 16) {
397 #if !defined(OS_WIN) 430 #if !defined(OS_WIN)
398 // In this version we bring the time format on Mac & Linux in sync with the 431 // In this version we bring the time format on Mac & Linux in sync with the
399 // Windows version so that profiles can be moved between computers. 432 // Windows version so that profiles can be moved between computers.
(...skipping 23 matching lines...) Expand all
423 456
424 if (cur_version == 19) { 457 if (cur_version == 19) {
425 cur_version++; 458 cur_version++;
426 meta_table_.SetVersionNumber(cur_version); 459 meta_table_.SetVersionNumber(cur_version);
427 // This was the thumbnail migration. Obsolete. 460 // This was the thumbnail migration. Obsolete.
428 } 461 }
429 462
430 if (cur_version == 20) { 463 if (cur_version == 20) {
431 // This is the version prior to adding the visit_duration field in visits 464 // This is the version prior to adding the visit_duration field in visits
432 // database. We need to migrate the database. 465 // database. We need to migrate the database.
433 if (!MigrateVisitsWithoutDuration()) { 466 if (!MigrateVisitsWithoutDuration())
434 LOG(WARNING) << "Unable to update history database to version 21."; 467 return LogMigrationFailure(20);
435 return sql::INIT_FAILURE;
436 }
437 ++cur_version; 468 ++cur_version;
438 meta_table_.SetVersionNumber(cur_version); 469 meta_table_.SetVersionNumber(cur_version);
439 } 470 }
440 471
441 if (cur_version == 21) { 472 if (cur_version == 21) {
442 // The android_urls table's data schemal was changed in version 21. 473 // The android_urls table's data schemal was changed in version 21.
443 #if defined(OS_ANDROID) 474 #if defined(OS_ANDROID)
444 if (!MigrateToVersion22()) { 475 if (!MigrateToVersion22())
445 LOG(WARNING) << "Unable to migrate the android_urls table to version 22"; 476 return LogMigrationFailure(21);
446 }
447 #endif 477 #endif
448 ++cur_version; 478 ++cur_version;
449 meta_table_.SetVersionNumber(cur_version); 479 meta_table_.SetVersionNumber(cur_version);
450 } 480 }
451 481
452 if (cur_version == 22) { 482 if (cur_version == 22) {
453 if (!MigrateDownloadsState()) { 483 if (!MigrateDownloadsState())
454 LOG(WARNING) << "Unable to fix invalid downloads state values"; 484 return LogMigrationFailure(22);
455 // Invalid state values may cause crashes.
456 return sql::INIT_FAILURE;
457 }
458 cur_version++; 485 cur_version++;
459 meta_table_.SetVersionNumber(cur_version); 486 meta_table_.SetVersionNumber(cur_version);
460 } 487 }
461 488
462 if (cur_version == 23) { 489 if (cur_version == 23) {
463 if (!MigrateDownloadsReasonPathsAndDangerType()) { 490 if (!MigrateDownloadsReasonPathsAndDangerType())
464 LOG(WARNING) << "Unable to upgrade download interrupt reason and paths"; 491 return LogMigrationFailure(23);
465 // Invalid state values may cause crashes.
466 return sql::INIT_FAILURE;
467 }
468 cur_version++; 492 cur_version++;
469 meta_table_.SetVersionNumber(cur_version); 493 meta_table_.SetVersionNumber(cur_version);
470 } 494 }
471 495
472 if (cur_version == 24) { 496 if (cur_version == 24) {
473 if (!MigratePresentationIndex()) { 497 if (!MigratePresentationIndex())
474 LOG(WARNING) << "Unable to migrate history to version 25"; 498 return LogMigrationFailure(24);
475 return sql::INIT_FAILURE;
476 }
477 cur_version++; 499 cur_version++;
478 meta_table_.SetVersionNumber(cur_version); 500 meta_table_.SetVersionNumber(cur_version);
479 } 501 }
480 502
481 if (cur_version == 25) { 503 if (cur_version == 25) {
482 if (!MigrateReferrer()) { 504 if (!MigrateReferrer())
483 LOG(WARNING) << "Unable to migrate history to version 26"; 505 return LogMigrationFailure(25);
484 return sql::INIT_FAILURE;
485 }
486 cur_version++; 506 cur_version++;
487 meta_table_.SetVersionNumber(cur_version); 507 meta_table_.SetVersionNumber(cur_version);
488 } 508 }
489 509
490 if (cur_version == 26) { 510 if (cur_version == 26) {
491 if (!MigrateDownloadedByExtension()) { 511 if (!MigrateDownloadedByExtension())
492 LOG(WARNING) << "Unable to migrate history to version 27"; 512 return LogMigrationFailure(26);
493 return sql::INIT_FAILURE;
494 }
495 cur_version++; 513 cur_version++;
496 meta_table_.SetVersionNumber(cur_version); 514 meta_table_.SetVersionNumber(cur_version);
497 } 515 }
498 516
499 if (cur_version == 27) { 517 if (cur_version == 27) {
500 if (!MigrateDownloadValidators()) { 518 if (!MigrateDownloadValidators())
501 LOG(WARNING) << "Unable to migrate history to version 28"; 519 return LogMigrationFailure(27);
502 return sql::INIT_FAILURE;
503 }
504 cur_version++; 520 cur_version++;
505 meta_table_.SetVersionNumber(cur_version); 521 meta_table_.SetVersionNumber(cur_version);
506 } 522 }
507 523
508 if (cur_version == 28) { 524 if (cur_version == 28) {
509 if (!MigrateMimeType()) { 525 if (!MigrateMimeType())
510 LOG(WARNING) << "Unable to migrate history to version 29"; 526 return LogMigrationFailure(28);
511 return sql::INIT_FAILURE;
512 }
513 cur_version++; 527 cur_version++;
514 meta_table_.SetVersionNumber(cur_version); 528 meta_table_.SetVersionNumber(cur_version);
515 } 529 }
516 530
517 if (cur_version == 29) { 531 if (cur_version == 29) {
518 if (!MigrateHashHttpMethodAndGenerateGuids()) { 532 if (!MigrateHashHttpMethodAndGenerateGuids())
519 LOG(WARNING) << "Unable to migrate history to version 30"; 533 return LogMigrationFailure(29);
520 return sql::INIT_FAILURE;
521 }
522 cur_version++; 534 cur_version++;
523 meta_table_.SetVersionNumber(cur_version); 535 meta_table_.SetVersionNumber(cur_version);
524 } 536 }
525 537
526 if (cur_version == 30) { 538 if (cur_version == 30) {
527 if (!MigrateDownloadTabUrl()) { 539 if (!MigrateDownloadTabUrl())
528 LOG(WARNING) << "Unable to migrate history to version 31"; 540 return LogMigrationFailure(30);
529 return sql::INIT_FAILURE;
530 }
531 cur_version++; 541 cur_version++;
532 meta_table_.SetVersionNumber(cur_version); 542 meta_table_.SetVersionNumber(cur_version);
533 } 543 }
534 544
535 if (cur_version == 31) { 545 if (cur_version == 31) {
536 if (!MigrateDownloadSiteInstanceUrl()) { 546 if (!MigrateDownloadSiteInstanceUrl())
537 LOG(WARNING) << "Unable to migrate history to version 32"; 547 return LogMigrationFailure(31);
538 return sql::INIT_FAILURE;
539 }
540 cur_version++; 548 cur_version++;
541 meta_table_.SetVersionNumber(cur_version); 549 meta_table_.SetVersionNumber(cur_version);
542 } 550 }
543 551
544 if (cur_version == 32) { 552 if (cur_version == 32) {
545 // New download slices table is introduced, no migration needed. 553 // New download slices table is introduced, no migration needed.
546 cur_version++; 554 cur_version++;
547 meta_table_.SetVersionNumber(cur_version); 555 meta_table_.SetVersionNumber(cur_version);
548 } 556 }
549 557
550 if (cur_version == 33) { 558 if (cur_version == 33) {
551 if (!MigrateDownloadLastAccessTime()) { 559 if (!MigrateDownloadLastAccessTime())
552 LOG(WARNING) << "Unable to migrate to version 34"; 560 return LogMigrationFailure(33);
553 return sql::INIT_FAILURE;
554 }
555 cur_version++; 561 cur_version++;
556 meta_table_.SetVersionNumber(cur_version); 562 meta_table_.SetVersionNumber(cur_version);
557 } 563 }
558 564
559 if (cur_version == 34) { 565 if (cur_version == 34) {
566 /*
567 This code is commented out because we suspect the additional disk storage
568 requirements of duplicating the URL table to update the schema cause
569 some devices to run out of storage. Errors during initialization are
570 very disruptive to the user experience.
571
572 TODO(https://crbug.com/736136) figure out how to update users to use
573 AUTOINCREMENT.
574
560 // AUTOINCREMENT is added to urls table PRIMARY KEY(id), need to recreate a 575 // AUTOINCREMENT is added to urls table PRIMARY KEY(id), need to recreate a
561 // new table and copy all contents over. favicon_id is removed from urls 576 // new table and copy all contents over. favicon_id is removed from urls
562 // table since we never use it. Also typed_url_sync_metadata and 577 // table since we never use it. Also typed_url_sync_metadata and
563 // autofill_model_type_state tables are introduced, no migration needed for 578 // autofill_model_type_state tables are introduced, no migration needed for
564 // those two tables. 579 // those two tables.
565 if (!RecreateURLTableWithAllContents()) { 580 if (!RecreateURLTableWithAllContents())
566 LOG(WARNING) << "Unable to update history database to version 35."; 581 return LogMigrationFailure(34);
567 return sql::INIT_FAILURE; 582 */
568 }
569 cur_version++; 583 cur_version++;
570 meta_table_.SetVersionNumber(cur_version); 584 meta_table_.SetVersionNumber(cur_version);
571 } 585 }
572 586
573 if (cur_version == 35) { 587 if (cur_version == 35) {
574 if (!MigrateDownloadTransient()) { 588 if (!MigrateDownloadTransient())
575 LOG(WARNING) << "Unable to migrate to version 36"; 589 return LogMigrationFailure(35);
576 return sql::INIT_FAILURE;
577 }
578 cur_version++; 590 cur_version++;
579 meta_table_.SetVersionNumber(cur_version); 591 meta_table_.SetVersionNumber(cur_version);
580 } 592 }
581 593
594 // ========================= ^^ new migration code goes here ^^
595 // ADDING NEW MIGRATION CODE
596 // =========================
597 //
598 // Add new migration code above here. It's important to use as little space
599 // as possible during migration. Many phones are very near their storage
600 // limit, so anything that recreates or duplicates large history tables can
601 // easily push them over that limit.
602 //
603 // When failures happen during initialization, history is not loaded. This
604 // causes all components related to the history database file to fail
605 // completely, including autocomplete and downloads. Devices near their
606 // storage limit are likely to fail doing some update later, but those
607 // operations will then just be skipped which is not nearly as disruptive.
608 // See https://crbug.com/734194.
609
582 // When the version is too old, we just try to continue anyway, there should 610 // When the version is too old, we just try to continue anyway, there should
583 // not be a released product that makes a database too old for us to handle. 611 // not be a released product that makes a database too old for us to handle.
584 LOG_IF(WARNING, cur_version < GetCurrentVersion()) << 612 LOG_IF(WARNING, cur_version < GetCurrentVersion()) <<
585 "History database version " << cur_version << " is too old to handle."; 613 "History database version " << cur_version << " is too old to handle.";
586 614
587 return sql::INIT_OK; 615 return sql::INIT_OK;
588 } 616 }
589 617
590 #if !defined(OS_WIN) 618 #if !defined(OS_WIN)
591 void HistoryDatabase::MigrateTimeEpoch() { 619 void HistoryDatabase::MigrateTimeEpoch() {
592 // Update all the times in the URLs and visits table in the main database. 620 // Update all the times in the URLs and visits table in the main database.
593 ignore_result(db_.Execute( 621 ignore_result(db_.Execute(
594 "UPDATE urls " 622 "UPDATE urls "
595 "SET last_visit_time = last_visit_time + 11644473600000000 " 623 "SET last_visit_time = last_visit_time + 11644473600000000 "
596 "WHERE id IN (SELECT id FROM urls WHERE last_visit_time > 0);")); 624 "WHERE id IN (SELECT id FROM urls WHERE last_visit_time > 0);"));
597 ignore_result(db_.Execute( 625 ignore_result(db_.Execute(
598 "UPDATE visits " 626 "UPDATE visits "
599 "SET visit_time = visit_time + 11644473600000000 " 627 "SET visit_time = visit_time + 11644473600000000 "
600 "WHERE id IN (SELECT id FROM visits WHERE visit_time > 0);")); 628 "WHERE id IN (SELECT id FROM visits WHERE visit_time > 0);"));
601 ignore_result(db_.Execute( 629 ignore_result(db_.Execute(
602 "UPDATE segment_usage " 630 "UPDATE segment_usage "
603 "SET time_slot = time_slot + 11644473600000000 " 631 "SET time_slot = time_slot + 11644473600000000 "
604 "WHERE id IN (SELECT id FROM segment_usage WHERE time_slot > 0);")); 632 "WHERE id IN (SELECT id FROM segment_usage WHERE time_slot > 0);"));
605 } 633 }
606 #endif 634 #endif
607 635
608 } // namespace history 636 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698