Home | History | Annotate | Download | only in history
      1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <algorithm>
      6 #include <string>
      7 
      8 #include "app/sql/transaction.h"
      9 #include "base/string_util.h"
     10 #include "chrome/browser/history/archived_database.h"
     11 
     12 namespace history {
     13 
     14 namespace {
     15 
     16 static const int kCurrentVersionNumber = 3;
     17 static const int kCompatibleVersionNumber = 2;
     18 
     19 }  // namespace
     20 
     21 ArchivedDatabase::ArchivedDatabase() {
     22 }
     23 
     24 ArchivedDatabase::~ArchivedDatabase() {
     25 }
     26 
     27 bool ArchivedDatabase::Init(const FilePath& file_name) {
     28   // Set the database page size to something a little larger to give us
     29   // better performance (we're typically seek rather than bandwidth limited).
     30   // This only has an effect before any tables have been created, otherwise
     31   // this is a NOP. Must be a power of 2 and a max of 8192.
     32   db_.set_page_size(4096);
     33 
     34   // Don't use very much memory caching this database. We seldom use it for
     35   // anything important.
     36   db_.set_cache_size(64);
     37 
     38   // Run the database in exclusive mode. Nobody else should be accessing the
     39   // database while we're running, and this will give somewhat improved perf.
     40   db_.set_exclusive_locking();
     41 
     42   if (!db_.Open(file_name))
     43     return false;
     44 
     45   sql::Transaction transaction(&db_);
     46   if (!transaction.Begin()) {
     47     db_.Close();
     48     return false;
     49   }
     50 
     51   // Version check.
     52   if (!meta_table_.Init(&db_, kCurrentVersionNumber,
     53                         kCompatibleVersionNumber)) {
     54     db_.Close();
     55     return false;
     56   }
     57 
     58   // Create the tables.
     59   if (!CreateURLTable(false) || !InitVisitTable() ||
     60       !InitKeywordSearchTermsTable()) {
     61     db_.Close();
     62     return false;
     63   }
     64   CreateMainURLIndex();
     65   CreateKeywordSearchTermsIndices();
     66 
     67   if (EnsureCurrentVersion() != sql::INIT_OK) {
     68     db_.Close();
     69     return false;
     70   }
     71 
     72   return transaction.Commit();
     73 }
     74 
     75 void ArchivedDatabase::BeginTransaction() {
     76   db_.BeginTransaction();
     77 }
     78 
     79 void ArchivedDatabase::CommitTransaction() {
     80   db_.CommitTransaction();
     81 }
     82 
     83 sql::Connection& ArchivedDatabase::GetDB() {
     84   return db_;
     85 }
     86 
     87 // Migration -------------------------------------------------------------------
     88 
     89 sql::InitStatus ArchivedDatabase::EnsureCurrentVersion() {
     90   // We can't read databases newer than we were designed for.
     91   if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
     92     LOG(WARNING) << "Archived database is too new.";
     93     return sql::INIT_TOO_NEW;
     94   }
     95 
     96   // NOTICE: If you are changing structures for things shared with the archived
     97   // history file like URLs, visits, or downloads, that will need migration as
     98   // well. Instead of putting such migration code in this class, it should be
     99   // in the corresponding file (url_database.cc, etc.) and called from here and
    100   // from the archived_database.cc.
    101 
    102   int cur_version = meta_table_.GetVersionNumber();
    103   if (cur_version == 1) {
    104     if (!DropStarredIDFromURLs()) {
    105       LOG(WARNING) << "Unable to update archived database to version 2.";
    106       return sql::INIT_FAILURE;
    107     }
    108     ++cur_version;
    109     meta_table_.SetVersionNumber(cur_version);
    110     meta_table_.SetCompatibleVersionNumber(
    111         std::min(cur_version, kCompatibleVersionNumber));
    112   }
    113 
    114   if (cur_version == 2) {
    115     // This is the version prior to adding visit_source table.
    116     ++cur_version;
    117     meta_table_.SetVersionNumber(cur_version);
    118   }
    119 
    120   // Put future migration cases here.
    121 
    122   // When the version is too old, we just try to continue anyway, there should
    123   // not be a released product that makes a database too old for us to handle.
    124   LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
    125       "Archived database version " << cur_version << " is too old to handle.";
    126 
    127   return sql::INIT_OK;
    128 }
    129 }  // namespace history
    130