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 "chrome/browser/history/in_memory_database.h"
      6 
      7 #include "base/file_path.h"
      8 #include "base/logging.h"
      9 #include "base/metrics/histogram.h"
     10 #include "base/time.h"
     11 #include "base/utf_string_conversions.h"
     12 #include "build/build_config.h"
     13 
     14 namespace history {
     15 
     16 InMemoryDatabase::InMemoryDatabase() : URLDatabase() {
     17 }
     18 
     19 InMemoryDatabase::~InMemoryDatabase() {
     20 }
     21 
     22 bool InMemoryDatabase::InitDB() {
     23   // Set the database page size to 4K for better performance.
     24   db_.set_page_size(4096);
     25 
     26   if (!db_.OpenInMemory()) {
     27     NOTREACHED() << "Cannot open databse " << GetDB().GetErrorMessage();
     28     return false;
     29   }
     30 
     31   // No reason to leave data behind in memory when rows are removed.
     32   db_.Execute("PRAGMA auto_vacuum=1");
     33 
     34   // Ensure this is really an in-memory-only cache.
     35   db_.Execute("PRAGMA temp_store=MEMORY");
     36 
     37   // Create the URL table, but leave it empty for now.
     38   if (!CreateURLTable(false)) {
     39     NOTREACHED() << "Unable to create table";
     40     db_.Close();
     41     return false;
     42   }
     43 
     44   // Create the keyword search terms table.
     45   if (!InitKeywordSearchTermsTable()) {
     46     NOTREACHED() << "Unable to create keyword search terms";
     47     db_.Close();
     48     return false;
     49   }
     50 
     51   return true;
     52 }
     53 
     54 bool InMemoryDatabase::InitFromScratch() {
     55   if (!InitDB())
     56     return false;
     57 
     58   // InitDB doesn't create the index so in the disk-loading case, it can be
     59   // added afterwards.
     60   CreateMainURLIndex();
     61   CreateKeywordSearchTermsIndices();
     62   return true;
     63 }
     64 
     65 bool InMemoryDatabase::InitFromDisk(const FilePath& history_name) {
     66   if (!InitDB())
     67     return false;
     68 
     69   // Attach to the history database on disk.  (We can't ATTACH in the middle of
     70   // a transaction.)
     71   sql::Statement attach(GetDB().GetUniqueStatement("ATTACH ? AS history"));
     72   if (!attach) {
     73     NOTREACHED() << "Unable to attach to history database.";
     74     return false;
     75   }
     76 #if defined(OS_POSIX)
     77   attach.BindString(0, history_name.value());
     78 #else
     79   attach.BindString(0, WideToUTF8(history_name.value()));
     80 #endif
     81   if (!attach.Run()) {
     82     NOTREACHED() << GetDB().GetErrorMessage();
     83     return false;
     84   }
     85 
     86   // Copy URL data to memory.
     87   base::TimeTicks begin_load = base::TimeTicks::Now();
     88   if (!db_.Execute(
     89       "INSERT INTO urls SELECT * FROM history.urls WHERE typed_count > 0")) {
     90     // Unable to get data from the history database. This is OK, the file may
     91     // just not exist yet.
     92   }
     93   base::TimeTicks end_load = base::TimeTicks::Now();
     94   UMA_HISTOGRAM_MEDIUM_TIMES("History.InMemoryDBPopulate",
     95                              end_load - begin_load);
     96   UMA_HISTOGRAM_COUNTS("History.InMemoryDBItemCount", db_.GetLastChangeCount());
     97 
     98   // Insert keyword search related URLs.
     99   begin_load = base::TimeTicks::Now();
    100   if (!db_.Execute(
    101       "INSERT INTO urls SELECT u.id, u.url, u.title, u.visit_count, "
    102       "u.typed_count, u.last_visit_time, u.hidden, u.favicon_id "
    103       "FROM history.urls u JOIN history.keyword_search_terms kst "
    104       "WHERE u.typed_count = 0 AND u.id = kst.url_id")) {
    105     // Unable to get data from the history database. This is OK, the file may
    106     // just not exist yet.
    107   }
    108   end_load = base::TimeTicks::Now();
    109   UMA_HISTOGRAM_MEDIUM_TIMES("History.InMemoryDBKeywordURLPopulate",
    110                              end_load - begin_load);
    111   UMA_HISTOGRAM_COUNTS("History.InMemoryDBKeywordURLItemCount",
    112                        db_.GetLastChangeCount());
    113 
    114   // Copy search terms to memory.
    115   begin_load = base::TimeTicks::Now();
    116   if (!db_.Execute(
    117       "INSERT INTO keyword_search_terms SELECT * FROM "
    118       "history.keyword_search_terms")) {
    119     // Unable to get data from the history database. This is OK, the file may
    120     // just not exist yet.
    121   }
    122   end_load = base::TimeTicks::Now();
    123   UMA_HISTOGRAM_MEDIUM_TIMES("History.InMemoryDBKeywordTermsPopulate",
    124                              end_load - begin_load);
    125   UMA_HISTOGRAM_COUNTS("History.InMemoryDBKeywordTermsCount",
    126                        db_.GetLastChangeCount());
    127 
    128   // Detach from the history database on disk.
    129   if (!db_.Execute("DETACH history")) {
    130     NOTREACHED() << "Unable to detach from history database.";
    131     return false;
    132   }
    133 
    134   // Index the table, this is faster than creating the index first and then
    135   // inserting into it.
    136   CreateMainURLIndex();
    137   CreateKeywordSearchTermsIndices();
    138 
    139   return true;
    140 }
    141 
    142 sql::Connection& InMemoryDatabase::GetDB() {
    143   return db_;
    144 }
    145 
    146 }  // namespace history
    147