database_string_table.cc revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
1// Copyright 2013 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/extensions/activity_log/database_string_table.h" 6 7#include "base/strings/stringprintf.h" 8#include "sql/connection.h" 9#include "sql/statement.h" 10 11using base::StringPrintf; 12 13namespace extensions { 14 15// A target maximum size (in number of entries) for the mapping tables. If the 16// cache would grow larger than this, the size should be reduced. 17static const size_t kMaximumCacheSize = 1000; 18 19DatabaseStringTable::DatabaseStringTable(const std::string& table) 20 : table_(table) {} 21 22DatabaseStringTable::~DatabaseStringTable() {} 23 24bool DatabaseStringTable::Initialize(sql::Connection* connection) { 25 if (!connection->DoesTableExist(table_.c_str())) { 26 return connection->Execute(StringPrintf( 27 "CREATE TABLE %s (id INTEGER PRIMARY KEY, value TEXT NOT NULL); " 28 "CREATE UNIQUE INDEX %s_index ON %s(value)", 29 table_.c_str(), 30 table_.c_str(), 31 table_.c_str()).c_str()); 32 } else { 33 return true; 34 } 35} 36 37bool DatabaseStringTable::StringToInt(sql::Connection* connection, 38 const std::string& value, 39 int64* id) { 40 std::map<std::string, int64>::const_iterator lookup = 41 value_to_id_.find(value); 42 if (lookup != value_to_id_.end()) { 43 *id = lookup->second; 44 return true; 45 } 46 47 // We will be adding data to the cache below--check the cache size now and 48 // reduce it if needed. 49 PruneCache(); 50 51 // Operate on the assumption that the cache does a good job on 52 // frequently-used strings--if there is a cache miss, first act on the 53 // assumption that the string is not in the database either. 54 sql::Statement update(connection->GetUniqueStatement( 55 StringPrintf("INSERT OR IGNORE INTO %s(value) VALUES (?)", table_.c_str()) 56 .c_str())); 57 update.BindString(0, value); 58 if (!update.Run()) 59 return false; 60 61 if (connection->GetLastChangeCount() == 1) { 62 *id = connection->GetLastInsertRowId(); 63 id_to_value_[*id] = value; 64 value_to_id_[value] = *id; 65 return true; 66 } 67 68 // The specified string may have already existed in the database, in which 69 // case the insert above will have been ignored. If this happens, do a 70 // lookup to find the old value. 71 sql::Statement query(connection->GetUniqueStatement( 72 StringPrintf("SELECT id FROM %s WHERE value = ?", table_.c_str()) 73 .c_str())); 74 query.BindString(0, value); 75 if (!query.Step()) 76 return false; 77 *id = query.ColumnInt64(0); 78 id_to_value_[*id] = value; 79 value_to_id_[value] = *id; 80 return true; 81} 82 83bool DatabaseStringTable::IntToString(sql::Connection* connection, 84 int64 id, 85 std::string* value) { 86 std::map<int64, std::string>::const_iterator lookup = 87 id_to_value_.find(id); 88 if (lookup != id_to_value_.end()) { 89 *value = lookup->second; 90 return true; 91 } 92 93 // We will be adding data to the cache below--check the cache size now and 94 // reduce it if needed. 95 PruneCache(); 96 97 sql::Statement query(connection->GetUniqueStatement( 98 StringPrintf("SELECT value FROM %s WHERE id = ?", table_.c_str()) 99 .c_str())); 100 query.BindInt64(0, id); 101 if (!query.Step()) 102 return false; 103 104 *value = query.ColumnString(0); 105 id_to_value_[id] = *value; 106 value_to_id_[*value] = id; 107 return true; 108} 109 110void DatabaseStringTable::ClearCache() { 111 id_to_value_.clear(); 112 value_to_id_.clear(); 113} 114 115void DatabaseStringTable::PruneCache() { 116 if (id_to_value_.size() <= kMaximumCacheSize && 117 value_to_id_.size() <= kMaximumCacheSize) 118 return; 119 120 // TODO(mvrable): Perhaps implement a more intelligent caching policy. For 121 // now, to limit memory usage we simply clear the entire cache when it would 122 // become too large. Data will be brought back in from the database as 123 // needed. 124 ClearCache(); 125} 126 127} // namespace extensions 128