• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InMemoryDatabase()16 InMemoryDatabase::InMemoryDatabase() : URLDatabase() {
17 }
18 
~InMemoryDatabase()19 InMemoryDatabase::~InMemoryDatabase() {
20 }
21 
InitDB()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 
InitFromScratch()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 
InitFromDisk(const FilePath & history_name)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 
GetDB()142 sql::Connection& InMemoryDatabase::GetDB() {
143   return db_;
144 }
145 
146 }  // namespace history
147