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