diff options
author | michaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-08 21:39:23 +0000 |
---|---|---|
committer | michaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-08 21:39:23 +0000 |
commit | 31be98b016611afba449aace847074724f51e22d (patch) | |
tree | 88c7cf441d37d26a4f7eff0182669035aa8ae35c /webkit/appcache | |
parent | 349e8d271a90f15a4746412c93706cc9f78e4520 (diff) | |
download | chromium_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.cc | 137 | ||||
-rw-r--r-- | webkit/appcache/appcache_database.h | 14 | ||||
-rw-r--r-- | webkit/appcache/appcache_database_unittest.cc | 79 | ||||
-rw-r--r-- | webkit/appcache/appcache_storage_impl.cc | 4 |
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_); } |