| Index: components/precache/core/precache_statistics_table.cc | 
| diff --git a/components/precache/core/precache_statistics_table.cc b/components/precache/core/precache_statistics_table.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..33b5fbda408c52c7a228abeaa28443a72af65ba6 | 
| --- /dev/null | 
| +++ b/components/precache/core/precache_statistics_table.cc | 
| @@ -0,0 +1,159 @@ | 
| +// 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 "components/precache/core/precache_statistics_table.h" | 
| + | 
| +#include "base/logging.h" | 
| +#include "base/strings/stringprintf.h" | 
| +#include "base/time/time.h" | 
| +#include "sql/connection.h" | 
| +#include "sql/statement.h" | 
| + | 
| +using sql::Statement; | 
| + | 
| +namespace precache { | 
| + | 
| +namespace { | 
| + | 
| +const char kStatisticsTableName[] = "precache_statistics"; | 
| + | 
| +}  // namespace | 
| + | 
| +PrecacheStatisticsTable::PrecacheStatistics::PrecacheStatistics() | 
| +    : precached_bytes(0), | 
| +      downloaded_bytes(0), | 
| +      downloaded_bytes_cellular(0), | 
| +      saved_bytes(0), | 
| +      saved_bytes_cellular(0) {} | 
| + | 
| +PrecacheStatisticsTable::PrecacheStatistics::PrecacheStatistics( | 
| +    int64 precached_bytes, int64 downloaded_bytes, | 
| +    int64 downloaded_bytes_cellular, int64 saved_bytes, | 
| +    int64 saved_bytes_cellular) | 
| +    : precached_bytes(precached_bytes), | 
| +      downloaded_bytes(downloaded_bytes), | 
| +      downloaded_bytes_cellular(downloaded_bytes_cellular), | 
| +      saved_bytes(saved_bytes), | 
| +      saved_bytes_cellular(saved_bytes_cellular) {} | 
| + | 
| +bool PrecacheStatisticsTable::PrecacheStatistics::operator==( | 
| +    const PrecacheStatistics& other) const { | 
| +  return precached_bytes == other.precached_bytes | 
| +      && downloaded_bytes == other.downloaded_bytes | 
| +      && downloaded_bytes_cellular == other.downloaded_bytes_cellular | 
| +      && saved_bytes == other.saved_bytes | 
| +      && saved_bytes_cellular == other.saved_bytes_cellular; | 
| +} | 
| + | 
| +PrecacheStatisticsTable::PrecacheStatisticsTable() : db_(NULL) {} | 
| + | 
| +PrecacheStatisticsTable::~PrecacheStatisticsTable() {} | 
| + | 
| +void PrecacheStatisticsTable::Init(sql::Connection* db) { | 
| +  DCHECK(!db_);  // Init must only be called once. | 
| +  DCHECK(db);    // The database connection must be non-NULL. | 
| +  db_ = db; | 
| +  CreateTableIfNonExistent(); | 
| +} | 
| + | 
| +void PrecacheStatisticsTable::IncreaseStatsForFetch( | 
| +    const base::Time& fetch_time, const PrecacheStatistics& stats) { | 
| +  DCHECK(db_); | 
| + | 
| +  // Create a row for that day if there is no existing one. | 
| +  Statement insert_statement(db_->GetCachedStatement( | 
| +      SQL_FROM_HERE, | 
| +      base::StringPrintf("INSERT OR IGNORE INTO %s (date) VALUES(?)", | 
| +                         kStatisticsTableName).c_str())); | 
| + | 
| +  insert_statement.BindInt64(0, GetKey(fetch_time)); | 
| +  DCHECK(insert_statement.Run()); | 
| + | 
| +  // Increase the recorded statistics for that day. | 
| +  Statement update_statement(db_->GetCachedStatement( | 
| +      SQL_FROM_HERE, | 
| +      base::StringPrintf( | 
| +          "UPDATE %s SET precached_bytes = precached_bytes + ?, " | 
| +              "downloaded_bytes = downloaded_bytes + ?, " | 
| +              "downloaded_bytes_cellular = downloaded_bytes_cellular + ?, " | 
| +              "saved_bytes = saved_bytes + ?, " | 
| +              "saved_bytes_cellular = saved_bytes_cellular + ? " | 
| +          "WHERE date = ?", kStatisticsTableName).c_str())); | 
| + | 
| +  update_statement.BindInt64(0, stats.precached_bytes); | 
| +  update_statement.BindInt64(1, stats.downloaded_bytes); | 
| +  update_statement.BindInt64(2, stats.downloaded_bytes_cellular); | 
| +  update_statement.BindInt64(3, stats.saved_bytes); | 
| +  update_statement.BindInt64(4, stats.saved_bytes_cellular); | 
| +  update_statement.BindInt64(5, GetKey(fetch_time)); | 
| + | 
| +  DCHECK(update_statement.Run()); | 
| +} | 
| + | 
| +void PrecacheStatisticsTable::GetAllStatsBetween( | 
| +    const base::Time& start_time, const base::Time& end_time, | 
| +    std::map<base::Time, PrecacheStatistics>* map) { | 
| +  DCHECK(db_); | 
| + | 
| +  Statement statement(db_->GetCachedStatement( | 
| +      SQL_FROM_HERE, | 
| +      base::StringPrintf( | 
| +          "SELECT date, precached_bytes, downloaded_bytes, " | 
| +          "downloaded_bytes_cellular, saved_bytes, saved_bytes_cellular FROM " | 
| +          "%s WHERE date >= ? and date <= ?", | 
| +          kStatisticsTableName).c_str())); | 
| + | 
| +  statement.BindInt64(0, GetKey(start_time)); | 
| +  statement.BindInt64(1, GetKey(end_time)); | 
| + | 
| +  while (statement.Step()) { | 
| +    base::Time date = base::Time::FromInternalValue(statement.ColumnInt64(0)); | 
| +    PrecacheStatistics stats; | 
| + | 
| +    stats.precached_bytes = statement.ColumnInt64(1); | 
| +    stats.downloaded_bytes = statement.ColumnInt64(2); | 
| +    stats.downloaded_bytes_cellular = statement.ColumnInt64(3); | 
| +    stats.saved_bytes = statement.ColumnInt64(4); | 
| +    stats.saved_bytes_cellular = statement.ColumnInt64(5); | 
| + | 
| +    (*map)[date] = stats; | 
| +  } | 
| +} | 
| + | 
| +void PrecacheStatisticsTable::DeleteAllStatsBetween( | 
| +    const base::Time& delete_begin, const base::Time& delete_end) { | 
| +  DCHECK(db_); | 
| + | 
| +  Statement statement(db_->GetCachedStatement( | 
| +      SQL_FROM_HERE, | 
| +      base::StringPrintf("DELETE FROM %s WHERE date >= ? AND date <= ?", | 
| +                         kStatisticsTableName).c_str())); | 
| + | 
| +  statement.BindInt64(0, GetKey(delete_begin)); | 
| +  statement.BindInt64(1, GetKey(delete_end)); | 
| + | 
| +  DCHECK(statement.Run()); | 
| +} | 
| + | 
| +// static | 
| +int64 PrecacheStatisticsTable::GetKey(const base::Time& fetch_time) { | 
| +  return fetch_time.LocalMidnight().ToInternalValue(); | 
| +} | 
| + | 
| +void PrecacheStatisticsTable::CreateTableIfNonExistent() { | 
| +  DCHECK(db_); | 
| +  if (db_->DoesTableExist(kStatisticsTableName)) | 
| +    return; | 
| + | 
| +  DCHECK(db_->Execute(base::StringPrintf( | 
| +      "CREATE TABLE %s (date INTEGER, " | 
| +                       "precached_bytes INTEGER DEFAULT 0, " | 
| +                       "downloaded_bytes INTEGER DEFAULT 0, " | 
| +                       "downloaded_bytes_cellular INTEGER DEFAULT 0, " | 
| +                       "saved_bytes INTEGER DEFAULT 0, " | 
| +                       "saved_bytes_cellular INTEGER DEFAULT 0, " | 
| +                       "PRIMARY KEY(date))", kStatisticsTableName).c_str())); | 
| +} | 
| + | 
| +}  // namespace precache | 
|  |