blob: 61e2570e4756b59dbbfdf9fddf7b58a47ec559f4 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/history/in_memory_database.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
namespace history {
InMemoryDatabase::InMemoryDatabase() : URLDatabase() {
}
InMemoryDatabase::~InMemoryDatabase() {
}
bool InMemoryDatabase::InitDB() {
// Set the database page size to 4K for better performance.
db_.set_page_size(4096);
if (!db_.OpenInMemory()) {
NOTREACHED() << "Cannot open databse " << GetDB().GetErrorMessage();
return false;
}
// No reason to leave data behind in memory when rows are removed.
ignore_result(db_.Execute("PRAGMA auto_vacuum=1"));
// Ensure this is really an in-memory-only cache.
ignore_result(db_.Execute("PRAGMA temp_store=MEMORY"));
// Create the URL table, but leave it empty for now.
if (!CreateURLTable(false)) {
NOTREACHED() << "Unable to create table";
db_.Close();
return false;
}
// Create the keyword search terms table.
if (!InitKeywordSearchTermsTable()) {
NOTREACHED() << "Unable to create keyword search terms";
db_.Close();
return false;
}
return true;
}
bool InMemoryDatabase::InitFromScratch() {
if (!InitDB())
return false;
// InitDB doesn't create the index so in the disk-loading case, it can be
// added afterwards.
CreateMainURLIndex();
CreateKeywordSearchTermsIndices();
return true;
}
bool InMemoryDatabase::InitFromDisk(const base::FilePath& history_name) {
if (!InitDB())
return false;
// Attach to the history database on disk. (We can't ATTACH in the middle of
// a transaction.)
sql::Statement attach(GetDB().GetUniqueStatement("ATTACH ? AS history"));
#if defined(OS_POSIX)
attach.BindString(0, history_name.value());
#else
attach.BindString(0, WideToUTF8(history_name.value()));
#endif
if (!attach.Run())
return false;
// Copy URL data to memory.
base::TimeTicks begin_load = base::TimeTicks::Now();
if (!db_.Execute(
"INSERT INTO urls SELECT * FROM history.urls WHERE typed_count > 0")) {
// Unable to get data from the history database. This is OK, the file may
// just not exist yet.
}
base::TimeTicks end_load = base::TimeTicks::Now();
UMA_HISTOGRAM_MEDIUM_TIMES("History.InMemoryDBPopulate",
end_load - begin_load);
UMA_HISTOGRAM_COUNTS("History.InMemoryDBItemCount", db_.GetLastChangeCount());
{
// This calculation should be fast (since it's on an in-memory DB with
// an average of only 35 rows).
sql::Statement visit_count(db_.GetUniqueStatement(
"SELECT sum(visit_count) FROM urls"));
if (visit_count.Step()) {
UMA_HISTOGRAM_COUNTS("History.InMemoryTypedUrlVisitCount",
visit_count.ColumnInt(0));
}
}
// Insert keyword search related URLs.
begin_load = base::TimeTicks::Now();
if (!db_.Execute(
"INSERT OR IGNORE INTO urls SELECT u.id, u.url, u.title, u.visit_count, "
"u.typed_count, u.last_visit_time, u.hidden, u.favicon_id "
"FROM history.urls u JOIN history.keyword_search_terms kst "
"WHERE u.typed_count = 0 AND u.id = kst.url_id")) {
// Unable to get data from the history database. This is OK, the file may
// just not exist yet.
}
end_load = base::TimeTicks::Now();
UMA_HISTOGRAM_MEDIUM_TIMES("History.InMemoryDBKeywordURLPopulate",
end_load - begin_load);
UMA_HISTOGRAM_COUNTS("History.InMemoryDBKeywordURLItemCount",
db_.GetLastChangeCount());
// Copy search terms to memory.
begin_load = base::TimeTicks::Now();
if (!db_.Execute(
"INSERT INTO keyword_search_terms SELECT * FROM "
"history.keyword_search_terms")) {
// Unable to get data from the history database. This is OK, the file may
// just not exist yet.
}
end_load = base::TimeTicks::Now();
UMA_HISTOGRAM_MEDIUM_TIMES("History.InMemoryDBKeywordTermsPopulate",
end_load - begin_load);
UMA_HISTOGRAM_COUNTS("History.InMemoryDBKeywordTermsCount",
db_.GetLastChangeCount());
// Detach from the history database on disk.
if (!db_.Execute("DETACH history")) {
NOTREACHED() << "Unable to detach from history database.";
return false;
}
// Index the table, this is faster than creating the index first and then
// inserting into it.
CreateMainURLIndex();
CreateKeywordSearchTermsIndices();
return true;
}
sql::Connection& InMemoryDatabase::GetDB() {
return db_;
}
} // namespace history