root/chrome/browser/extensions/activity_log/database_string_table.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Initialize
  2. StringToInt
  3. IntToString
  4. ClearCache
  5. PruneCache

// Copyright 2013 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/extensions/activity_log/database_string_table.h"

#include "base/strings/stringprintf.h"
#include "sql/connection.h"
#include "sql/statement.h"

using base::StringPrintf;

namespace extensions {

// A target maximum size (in number of entries) for the mapping tables.  If the
// cache would grow larger than this, the size should be reduced.
static const size_t kMaximumCacheSize = 1000;

DatabaseStringTable::DatabaseStringTable(const std::string& table)
    : table_(table) {}

DatabaseStringTable::~DatabaseStringTable() {}

bool DatabaseStringTable::Initialize(sql::Connection* connection) {
  if (!connection->DoesTableExist(table_.c_str())) {
    return connection->Execute(StringPrintf(
        "CREATE TABLE %s (id INTEGER PRIMARY KEY, value TEXT NOT NULL); "
        "CREATE UNIQUE INDEX %s_index ON %s(value)",
        table_.c_str(),
        table_.c_str(),
        table_.c_str()).c_str());
  } else {
    return true;
  }
}

bool DatabaseStringTable::StringToInt(sql::Connection* connection,
                                      const std::string& value,
                                      int64* id) {
  std::map<std::string, int64>::const_iterator lookup =
      value_to_id_.find(value);
  if (lookup != value_to_id_.end()) {
    *id = lookup->second;
    return true;
  }

  // We will be adding data to the cache below--check the cache size now and
  // reduce it if needed.
  PruneCache();

  // Operate on the assumption that the cache does a good job on
  // frequently-used strings--if there is a cache miss, first act on the
  // assumption that the string is not in the database either.
  sql::Statement update(connection->GetUniqueStatement(
      StringPrintf("INSERT OR IGNORE INTO %s(value) VALUES (?)", table_.c_str())
          .c_str()));
  update.BindString(0, value);
  if (!update.Run())
    return false;

  if (connection->GetLastChangeCount() == 1) {
    *id = connection->GetLastInsertRowId();
    id_to_value_[*id] = value;
    value_to_id_[value] = *id;
    return true;
  }

  // The specified string may have already existed in the database, in which
  // case the insert above will have been ignored.  If this happens, do a
  // lookup to find the old value.
  sql::Statement query(connection->GetUniqueStatement(
      StringPrintf("SELECT id FROM %s WHERE value = ?", table_.c_str())
          .c_str()));
  query.BindString(0, value);
  if (!query.Step())
    return false;
  *id = query.ColumnInt64(0);
  id_to_value_[*id] = value;
  value_to_id_[value] = *id;
  return true;
}

bool DatabaseStringTable::IntToString(sql::Connection* connection,
                                      int64 id,
                                      std::string* value) {
  std::map<int64, std::string>::const_iterator lookup =
      id_to_value_.find(id);
  if (lookup != id_to_value_.end()) {
    *value = lookup->second;
    return true;
  }

  // We will be adding data to the cache below--check the cache size now and
  // reduce it if needed.
  PruneCache();

  sql::Statement query(connection->GetUniqueStatement(
      StringPrintf("SELECT value FROM %s WHERE id = ?", table_.c_str())
          .c_str()));
  query.BindInt64(0, id);
  if (!query.Step())
    return false;

  *value = query.ColumnString(0);
  id_to_value_[id] = *value;
  value_to_id_[*value] = id;
  return true;
}

void DatabaseStringTable::ClearCache() {
  id_to_value_.clear();
  value_to_id_.clear();
}

void DatabaseStringTable::PruneCache() {
  if (id_to_value_.size() <= kMaximumCacheSize &&
      value_to_id_.size() <= kMaximumCacheSize)
    return;

  // TODO(mvrable): Perhaps implement a more intelligent caching policy.  For
  // now, to limit memory usage we simply clear the entire cache when it would
  // become too large.  Data will be brought back in from the database as
  // needed.
  ClearCache();
}

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */