Index: webkit/quota/quota_database.cc |
=================================================================== |
--- webkit/quota/quota_database.cc (revision 91690) |
+++ webkit/quota/quota_database.cc (working copy) |
@@ -12,25 +12,60 @@ |
#include "app/sql/statement.h" |
#include "app/sql/transaction.h" |
#include "base/auto_reset.h" |
-#include "base/bind.h" |
#include "base/file_util.h" |
#include "base/time.h" |
#include "googleurl/src/gurl.h" |
#include "webkit/quota/special_storage_policy.h" |
-namespace quota { |
namespace { |
// Definitions for database schema. |
-const int kCurrentVersion = 3; |
+const int kCurrentVersion = 2; |
const int kCompatibleVersion = 2; |
+const char kOriginsTable[] = "Origins"; |
const char kHostQuotaTable[] = "HostQuotaTable"; |
-const char kOriginInfoTable[] = "OriginInfoTable"; |
+const char kOriginLastAccessTable[] = "OriginLastAccessTable"; |
const char kGlobalQuotaKeyPrefix[] = "GlobalQuota-"; |
const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped"; |
+const struct { |
+ const char* table_name; |
+ const char* columns; |
+} kTables[] = { |
+ { kHostQuotaTable, |
+ "(host TEXT NOT NULL," |
+ " type INTEGER NOT NULL," |
+ " quota INTEGER," |
+ " UNIQUE(host, type))" }, |
+ { kOriginLastAccessTable, |
+ "(origin TEXT NOT NULL," |
+ " type INTEGER NOT NULL," |
+ " used_count INTEGER," |
+ " last_access_time INTEGER," |
+ " UNIQUE(origin, type))" }, |
+}; |
+ |
+const struct { |
+ const char* index_name; |
+ const char* table_name; |
+ const char* columns; |
+ bool unique; |
+} kIndexes[] = { |
+ { "HostIndex", |
+ kHostQuotaTable, |
+ "(host)", |
+ false }, |
+ { "OriginLastAccessIndex", |
+ kOriginLastAccessTable, |
+ "(origin, last_access_time)", |
+ false }, |
+}; |
+ |
+const int kTableCount = ARRAYSIZE_UNSAFE(kTables); |
+const int kIndexCount = ARRAYSIZE_UNSAFE(kIndexes); |
+ |
class HistogramUniquifier { |
public: |
static const char* name() { return "Sqlite.Quota.Error"; } |
@@ -61,50 +96,8 @@ |
} // anonymous namespace |
-// static |
-const QuotaDatabase::TableSchema QuotaDatabase::kTables[] = { |
- { kHostQuotaTable, |
- "(host TEXT NOT NULL," |
- " type INTEGER NOT NULL," |
- " quota INTEGER DEFAULT 0," |
- " UNIQUE(host, type))" }, |
- { kOriginInfoTable, |
- "(origin TEXT NOT NULL," |
- " type INTEGER NOT NULL," |
- " used_count INTEGER DEFAULT 0," |
- " last_access_time INTEGER DEFAULT 0," |
- " last_modified_time INTEGER DEFAULT 0," |
- " UNIQUE(origin, type))" }, |
-}; |
+namespace quota { |
-// static |
-const QuotaDatabase::IndexSchema QuotaDatabase::kIndexes[] = { |
- { "HostIndex", |
- kHostQuotaTable, |
- "(host)", |
- false }, |
- { "OriginInfoIndex", |
- kOriginInfoTable, |
- "(origin)", |
- false }, |
- { "OriginLastAccessTimeIndex", |
- kOriginInfoTable, |
- "(last_access_time)", |
- false }, |
- { "OriginLastModifiedTimeIndex", |
- kOriginInfoTable, |
- "(last_modified_time)", |
- false }, |
-}; |
- |
-struct QuotaDatabase::QuotaTableImporter { |
- bool Append(const QuotaTableEntry& entry) { |
- entries.push_back(entry); |
- return true; |
- } |
- std::vector<QuotaTableEntry> entries; |
-}; |
- |
QuotaDatabase::QuotaDatabase(const FilePath& path) |
: db_file_path_(path), |
is_recreating_(false), |
@@ -153,13 +146,24 @@ |
return false; |
sql::Statement statement; |
- const char* kSql = |
- "INSERT OR REPLACE INTO HostQuotaTable" |
- " (quota, host, type)" |
- " VALUES (?, ?, ?)"; |
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
- return false; |
+ int64 dummy; |
+ if (GetHostQuota(host, type, &dummy)) { |
+ const char* kSql = |
+ "UPDATE HostQuotaTable" |
+ " SET quota = ?" |
+ " WHERE host = ? AND type = ?"; |
+ if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
+ return false; |
+ } else { |
+ const char* kSql = |
+ "INSERT INTO HostQuotaTable" |
+ " (quota, host, type)" |
+ " VALUES (?, ?, ?)"; |
+ if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
+ return false; |
+ } |
+ |
statement.BindInt64(0, quota); |
statement.BindString(1, host); |
statement.BindInt(2, static_cast<int>(type)); |
@@ -181,14 +185,14 @@ |
if (FindOriginUsedCount(origin, type, &used_count)) { |
++used_count; |
const char* kSql = |
- "UPDATE OriginInfoTable" |
+ "UPDATE OriginLastAccessTable" |
" SET used_count = ?, last_access_time = ?" |
" WHERE origin = ? AND type = ?"; |
if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
return false; |
} else { |
const char* kSql = |
- "INSERT INTO OriginInfoTable" |
+ "INSERT INTO OriginLastAccessTable" |
" (used_count, last_access_time, origin, type)" |
" VALUES (?, ?, ?, ?)"; |
if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
@@ -206,56 +210,27 @@ |
return true; |
} |
-bool QuotaDatabase::SetOriginLastModifiedTime( |
- const GURL& origin, StorageType type, base::Time last_modified_time) { |
+bool QuotaDatabase::RegisterOrigins(const std::set<GURL>& origins, |
+ StorageType type, |
+ base::Time last_access_time) { |
if (!LazyOpen(true)) |
return false; |
- sql::Statement statement; |
- |
- int dummy; |
- if (FindOriginUsedCount(origin, type, &dummy)) { |
- const char* kSql = |
- "UPDATE OriginInfoTable" |
- " SET last_modified_time = ?" |
- " WHERE origin = ? AND type = ?"; |
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
- return false; |
- } else { |
- const char* kSql = |
- "INSERT INTO OriginInfoTable" |
- " (last_modified_time, origin, type) VALUES (?, ?, ?)"; |
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
- return false; |
- } |
- |
- statement.BindInt64(0, last_modified_time.ToInternalValue()); |
- statement.BindString(1, origin.spec()); |
- statement.BindInt(2, static_cast<int>(type)); |
- if (!statement.Run()) |
- return false; |
- |
- ScheduleCommit(); |
- return true; |
-} |
- |
-bool QuotaDatabase::RegisterInitialOriginInfo( |
- const std::set<GURL>& origins, StorageType type) { |
- if (!LazyOpen(true)) |
- return false; |
- |
typedef std::set<GURL>::const_iterator itr_type; |
for (itr_type itr = origins.begin(), end = origins.end(); |
itr != end; ++itr) { |
const char* kSql = |
- "INSERT OR IGNORE INTO OriginInfoTable" |
- " (origin, type) VALUES (?, ?)"; |
+ "INSERT OR IGNORE INTO OriginLastAccessTable" |
+ " (used_count, last_access_time, origin, type)" |
+ " VALUES (?, ?, ?, ?)"; |
sql::Statement statement; |
if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
return false; |
- statement.BindString(0, itr->spec()); |
- statement.BindInt(1, static_cast<int>(type)); |
+ statement.BindInt(0, 0); // used_count |
+ statement.BindInt64(1, last_access_time.ToInternalValue()); |
+ statement.BindString(2, itr->spec()); |
+ statement.BindInt(3, static_cast<int>(type)); |
if (!statement.Run()) |
return false; |
} |
@@ -286,13 +261,13 @@ |
return true; |
} |
-bool QuotaDatabase::DeleteOriginInfo( |
+bool QuotaDatabase::DeleteOriginLastAccessTime( |
const GURL& origin, StorageType type) { |
if (!LazyOpen(false)) |
return false; |
const char* kSql = |
- "DELETE FROM OriginInfoTable" |
+ "DELETE FROM OriginLastAccessTable" |
" WHERE origin = ? AND type = ?"; |
sql::Statement statement; |
@@ -329,7 +304,7 @@ |
if (!LazyOpen(false)) |
return false; |
- const char* kSql = "SELECT origin FROM OriginInfoTable" |
+ const char* kSql = "SELECT origin FROM OriginLastAccessTable" |
" WHERE type = ?" |
" ORDER BY last_access_time ASC"; |
@@ -353,28 +328,6 @@ |
return statement.Succeeded(); |
} |
-bool QuotaDatabase::GetOriginsModifiedSince( |
- StorageType type, std::set<GURL>* origins, base::Time modified_since) { |
- DCHECK(origins); |
- if (!LazyOpen(false)) |
- return false; |
- |
- const char* kSql = "SELECT origin FROM OriginInfoTable" |
- " WHERE type = ? AND last_modified_time > ?"; |
- |
- sql::Statement statement; |
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
- return false; |
- statement.BindInt(0, static_cast<int>(type)); |
- statement.BindInt64(1, modified_since.ToInternalValue()); |
- |
- origins->clear(); |
- while (statement.Step()) |
- origins->insert(GURL(statement.ColumnString(0))); |
- |
- return statement.Succeeded(); |
-} |
- |
bool QuotaDatabase::IsOriginDatabaseBootstrapped() { |
if (!LazyOpen(true)) |
return false; |
@@ -394,8 +347,9 @@ |
if (!db_.get()) |
return; |
- if (timer_.IsRunning()) |
- timer_.Stop(); |
+ // Note: for now this will be called only by ScheduleCommit, but when it |
+ // becomes untrue we should call timer_.Stop() here. |
+ DCHECK(!timer_.IsRunning()); |
db_->CommitTransaction(); |
db_->BeginTransaction(); |
@@ -415,7 +369,7 @@ |
return false; |
const char* kSql = |
- "SELECT used_count FROM OriginInfoTable" |
+ "SELECT used_count FROM OriginLastAccessTable" |
" WHERE origin = ? AND type = ?"; |
sql::Statement statement; |
@@ -475,13 +429,8 @@ |
} |
bool QuotaDatabase::EnsureDatabaseVersion() { |
- static const size_t kTableCount = ARRAYSIZE_UNSAFE(kTables); |
- static const size_t kIndexCount = ARRAYSIZE_UNSAFE(kIndexes); |
if (!sql::MetaTable::DoesTableExist(db_.get())) |
- return CreateSchema(db_.get(), meta_table_.get(), |
- kCurrentVersion, kCompatibleVersion, |
- kTables, kTableCount, |
- kIndexes, kIndexCount); |
+ return CreateSchema(); |
if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion)) |
return false; |
@@ -492,13 +441,13 @@ |
} |
if (meta_table_->GetVersionNumber() < kCurrentVersion) { |
- if (!UpgradeSchema(meta_table_->GetVersionNumber())) |
- return ResetSchema(); |
+ // TODO(kinuko): Support schema upgrade. |
+ return ResetSchema(); |
} |
#ifndef NDEBUG |
DCHECK(sql::MetaTable::DoesTableExist(db_.get())); |
- for (size_t i = 0; i < kTableCount; ++i) { |
+ for (int i = 0; i < kTableCount; ++i) { |
DCHECK(db_->DoesTableExist(kTables[i].table_name)); |
} |
#endif |
@@ -506,42 +455,36 @@ |
return true; |
} |
-// static |
-bool QuotaDatabase::CreateSchema( |
- sql::Connection* database, |
- sql::MetaTable* meta_table, |
- int schema_version, int compatible_version, |
- const TableSchema* tables, size_t tables_size, |
- const IndexSchema* indexes, size_t indexes_size) { |
+bool QuotaDatabase::CreateSchema() { |
// TODO(kinuko): Factor out the common code to create databases. |
- sql::Transaction transaction(database); |
+ sql::Transaction transaction(db_.get()); |
if (!transaction.Begin()) |
return false; |
- if (!meta_table->Init(database, schema_version, compatible_version)) |
+ if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion)) |
return false; |
- for (size_t i = 0; i < tables_size; ++i) { |
+ for (int i = 0; i < kTableCount; ++i) { |
std::string sql("CREATE TABLE "); |
- sql += tables[i].table_name; |
- sql += tables[i].columns; |
- if (!database->Execute(sql.c_str())) { |
+ sql += kTables[i].table_name; |
+ sql += kTables[i].columns; |
+ if (!db_->Execute(sql.c_str())) { |
VLOG(1) << "Failed to execute " << sql; |
return false; |
} |
} |
- for (size_t i = 0; i < indexes_size; ++i) { |
+ for (int i = 0; i < kIndexCount; ++i) { |
std::string sql; |
- if (indexes[i].unique) |
+ if (kIndexes[i].unique) |
sql += "CREATE UNIQUE INDEX "; |
else |
sql += "CREATE INDEX "; |
- sql += indexes[i].index_name; |
+ sql += kIndexes[i].index_name; |
sql += " ON "; |
- sql += indexes[i].table_name; |
- sql += indexes[i].columns; |
- if (!database->Execute(sql.c_str())) { |
+ sql += kIndexes[i].table_name; |
+ sql += kIndexes[i].columns; |
+ if (!db_->Execute(sql.c_str())) { |
VLOG(1) << "Failed to execute " << sql; |
return false; |
} |
@@ -573,25 +516,6 @@ |
return LazyOpen(true); |
} |
-bool QuotaDatabase::UpgradeSchema(int current_version) { |
- if (current_version == 2) { |
- QuotaTableImporter importer; |
- typedef std::vector<QuotaTableEntry> QuotaTableEntries; |
- if (!DumpQuotaTable(new QuotaTableCallback(base::Bind( |
- &QuotaTableImporter::Append, base::Unretained(&importer))))) |
- return false; |
- ResetSchema(); |
- for (QuotaTableEntries::const_iterator iter = importer.entries.begin(); |
- iter != importer.entries.end(); ++iter) { |
- if (!SetHostQuota(iter->host, iter->type, iter->quota)) |
- return false; |
- } |
- Commit(); |
- return true; |
- } |
- return false; |
-} |
- |
bool QuotaDatabase::DumpQuotaTable(QuotaTableCallback* callback) { |
scoped_ptr<QuotaTableCallback> callback_deleter(callback); |
if (!LazyOpen(true)) |
@@ -616,25 +540,24 @@ |
return statement.Succeeded(); |
} |
-bool QuotaDatabase::DumpOriginInfoTable( |
- OriginInfoTableCallback* callback) { |
- scoped_ptr<OriginInfoTableCallback> callback_deleter(callback); |
+bool QuotaDatabase::DumpLastAccessTimeTable( |
+ LastAccessTimeTableCallback* callback) { |
+ scoped_ptr<LastAccessTimeTableCallback> callback_deleter(callback); |
if (!LazyOpen(true)) |
return false; |
- const char* kSql = "SELECT * FROM OriginInfoTable"; |
+ const char* kSql = "SELECT * FROM OriginLastAccessTable"; |
sql::Statement statement; |
if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement)) |
return false; |
while (statement.Step()) { |
- OriginInfoTableEntry entry = { |
+ LastAccessTimeTableEntry entry = { |
GURL(statement.ColumnString(0)), |
static_cast<StorageType>(statement.ColumnInt(1)), |
statement.ColumnInt(2), |
- base::Time::FromInternalValue(statement.ColumnInt64(3)), |
- base::Time::FromInternalValue(statement.ColumnInt64(4)) |
+ base::Time::FromInternalValue(statement.ColumnInt64(3)) |
}; |
if (!callback->Run(entry)) |
@@ -653,8 +576,8 @@ |
return lhs.quota < rhs.quota; |
} |
-bool operator<(const QuotaDatabase::OriginInfoTableEntry& lhs, |
- const QuotaDatabase::OriginInfoTableEntry& rhs) { |
+bool operator<(const QuotaDatabase::LastAccessTimeTableEntry& lhs, |
+ const QuotaDatabase::LastAccessTimeTableEntry& rhs) { |
if (lhs.origin < rhs.origin) return true; |
if (rhs.origin < lhs.origin) return false; |
if (lhs.type < rhs.type) return true; |
@@ -663,5 +586,4 @@ |
if (rhs.used_count < lhs.used_count) return false; |
return lhs.last_access_time < rhs.last_access_time; |
} |
- |
} // quota namespace |