summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-25 11:30:32 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-25 11:30:32 +0000
commit2321fbd36f6fe4034ce8397beb35de79c2257bac (patch)
treefa7e3cc7479cd879060e4038de28e90cc6fae3eb
parent500f32799c7bc1f521f6ef1120bb1ee5ae9c75dd (diff)
downloadchromium_src-2321fbd36f6fe4034ce8397beb35de79c2257bac.zip
chromium_src-2321fbd36f6fe4034ce8397beb35de79c2257bac.tar.gz
chromium_src-2321fbd36f6fe4034ce8397beb35de79c2257bac.tar.bz2
Update quota database schema to store quota per-host instead of per-origin.
BUG=61676 TEST=QuotaDatabaseTest.* Review URL: http://codereview.chromium.org/6882012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82847 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--webkit/quota/quota_database.cc303
-rw-r--r--webkit/quota/quota_database.h22
-rw-r--r--webkit/quota/quota_database_unittest.cc34
3 files changed, 141 insertions, 218 deletions
diff --git a/webkit/quota/quota_database.cc b/webkit/quota/quota_database.cc
index a6dd0e6..8bda57c 100644
--- a/webkit/quota/quota_database.cc
+++ b/webkit/quota/quota_database.cc
@@ -15,28 +15,27 @@
namespace {
-const int64 kUninitializedId = -1;
-const int64 kUninitializedQuota = -1;
-
// Definitions for database schema.
-const int kCurrentVersion = 1;
-const int kCompatibleVersion = 1;
+const int kCurrentVersion = 2;
+const int kCompatibleVersion = 2;
const char kOriginsTable[] = "Origins";
-const char kStorageInfoTable[] = "StorageInfo";
+const char kHostQuotaTable[] = "HostQuotaTable";
+const char kOriginLastAccessTable[] = "OriginLastAccessTable";
const char kGlobalQuotaKeyPrefix[] = "GlobalQuota-";
const struct {
const char* table_name;
const char* columns;
} kTables[] = {
- { kOriginsTable,
- "(origin_url TEXT NOT NULL)" },
- { kStorageInfoTable,
- "(origin_rowid INTEGER,"
+ { kHostQuotaTable,
+ "(host TEXT NOT NULL,"
+ " type INTEGER NOT NULL,"
+ " quota INTEGER)" },
+ { kOriginLastAccessTable,
+ "(origin TEXT NOT NULL,"
" type INTEGER NOT NULL,"
- " quota INTEGER,"
" used_count INTEGER,"
" last_access_time INTEGER)" },
};
@@ -47,13 +46,13 @@ const struct {
const char* columns;
bool unique;
} kIndexes[] = {
- { "OriginsIndex",
- kOriginsTable,
- "(origin_url)",
- true },
- { "StorageInfoIndex",
- kStorageInfoTable,
- "(origin_rowid)",
+ { "HostIndex",
+ kHostQuotaTable,
+ "(host)",
+ false },
+ { "OriginLastAccessIndex",
+ kOriginLastAccessTable,
+ "(origin, last_access_time)",
false },
};
@@ -105,21 +104,6 @@ std::string GetGlobalQuotaKey(quota::StorageType type) {
namespace quota {
-struct QuotaDatabase::StorageInfoRecord {
- StorageInfoRecord()
- : rowid(kUninitializedId),
- origin_rowid(kUninitializedId),
- type(kStorageTypeUnknown),
- quota(kUninitializedQuota),
- used_count(0) {}
- int64 rowid;
- int64 origin_rowid;
- StorageType type;
- int64 quota;
- int used_count;
- base::Time last_access_time;
-};
-
QuotaDatabase::QuotaDatabase(const FilePath& path)
: db_file_path_(path),
is_recreating_(false),
@@ -134,20 +118,32 @@ void QuotaDatabase::CloseConnection() {
db_.reset();
}
-bool QuotaDatabase::GetOriginQuota(
- const GURL& origin, StorageType type, int64* quota) {
+bool QuotaDatabase::GetHostQuota(
+ const std::string& host, StorageType type, int64* quota) {
DCHECK(quota);
- StorageInfoRecord record;
- if (!FindStorageInfo(origin, type, &record))
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT quota"
+ " FROM HostQuotaTable"
+ " WHERE host = ? AND type = ?";
+
+ sql::Statement statement;
+ if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
return false;
- if (record.quota == kUninitializedQuota)
+
+ statement.BindString(0, host);
+ statement.BindInt(1, static_cast<int>(type));
+ if (!statement.Step() || !statement.Succeeded())
return false;
- *quota = record.quota;
+
+ *quota = statement.ColumnInt64(0);
return true;
}
-bool QuotaDatabase::SetOriginQuota(
- const GURL& origin, StorageType type, int64 quota) {
+bool QuotaDatabase::SetHostQuota(
+ const std::string& host, StorageType type, int64 quota) {
DCHECK(quota >= 0);
if (!LazyOpen(true))
return false;
@@ -156,34 +152,31 @@ bool QuotaDatabase::SetOriginQuota(
if (!transaction.Begin())
return false;
- int64 origin_rowid;
- if (!FindOrigin(origin, &origin_rowid)) {
- if (!InsertOrigin(origin, &origin_rowid))
- return false;
- }
+ sql::Statement statement;
- StorageInfoRecord record;
- if (!FindStorageInfo(origin_rowid, type, &record)) {
- record.origin_rowid = origin_rowid;
- record.type = type;
- record.quota = quota;
- if (!InsertStorageInfo(record))
+ 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;
- return transaction.Commit();
}
- const char* kSql =
- "UPDATE StorageInfo"
- " SET quota = ?"
- " WHERE rowid = ?";
- sql::Statement statement;
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
- return false;
-
statement.BindInt64(0, quota);
- statement.BindInt64(1, record.rowid);
+ statement.BindString(1, host);
+ statement.BindInt(2, static_cast<int>(type));
if (!statement.Run())
return false;
+
return transaction.Commit();
}
@@ -196,60 +189,69 @@ bool QuotaDatabase::SetOriginLastAccessTime(
if (!transaction.Begin())
return false;
- int64 origin_rowid;
- if (!FindOrigin(origin, &origin_rowid)) {
- if (!InsertOrigin(origin, &origin_rowid))
+ sql::Statement statement;
+
+ int used_count = 0;
+ if (FindOriginUsedCount(origin, type, &used_count)) {
+ ++used_count;
+ const char* kSql =
+ "UPDATE OriginLastAccessTable"
+ " SET used_count = ?, last_access_time = ?"
+ " WHERE origin = ? AND type = ?";
+ if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
return false;
- }
- StorageInfoRecord record;
- if (!FindStorageInfo(origin_rowid, type, &record)) {
- record.origin_rowid = origin_rowid;
- record.type = type;
- record.used_count = 0;
- record.last_access_time = last_access_time;
- if (!InsertStorageInfo(record))
+ } else {
+ const char* kSql =
+ "INSERT INTO OriginLastAccessTable"
+ " (used_count, last_access_time, origin, type)"
+ " VALUES (?, ?, ?, ?)";
+ if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
return false;
- return transaction.Commit();
}
- const char* kSql =
- "UPDATE StorageInfo"
- " SET used_count = ?, last_access_time = ?"
- " WHERE rowid = ?";
- sql::Statement statement;
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
- return false;
-
- statement.BindInt(0, record.used_count + 1);
+ statement.BindInt(0, used_count);
statement.BindInt64(1, last_access_time.ToInternalValue());
- statement.BindInt64(2, record.rowid);
+ statement.BindString(2, origin.spec());
+ statement.BindInt(3, static_cast<int>(type));
if (!statement.Run())
return false;
return transaction.Commit();
}
-bool QuotaDatabase::DeleteStorageInfo(const GURL& origin, StorageType type) {
+bool QuotaDatabase::DeleteHostQuota(
+ const std::string& host, StorageType type) {
if (!LazyOpen(false))
return false;
- int64 origin_rowid;
- if (!FindOrigin(origin, &origin_rowid))
+ const char* kSql =
+ "DELETE FROM HostQuotaTable"
+ " WHERE host = ? AND type = ?";
+
+ sql::Statement statement;
+ if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
return false;
- StorageInfoRecord record;
- if (!FindStorageInfo(origin_rowid, type, &record))
+ statement.BindString(0, host);
+ statement.BindInt(1, static_cast<int>(type));
+ return statement.Run();
+}
+
+bool QuotaDatabase::DeleteOriginLastAccessTime(
+ const GURL& origin, StorageType type) {
+ if (!LazyOpen(false))
return false;
const char* kSql =
- "DELETE FROM StorageInfo"
- " WHERE rowid = ?";
+ "DELETE FROM OriginLastAccessTable"
+ " WHERE origin = ? AND type = ?";
sql::Statement statement;
if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
return false;
- statement.BindInt64(0, record.rowid);
+ statement.BindString(0, origin.spec());
+ statement.BindInt(1, static_cast<int>(type));
return statement.Run();
}
@@ -274,20 +276,17 @@ bool QuotaDatabase::GetLRUOrigins(
return false;
const char* kSqlBase =
- "SELECT o.origin_url FROM Origins o, StorageInfo s"
- " WHERE o.rowid = s.origin_rowid AND"
- " s.type = ?";
+ "SELECT origin FROM OriginLastAccessTable"
+ " WHERE type = ?";
- // TODO(kinuko): depending on how we call this method, consider creating
- // an index to avoid frequent full table scan.
const char* kSqlSuffix =
- " ORDER BY s.last_access_time ASC "
+ " ORDER BY last_access_time ASC "
" LIMIT ?";
std::string sql(kSqlBase);
sql::StatementID id = SQL_FROM_HERE;
if (max_used_count >= 0) {
- sql += " AND s.used_count <= ?";
+ sql += " AND used_count <= ?";
id = SQL_FROM_HERE;
}
sql += kSqlSuffix;
@@ -311,113 +310,29 @@ bool QuotaDatabase::GetLRUOrigins(
return statement.Succeeded();
}
-bool QuotaDatabase::FindOrigin(const GURL& origin_url, int64* origin_rowid) {
- DCHECK(origin_rowid);
- if (!LazyOpen(false))
- return false;
-
- const char* kSql = "SELECT rowid FROM Origins WHERE origin_url = ?";
-
- sql::Statement statement;
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
- return false;
-
- statement.BindString(0, origin_url.spec());
- if (!statement.Step() || !statement.Succeeded())
- return false;
-
- *origin_rowid = statement.ColumnInt64(0);
- return true;
-}
-
-bool QuotaDatabase::InsertOrigin(const GURL& origin_url, int64 *origin_rowid) {
- DCHECK(origin_rowid);
- if (!LazyOpen(true))
- return false;
-
- const char* kSql =
- "INSERT INTO Origins (origin_url) VALUES(?)";
-
- sql::Statement statement;
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
- return false;
-
-
- statement.BindString(0, origin_url.spec());
- if (!statement.Run())
- return false;
-
- *origin_rowid = db_->GetLastInsertRowId();
- return true;
-}
-
-bool QuotaDatabase::FindStorageInfo(int64 origin_rowid, StorageType type,
- StorageInfoRecord* record) {
- DCHECK(record);
+bool QuotaDatabase::FindOriginUsedCount(
+ const GURL& origin, StorageType type, int* used_count) {
+ DCHECK(used_count);
if (!LazyOpen(false))
return false;
const char* kSql =
- "SELECT rowid, origin_rowid, quota, used_count, last_access_time"
- " FROM StorageInfo"
- " WHERE origin_rowid = ? AND type = ?";
+ "SELECT used_count FROM OriginLastAccessTable"
+ " WHERE origin = ? AND type = ?";
sql::Statement statement;
if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
return false;
- statement.BindInt64(0, origin_rowid);
+ statement.BindString(0, origin.spec());
statement.BindInt(1, static_cast<int>(type));
if (!statement.Step() || !statement.Succeeded())
return false;
- record->rowid = statement.ColumnInt64(0);
- record->origin_rowid = statement.ColumnInt64(1);
- record->quota = statement.ColumnInt64(2);
- record->used_count = statement.ColumnInt(3);
- record->last_access_time = base::Time::FromInternalValue(
- statement.ColumnInt64(4));
-
+ *used_count = statement.ColumnInt(3);
return true;
}
-bool QuotaDatabase::FindStorageInfo(const GURL& origin, StorageType type,
- StorageInfoRecord* record) {
- DCHECK(record);
- if (!LazyOpen(false))
- return false;
-
- int64 origin_rowid;
- if (!FindOrigin(origin, &origin_rowid))
- return false;
-
- return FindStorageInfo(origin_rowid, type, record);
-}
-
-bool QuotaDatabase::InsertStorageInfo(const StorageInfoRecord& record) {
- if (!LazyOpen(true))
- return false;
-
- DCHECK(record.type == kStorageTypeTemporary ||
- record.type == kStorageTypePersistent);
-
- const char* kSql =
- "INSERT INTO StorageInfo"
- " (origin_rowid, type, quota, used_count, last_access_time)"
- " VALUES(?, ?, ?, ?, ?)";
-
- sql::Statement statement;
- if (!PrepareCachedStatement(db_.get(), SQL_FROM_HERE, kSql, &statement))
- return false;
-
- statement.BindInt64(0, record.origin_rowid);
- statement.BindInt(1, static_cast<int>(record.type));
- statement.BindInt64(2, record.quota);
- statement.BindInt(3, record.used_count);
- statement.BindInt64(4, record.last_access_time.ToInternalValue());
- return statement.Run();
-}
-
bool QuotaDatabase::LazyOpen(bool create_if_needed) {
if (db_.get())
return true;
@@ -493,8 +408,10 @@ bool QuotaDatabase::CreateSchema() {
std::string sql("CREATE TABLE ");
sql += kTables[i].table_name;
sql += kTables[i].columns;
- if (!db_->Execute(sql.c_str()))
+ if (!db_->Execute(sql.c_str())) {
+ VLOG(1) << "Failed to execute " << sql;
return false;
+ }
}
for (int i = 0; i < kIndexCount; ++i) {
@@ -507,8 +424,10 @@ bool QuotaDatabase::CreateSchema() {
sql += " ON ";
sql += kIndexes[i].table_name;
sql += kIndexes[i].columns;
- if (!db_->Execute(sql.c_str()))
+ if (!db_->Execute(sql.c_str())) {
+ VLOG(1) << "Failed to execute " << sql;
return false;
+ }
}
return transaction.Commit();
diff --git a/webkit/quota/quota_database.h b/webkit/quota/quota_database.h
index 94b5181..aabb9ac 100644
--- a/webkit/quota/quota_database.h
+++ b/webkit/quota/quota_database.h
@@ -38,13 +38,14 @@ class QuotaDatabase {
void CloseConnection();
- bool GetOriginQuota(const GURL& origin, StorageType type, int64* quota);
- bool SetOriginQuota(const GURL& origin, StorageType type, int64 quota);
+ bool GetHostQuota(const std::string& host, StorageType type, int64* quota);
+ bool SetHostQuota(const std::string& host, StorageType type, int64 quota);
bool SetOriginLastAccessTime(const GURL& origin, StorageType type,
base::Time last_access_time);
- bool DeleteStorageInfo(const GURL& origin, StorageType type);
+ bool DeleteHostQuota(const std::string& host, StorageType type);
+ bool DeleteOriginLastAccessTime(const GURL& origin, StorageType type);
bool GetGlobalQuota(StorageType type, int64* quota);
bool SetGlobalQuota(StorageType type, int64 quota);
@@ -57,16 +58,9 @@ class QuotaDatabase {
int max_used_count, int num_origins_limit);
private:
- struct StorageInfoRecord;
-
- bool FindOrigin(const GURL& origin_url, int64* origin_rowid);
- bool InsertOrigin(const GURL& origin_url, int64* origin_rowid);
-
- bool FindStorageInfo(int64 origin_rowid, StorageType type,
- StorageInfoRecord* record);
- bool FindStorageInfo(const GURL& origin, StorageType type,
- StorageInfoRecord* record);
- bool InsertStorageInfo(const StorageInfoRecord& record);
+ bool FindOriginUsedCount(const GURL& origin,
+ StorageType type,
+ int* used_count);
bool LazyOpen(bool create_if_needed);
bool EnsureDatabaseVersion();
@@ -81,7 +75,7 @@ class QuotaDatabase {
bool is_disabled_;
FRIEND_TEST_ALL_PREFIXES(QuotaDatabaseTest, LazyOpen);
- FRIEND_TEST_ALL_PREFIXES(QuotaDatabaseTest, OriginQuota);
+ FRIEND_TEST_ALL_PREFIXES(QuotaDatabaseTest, HostQuota);
FRIEND_TEST_ALL_PREFIXES(QuotaDatabaseTest, GlobalQuota);
FRIEND_TEST_ALL_PREFIXES(QuotaDatabaseTest, OriginLastAccessTimeLRU);
diff --git a/webkit/quota/quota_database_unittest.cc b/webkit/quota/quota_database_unittest.cc
index c5905ed..ccbe74f 100644
--- a/webkit/quota/quota_database_unittest.cc
+++ b/webkit/quota/quota_database_unittest.cc
@@ -38,7 +38,7 @@ TEST(QuotaDatabaseTest, LazyOpen) {
EXPECT_TRUE(file_util::PathExists(kDbFile));
}
-TEST(QuotaDatabaseTest, OriginQuota) {
+TEST(QuotaDatabaseTest, HostQuota) {
ScopedTempDir data_dir;
ASSERT_TRUE(data_dir.CreateUniqueTempDir());
@@ -46,30 +46,30 @@ TEST(QuotaDatabaseTest, OriginQuota) {
QuotaDatabase db(kDbFile);
ASSERT_TRUE(db.LazyOpen(true));
- const GURL kOrigin("http://foo.com:8080/");
+ const char* kHost = "foo.com";
const int kQuota1 = 13579;
const int kQuota2 = kQuota1 + 1024;
int64 quota = -1;
- EXPECT_FALSE(db.GetOriginQuota(kOrigin, kStorageTypeTemporary, &quota));
- EXPECT_FALSE(db.GetOriginQuota(kOrigin, kStorageTypePersistent, &quota));
+ EXPECT_FALSE(db.GetHostQuota(kHost, kStorageTypeTemporary, &quota));
+ EXPECT_FALSE(db.GetHostQuota(kHost, kStorageTypePersistent, &quota));
// Insert quota for temporary.
- EXPECT_TRUE(db.SetOriginQuota(kOrigin, kStorageTypeTemporary, kQuota1));
- EXPECT_TRUE(db.GetOriginQuota(kOrigin, kStorageTypeTemporary, &quota));
+ EXPECT_TRUE(db.SetHostQuota(kHost, kStorageTypeTemporary, kQuota1));
+ EXPECT_TRUE(db.GetHostQuota(kHost, kStorageTypeTemporary, &quota));
EXPECT_EQ(kQuota1, quota);
// Update quota for temporary.
- EXPECT_TRUE(db.SetOriginQuota(kOrigin, kStorageTypeTemporary, kQuota2));
- EXPECT_TRUE(db.GetOriginQuota(kOrigin, kStorageTypeTemporary, &quota));
+ EXPECT_TRUE(db.SetHostQuota(kHost, kStorageTypeTemporary, kQuota2));
+ EXPECT_TRUE(db.GetHostQuota(kHost, kStorageTypeTemporary, &quota));
EXPECT_EQ(kQuota2, quota);
// Quota for persistent must not be updated.
- EXPECT_FALSE(db.GetOriginQuota(kOrigin, kStorageTypePersistent, &quota));
+ EXPECT_FALSE(db.GetHostQuota(kHost, kStorageTypePersistent, &quota));
- // Delete temporary storage info.
- EXPECT_TRUE(db.DeleteStorageInfo(kOrigin, kStorageTypeTemporary));
- EXPECT_FALSE(db.GetOriginQuota(kOrigin, kStorageTypeTemporary, &quota));
+ // Delete temporary storage quota.
+ EXPECT_TRUE(db.DeleteHostQuota(kHost, kStorageTypeTemporary));
+ EXPECT_FALSE(db.GetHostQuota(kHost, kStorageTypeTemporary, &quota));
}
TEST(QuotaDatabaseTest, GlobalQuota) {
@@ -156,6 +156,16 @@ TEST(QuotaDatabaseTest, OriginLastAccessTimeLRU) {
EXPECT_EQ(kOrigin2.spec(), origins[0].spec());
EXPECT_EQ(kOrigin3.spec(), origins[1].spec());
EXPECT_EQ(kOrigin1.spec(), origins[2].spec());
+
+ // Delete origin/type last access time information.
+ EXPECT_TRUE(db.DeleteOriginLastAccessTime(kOrigin3, kStorageTypeTemporary));
+
+ // Querying again to see if the deletion has worked.
+ EXPECT_TRUE(db.GetLRUOrigins(kStorageTypeTemporary, &origins, -1, 10));
+
+ ASSERT_EQ(2U, origins.size());
+ EXPECT_EQ(kOrigin2.spec(), origins[0].spec());
+ EXPECT_EQ(kOrigin1.spec(), origins[1].spec());
}
} // namespace quota