summaryrefslogtreecommitdiffstats
path: root/webkit/appcache
diff options
context:
space:
mode:
authormichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-08 21:39:23 +0000
committermichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-08 21:39:23 +0000
commit31be98b016611afba449aace847074724f51e22d (patch)
tree88c7cf441d37d26a4f7eff0182669035aa8ae35c /webkit/appcache
parent349e8d271a90f15a4746412c93706cc9f78e4520 (diff)
downloadchromium_src-31be98b016611afba449aace847074724f51e22d.zip
chromium_src-31be98b016611afba449aace847074724f51e22d.tar.gz
chromium_src-31be98b016611afba449aace847074724f51e22d.tar.bz2
Add a DeletableResponseIds table to the appcache database schema, groundwork for purging unused responses from the disk cache.
TEST=yes BUG=none Review URL: http://codereview.chromium.org/523157 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35829 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache')
-rw-r--r--webkit/appcache/appcache_database.cc137
-rw-r--r--webkit/appcache/appcache_database.h14
-rw-r--r--webkit/appcache/appcache_database_unittest.cc79
-rw-r--r--webkit/appcache/appcache_storage_impl.cc4
4 files changed, 209 insertions, 25 deletions
diff --git a/webkit/appcache/appcache_database.cc b/webkit/appcache/appcache_database.cc
index 606d6c1..ddfa34d 100644
--- a/webkit/appcache/appcache_database.cc
+++ b/webkit/appcache/appcache_database.cc
@@ -24,6 +24,7 @@ const char* kCachesTable = "Caches";
const char* kEntriesTable = "Entries";
const char* kFallbackNameSpacesTable = "FallbackNameSpaces";
const char* kOnlineWhiteListsTable = "OnlineWhiteLists";
+const char* kDeletableResponseIdsTable = "DeletableResponseIds";
const struct {
const char* table_name;
@@ -57,6 +58,9 @@ const struct {
{ kOnlineWhiteListsTable,
"(cache_id INTEGER,"
" namespace_url TEXT)" },
+
+ { kDeletableResponseIdsTable,
+ "(response_id INTEGER NOT NULL)" },
};
const struct {
@@ -109,6 +113,11 @@ const struct {
kOnlineWhiteListsTable,
"(cache_id)",
false },
+
+ { "DeletableResponsesIdIndex",
+ kDeletableResponseIdsTable,
+ "(response_id)",
+ true },
};
const int kTableCount = ARRAYSIZE_UNSAFE(kTables);
@@ -155,38 +164,41 @@ bool AppCacheDatabase::FindOriginsWithGroups(std::set<GURL>* origins) {
}
bool AppCacheDatabase::FindLastStorageIds(
- int64* last_group_id, int64* last_cache_id, int64* last_response_id) {
- DCHECK(last_group_id && last_cache_id && last_response_id);
+ int64* last_group_id, int64* last_cache_id, int64* last_response_id,
+ int64* last_deletable_response_rowid) {
+ DCHECK(last_group_id && last_cache_id && last_response_id &&
+ last_deletable_response_rowid);
*last_group_id = 0;
*last_cache_id = 0;
*last_response_id = 0;
+ *last_deletable_response_rowid = 0;
if (!LazyOpen(false))
return false;
- sql::Statement statement;
-
- const char* kSql1 = "SELECT MAX(group_id) FROM Groups";
- if (!PrepareUniqueStatement(kSql1, &statement) ||
- !statement.Step()) {
- return false;
- }
- int64 group_id = statement.ColumnInt64(0);
-
- const char* kSql2 = "SELECT MAX(cache_id) FROM Caches";
- if (!PrepareUniqueStatement(kSql2, &statement) ||
- !statement.Step()) {
+ const char* kMaxGroupIdSql = "SELECT MAX(group_id) FROM Groups";
+ const char* kMaxCacheIdSql = "SELECT MAX(cache_id) FROM Caches";
+ const char* kMaxDeletableResponseRowIdSql =
+ "SELECT MAX(rowid) FROM DeletableResponseIds";
+ int64 group_id;
+ int64 cache_id;
+ int64 deletable_response_rowid;
+ if (!RunUniqueStatementWithInt64Result(kMaxGroupIdSql, &group_id) ||
+ !RunUniqueStatementWithInt64Result(kMaxCacheIdSql, &cache_id) ||
+ !RunUniqueStatementWithInt64Result(kMaxDeletableResponseRowIdSql,
+ &deletable_response_rowid)) {
return false;
}
- int64 cache_id = statement.ColumnInt64(0);
- // TODO(michaeln): SELECT MAX(responseId) FROM Where/How ?
+ // TODO(michaeln): SELECT MAX(responseId) FROM somewhere,
+ // or retrieve from the meta_table.
int64 response_id = 0;
*last_group_id = group_id;
*last_cache_id = cache_id;
*last_response_id = response_id;
+ *last_deletable_response_rowid = deletable_response_rowid;
return true;
}
@@ -444,7 +456,6 @@ bool AppCacheDatabase::FindEntriesForUrl(
return statement.Succeeded();
}
-
bool AppCacheDatabase::FindEntry(
int64 cache_id, const GURL& url, EntryRecord* record) {
DCHECK(record);
@@ -492,13 +503,18 @@ bool AppCacheDatabase::InsertEntry(const EntryRecord* record) {
bool AppCacheDatabase::InsertEntryRecords(
const std::vector<EntryRecord>& records) {
+ if (records.empty())
+ return true;
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
std::vector<EntryRecord>::const_iterator iter = records.begin();
while (iter != records.end()) {
if (!InsertEntry(&(*iter)))
return false;
++iter;
}
- return true;
+ return transaction.Commit();
}
bool AppCacheDatabase::DeleteEntriesForCache(int64 cache_id) {
@@ -603,13 +619,18 @@ bool AppCacheDatabase::InsertFallbackNameSpace(
bool AppCacheDatabase::InsertFallbackNameSpaceRecords(
const std::vector<FallbackNameSpaceRecord>& records) {
+ if (records.empty())
+ return true;
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
std::vector<FallbackNameSpaceRecord>::const_iterator iter = records.begin();
while (iter != records.end()) {
if (!InsertFallbackNameSpace(&(*iter)))
return false;
++iter;
}
- return true;
+ return transaction.Commit();
}
bool AppCacheDatabase::DeleteFallbackNameSpacesForCache(int64 cache_id) {
@@ -669,13 +690,18 @@ bool AppCacheDatabase::InsertOnlineWhiteList(
bool AppCacheDatabase::InsertOnlineWhiteListRecords(
const std::vector<OnlineWhiteListRecord>& records) {
+ if (records.empty())
+ return true;
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
std::vector<OnlineWhiteListRecord>::const_iterator iter = records.begin();
while (iter != records.end()) {
if (!InsertOnlineWhiteList(&(*iter)))
return false;
++iter;
}
- return true;
+ return transaction.Commit();
}
bool AppCacheDatabase::DeleteOnlineWhiteListForCache(int64 cache_id) {
@@ -693,6 +719,77 @@ bool AppCacheDatabase::DeleteOnlineWhiteListForCache(int64 cache_id) {
return statement.Run();
}
+bool AppCacheDatabase::GetDeletableResponseIds(
+ std::vector<int64>* response_ids, int64 max_rowid, int limit) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT response_id FROM DeletableResponseIds "
+ " WHERE rowid <= ?"
+ " LIMIT ?";
+ sql::Statement statement;
+ if (!PrepareCachedStatement(SQL_FROM_HERE, kSql, &statement))
+ return false;
+
+ statement.BindInt64(0, max_rowid);
+ statement.BindInt64(1, limit);
+ while (statement.Step())
+ response_ids->push_back(statement.ColumnInt64(0));
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::InsertDeletableResponseIds(
+ const std::vector<int64>& response_ids) {
+ const char* kSql =
+ "INSERT INTO DeletableResponseIds (response_id) VALUES (?)";
+ return RunCachedStatementWithIds(SQL_FROM_HERE, kSql, response_ids);
+}
+
+bool AppCacheDatabase::DeleteDeletableResponseIds(
+ const std::vector<int64>& response_ids) {
+ const char* kSql =
+ "DELETE FROM DeletableResponseIds WHERE response_id = ?";
+ return RunCachedStatementWithIds(SQL_FROM_HERE, kSql, response_ids);
+}
+
+bool AppCacheDatabase::RunCachedStatementWithIds(
+ const sql::StatementID& statement_id, const char* sql,
+ const std::vector<int64>& ids) {
+ if (!LazyOpen(true))
+ return false;
+
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
+
+ sql::Statement statement;
+ if (!PrepareCachedStatement(statement_id, sql, &statement))
+ return false;
+
+ std::vector<int64>::const_iterator iter = ids.begin();
+ while (iter != ids.end()) {
+ statement.BindInt64(0, *iter);
+ if (!statement.Run())
+ return false;
+ statement.Reset();
+ ++iter;
+ }
+
+ return transaction.Commit();
+}
+
+bool AppCacheDatabase::RunUniqueStatementWithInt64Result(
+ const char* sql, int64* result) {
+ sql::Statement statement;
+ if (!PrepareUniqueStatement(sql, &statement) ||
+ !statement.Step()) {
+ return false;
+ }
+ *result = statement.ColumnInt64(0);
+ return true;
+}
+
bool AppCacheDatabase::PrepareUniqueStatement(
const char* sql, sql::Statement* statement) {
DCHECK(sql && statement);
diff --git a/webkit/appcache/appcache_database.h b/webkit/appcache/appcache_database.h
index 5f1713e..c492cae 100644
--- a/webkit/appcache/appcache_database.h
+++ b/webkit/appcache/appcache_database.h
@@ -72,7 +72,8 @@ class AppCacheDatabase {
void CloseConnection();
bool FindOriginsWithGroups(std::set<GURL>* origins);
bool FindLastStorageIds(
- int64* last_group_id, int64* last_cache_id, int64* last_response_id);
+ int64* last_group_id, int64* last_cache_id, int64* last_response_id,
+ int64* last_deletable_response_rowid);
bool FindGroup(int64 group_id, GroupRecord* record);
bool FindGroupForManifestUrl(const GURL& manifest_url, GroupRecord* record);
@@ -115,6 +116,11 @@ class AppCacheDatabase {
const std::vector<OnlineWhiteListRecord>& records);
bool DeleteOnlineWhiteListForCache(int64 cache_id);
+ bool GetDeletableResponseIds(std::vector<int64>* response_ids,
+ int64 max_rowid, int limit);
+ bool InsertDeletableResponseIds(const std::vector<int64>& response_ids);
+ bool DeleteDeletableResponseIds(const std::vector<int64>& response_ids);
+
// So our callers can wrap operations in transactions.
sql::Connection* db_connection() {
LazyOpen(true);
@@ -122,6 +128,11 @@ class AppCacheDatabase {
}
private:
+ bool RunCachedStatementWithIds(
+ const sql::StatementID& statement_id, const char* sql,
+ const std::vector<int64>& ids);
+ bool RunUniqueStatementWithInt64Result(const char* sql, int64* result);
+
bool PrepareUniqueStatement(const char* sql, sql::Statement* statement);
bool PrepareCachedStatement(
const sql::StatementID& id, const char* sql, sql::Statement* statement);
@@ -159,6 +170,7 @@ class AppCacheDatabase {
FRIEND_TEST(AppCacheDatabaseTest, LazyOpen);
FRIEND_TEST(AppCacheDatabaseTest, OnlineWhiteListRecords);
FRIEND_TEST(AppCacheDatabaseTest, ReCreate);
+ FRIEND_TEST(AppCacheDatabaseTest, DeletableResponseIds);
DISALLOW_COPY_AND_ASSIGN(AppCacheDatabase);
};
diff --git a/webkit/appcache/appcache_database_unittest.cc b/webkit/appcache/appcache_database_unittest.cc
index 11452c8..2ee25da 100644
--- a/webkit/appcache/appcache_database_unittest.cc
+++ b/webkit/appcache/appcache_database_unittest.cc
@@ -37,12 +37,14 @@ TEST(AppCacheDatabaseTest, LazyOpen) {
EXPECT_FALSE(db.LazyOpen(false));
EXPECT_TRUE(db.LazyOpen(true));
- int64 group_id, cache_id, response_id;
- group_id = cache_id = response_id = 0;
- EXPECT_TRUE(db.FindLastStorageIds(&group_id, &cache_id, &response_id));
+ int64 group_id, cache_id, response_id, deleteable_response_rowid;
+ group_id = cache_id = response_id = deleteable_response_rowid = 0;
+ EXPECT_TRUE(db.FindLastStorageIds(&group_id, &cache_id, &response_id,
+ &deleteable_response_rowid));
EXPECT_EQ(0, group_id);
EXPECT_EQ(0, cache_id);
EXPECT_EQ(0, response_id);
+ EXPECT_EQ(0, deleteable_response_rowid);
std::set<GURL> origins;
EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
@@ -444,4 +446,75 @@ TEST(AppCacheDatabaseTest, OnlineWhiteListRecords) {
EXPECT_TRUE(records.empty());
}
+TEST(AppCacheDatabaseTest, DeletableResponseIds) {
+ const FilePath kEmptyPath;
+ AppCacheDatabase db(kEmptyPath);
+ EXPECT_TRUE(db.LazyOpen(true));
+
+ scoped_refptr<TestErrorDelegate> error_delegate(new TestErrorDelegate);
+ db.db_->set_error_delegate(error_delegate);
+
+ std::vector<int64> ids;
+
+ EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
+ EXPECT_TRUE(ids.empty());
+ ids.push_back(0);
+ EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
+ EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
+
+ ids.clear();
+ EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
+ EXPECT_EQ(1U, ids.size());
+ EXPECT_EQ(0, ids[0]);
+
+ int64 unused, deleteable_response_rowid;
+ unused = deleteable_response_rowid = 0;
+ EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
+ &deleteable_response_rowid));
+ EXPECT_EQ(1, deleteable_response_rowid);
+
+
+ // Expected to fail due to the duplicate id, 0 is already in the table.
+ ids.clear();
+ ids.push_back(0);
+ ids.push_back(1);
+ EXPECT_FALSE(db.InsertDeletableResponseIds(ids));
+
+ ids.clear();
+ for (int i = 1; i < 10; ++i)
+ ids.push_back(i);
+ EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
+ EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
+ &deleteable_response_rowid));
+ EXPECT_EQ(10, deleteable_response_rowid);
+
+ ids.clear();
+ EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
+ EXPECT_EQ(10U, ids.size());
+ for (int i = 0; i < 10; ++i)
+ EXPECT_EQ(i, ids[i]);
+
+ // Ensure the limit is respected.
+ ids.clear();
+ EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 5));
+ EXPECT_EQ(5U, ids.size());
+ for (size_t i = 0; i < ids.size(); ++i)
+ EXPECT_EQ(i, ids[i]);
+
+ // Ensure the max_rowid is respected (the first rowid is 1).
+ ids.clear();
+ EXPECT_TRUE(db.GetDeletableResponseIds(&ids, 5, 100));
+ EXPECT_EQ(5U, ids.size());
+ for (size_t i = 0; i < ids.size(); ++i)
+ EXPECT_EQ(i, ids[i]);
+
+ // Ensure that we can delete from the table.
+ EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
+ ids.clear();
+ EXPECT_TRUE(db.GetDeletableResponseIds(&ids, kint64max, 100));
+ EXPECT_EQ(5U, ids.size());
+ for (size_t i = 0; i < ids.size(); ++i)
+ EXPECT_EQ(i + 5, ids[i]);
+}
+
} // namespace appcache
diff --git a/webkit/appcache/appcache_storage_impl.cc b/webkit/appcache/appcache_storage_impl.cc
index 44c2365..3d88727 100644
--- a/webkit/appcache/appcache_storage_impl.cc
+++ b/webkit/appcache/appcache_storage_impl.cc
@@ -114,12 +114,14 @@ class AppCacheStorageImpl::InitTask : public DatabaseTask {
int64 last_group_id_;
int64 last_cache_id_;
int64 last_response_id_;
+ int64 last_deletable_response_rowid_;
std::set<GURL> origins_with_groups_;
};
void AppCacheStorageImpl::InitTask::Run() {
database_->FindLastStorageIds(
- &last_group_id_, &last_cache_id_, &last_response_id_);
+ &last_group_id_, &last_cache_id_, &last_response_id_,
+ &last_deletable_response_rowid_);
database_->FindOriginsWithGroups(&origins_with_groups_);
}