Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Unified Diff: webkit/appcache/appcache_storage_impl.cc

Issue 7031065: AppCache + Quota integration (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/appcache/appcache_storage_impl.h ('k') | webkit/appcache/appcache_storage_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/appcache/appcache_storage_impl.cc
===================================================================
--- webkit/appcache/appcache_storage_impl.cc (revision 88615)
+++ webkit/appcache/appcache_storage_impl.cc (working copy)
@@ -4,6 +4,8 @@
#include "webkit/appcache/appcache_storage_impl.h"
+#include <set>
+
#include "app/sql/connection.h"
#include "app/sql/transaction.h"
#include "base/file_util.h"
@@ -19,9 +21,12 @@
#include "webkit/appcache/appcache_group.h"
#include "webkit/appcache/appcache_histograms.h"
#include "webkit/appcache/appcache_policy.h"
+#include "webkit/appcache/appcache_quota_client.h"
#include "webkit/appcache/appcache_response.h"
#include "webkit/appcache/appcache_service.h"
#include "webkit/appcache/appcache_thread.h"
+#include "webkit/quota/quota_client.h"
+#include "webkit/quota/quota_manager.h"
#include "webkit/quota/special_storage_policy.h"
namespace {
@@ -33,6 +38,9 @@
namespace appcache {
+// Hard coded default when not using quota management.
+static const int kDefaultQuota = 5 * 1024 * 1024;
+
static const int kMaxDiskCacheSize = 250 * 1024 * 1024;
static const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
static const FilePath::CharType kDiskCacheDirectoryName[] =
@@ -146,14 +154,14 @@
int64 last_cache_id_;
int64 last_response_id_;
int64 last_deletable_response_rowid_;
- std::set<GURL> origins_with_groups_;
+ std::map<GURL, int64> usage_map_;
};
void AppCacheStorageImpl::InitTask::Run() {
database_->FindLastStorageIds(
&last_group_id_, &last_cache_id_, &last_response_id_,
&last_deletable_response_rowid_);
- database_->FindOriginsWithGroups(&origins_with_groups_);
+ database_->GetAllOriginUsage(&usage_map_);
}
void AppCacheStorageImpl::InitTask::RunCompleted() {
@@ -163,14 +171,16 @@
storage_->last_deletable_response_rowid_ = last_deletable_response_rowid_;
if (!storage_->is_disabled()) {
- storage_->origins_with_groups_.swap(origins_with_groups_);
-
+ storage_->usage_map_.swap(usage_map_);
const int kDelayMillis = 5 * 60 * 1000; // Five minutes.
MessageLoop::current()->PostDelayedTask(FROM_HERE,
storage_->method_factory_.NewRunnableMethod(
&AppCacheStorageImpl::DelayedStartDeletingUnusedResponses),
kDelayMillis);
}
+
+ if (storage_->service()->quota_client())
+ storage_->service()->quota_client()->NotifyAppCacheReady();
}
// CloseConnectionTask -------
@@ -302,6 +312,8 @@
cache->get()->GetEntry(*iter)->add_types(AppCacheEntry::FOREIGN);
}
+ storage_->NotifyStorageAccessed(group_record_.origin);
+
// TODO(michaeln): Maybe verify that the responses we expect to exist
// do actually exist in the disk_cache (and if not then what?)
}
@@ -395,6 +407,10 @@
StoreGroupAndCacheTask(AppCacheStorageImpl* storage, AppCacheGroup* group,
AppCache* newest_cache);
+ void GetQuotaThenSchedule();
+ void OnQuotaCallback(
+ quota::QuotaStatusCode status, int64 usage, int64 quota);
+
virtual void Run();
virtual void RunCompleted();
virtual void CancelCompletion();
@@ -403,7 +419,8 @@
scoped_refptr<AppCache> cache_;
bool success_;
bool would_exceed_quota_;
- int64 quota_override_;
+ int64 space_available_;
+ int64 new_origin_usage_;
std::vector<int64> newly_deletable_response_ids_;
};
@@ -411,7 +428,7 @@
AppCacheStorageImpl* storage, AppCacheGroup* group, AppCache* newest_cache)
: StoreOrLoadTask(storage), group_(group), cache_(newest_cache),
success_(false), would_exceed_quota_(false),
- quota_override_(-1) {
+ space_available_(-1), new_origin_usage_(-1) {
group_record_.group_id = group->group_id();
group_record_.manifest_url = group->manifest_url();
group_record_.origin = group_record_.manifest_url.GetOrigin();
@@ -419,14 +436,45 @@
group,
&cache_record_, &entry_records_, &fallback_namespace_records_,
&online_whitelist_records_);
+}
- if (storage->service()->special_storage_policy() &&
- storage->service()->special_storage_policy()->IsStorageUnlimited(
- group_record_.origin)) {
- quota_override_ = kint64max;
+void AppCacheStorageImpl::StoreGroupAndCacheTask::GetQuotaThenSchedule() {
+ quota::QuotaManager* quota_manager = NULL;
+ if (storage_->service()->quota_manager_proxy()) {
+ quota_manager =
+ storage_->service()->quota_manager_proxy()->quota_manager();
}
+
+ if (!quota_manager) {
+ if (storage_->service()->special_storage_policy() &&
+ storage_->service()->special_storage_policy()->IsStorageUnlimited(
+ group_record_.origin))
+ space_available_ = kint64max;
+ Schedule();
+ return;
+ }
+
+ // We have to ask the quota manager for the value.
+ AddRef(); // balanced in the OnQuotaCallback
+ storage_->pending_quota_queries_.insert(this);
+ quota_manager->GetUsageAndQuota(
+ group_record_.origin, quota::kStorageTypeTemporary,
+ NewCallback(this, &StoreGroupAndCacheTask::OnQuotaCallback));
}
+void AppCacheStorageImpl::StoreGroupAndCacheTask::OnQuotaCallback(
+ quota::QuotaStatusCode status, int64 usage, int64 quota) {
+ if (storage_) {
+ if (status == quota::kQuotaStatusOk)
+ space_available_ = std::max(static_cast<int64>(0), quota - usage);
+ else
+ space_available_ = 0;
+ storage_->pending_quota_queries_.erase(this);
+ Schedule();
+ }
+ Release(); // balanced in GetQuotaThenSchedule
+}
+
void AppCacheStorageImpl::StoreGroupAndCacheTask::Run() {
DCHECK(!success_);
sql::Connection* connection = database_->db_connection();
@@ -437,6 +485,8 @@
if (!transaction.Begin())
return;
+ int64 old_origin_usage = database_->GetOriginUsage(group_record_.origin);
+
AppCacheDatabase::GroupRecord existing_group;
success_ = database_->FindGroup(group_record_.group_id, &existing_group);
if (!success_) {
@@ -494,11 +544,29 @@
if (!success_)
return;
- int64 quota = (quota_override_ >= 0) ?
- quota_override_ :
- database_->GetOriginQuota(group_record_.origin);
+ new_origin_usage_ = database_->GetOriginUsage(group_record_.origin);
- if (database_->GetOriginUsage(group_record_.origin) > quota) {
+ // Only check quota when the new usage exceeds the old usage.
+ if (new_origin_usage_ <= old_origin_usage) {
+ success_ = transaction.Commit();
+ return;
+ }
+
+ // Use a simple hard-coded value when not using quota management.
+ if (space_available_ == -1) {
+ if (new_origin_usage_ > kDefaultQuota) {
+ would_exceed_quota_ = true;
+ success_ = false;
+ return;
+ }
+ success_ = transaction.Commit();
+ return;
+ }
+
+ // Check limits based on the space availbable given to us via the
+ // quota system.
+ int64 delta = new_origin_usage_ - old_origin_usage;
+ if (delta > space_available_) {
would_exceed_quota_ = true;
success_ = false;
return;
@@ -509,7 +577,8 @@
void AppCacheStorageImpl::StoreGroupAndCacheTask::RunCompleted() {
if (success_) {
- storage_->origins_with_groups_.insert(group_->manifest_url().GetOrigin());
+ storage_->UpdateUsageMapAndNotify(
+ group_->manifest_url().GetOrigin(), new_origin_usage_);
if (cache_ != group_->newest_complete_cache()) {
cache_->set_complete(true);
group_->AddCache(cache_);
@@ -523,6 +592,9 @@
would_exceed_quota_));
group_ = NULL;
cache_ = NULL;
+
+ // TODO(michaeln): if (would_exceed_quota_) what if the current usage
+ // also exceeds the quota? http://crbug.com/83968
}
void AppCacheStorageImpl::StoreGroupAndCacheTask::CancelCompletion() {
@@ -837,15 +909,17 @@
scoped_refptr<AppCacheGroup> group_;
int64 group_id_;
+ GURL origin_;
bool success_;
- std::set<GURL> origins_with_groups_;
+ int64 new_origin_usage_;
std::vector<int64> newly_deletable_response_ids_;
};
AppCacheStorageImpl::MakeGroupObsoleteTask::MakeGroupObsoleteTask(
AppCacheStorageImpl* storage, AppCacheGroup* group)
: DatabaseTask(storage), group_(group), group_id_(group->group_id()),
- success_(false) {
+ origin_(group->manifest_url().GetOrigin()),
+ success_(false), new_origin_usage_(-1) {
}
void AppCacheStorageImpl::MakeGroupObsoleteTask::Run() {
@@ -861,10 +935,13 @@
AppCacheDatabase::GroupRecord group_record;
if (!database_->FindGroup(group_id_, &group_record)) {
// This group doesn't exists in the database, nothing todo here.
+ new_origin_usage_ = database_->GetOriginUsage(origin_);
success_ = true;
return;
}
+ DCHECK_EQ(group_record.origin, origin_);
+
AppCacheDatabase::CacheRecord cache_record;
if (database_->FindCacheForGroup(group_id_, &cache_record)) {
database_->FindResponseIdsForCacheAsVector(cache_record.cache_id,
@@ -881,16 +958,15 @@
success_ = database_->DeleteGroup(group_id_);
}
- success_ = success_ &&
- database_->FindOriginsWithGroups(&origins_with_groups_) &&
- transaction.Commit();
+ new_origin_usage_ = database_->GetOriginUsage(origin_);
+ success_ = success_ && transaction.Commit();
}
void AppCacheStorageImpl::MakeGroupObsoleteTask::RunCompleted() {
if (success_) {
group_->set_obsolete(true);
if (!storage_->is_disabled()) {
- storage_->origins_with_groups_.swap(origins_with_groups_);
+ storage_->UpdateUsageMapAndNotify(origin_, new_origin_usage_);
group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_);
// Also remove from the working set, caches for an 'obsolete' group
@@ -970,8 +1046,11 @@
: public DatabaseTask {
public:
UpdateGroupLastAccessTimeTask(
- AppCacheStorageImpl* storage, int64 group_id, base::Time time)
- : DatabaseTask(storage), group_id_(group_id), last_access_time_(time) {}
+ AppCacheStorageImpl* storage, AppCacheGroup* group, base::Time time)
+ : DatabaseTask(storage), group_id_(group->group_id()),
+ last_access_time_(time) {
+ storage->NotifyStorageAccessed(group->manifest_url().GetOrigin());
+ }
virtual void Run();
@@ -1002,6 +1081,9 @@
AppCacheStorageImpl::~AppCacheStorageImpl() {
STLDeleteElements(&pending_simple_tasks_);
+ std::for_each(pending_quota_queries_.begin(),
+ pending_quota_queries_.end(),
+ std::mem_fun(&DatabaseTask::CancelCompletion));
std::for_each(scheduled_database_tasks_.begin(),
scheduled_database_tasks_.end(),
std::mem_fun(&DatabaseTask::CancelCompletion));
@@ -1030,7 +1112,7 @@
return;
VLOG(1) << "Disabling appcache storage.";
is_disabled_ = true;
- origins_with_groups_.clear();
+ ClearUsageMapAndNotify();
working_set()->Disable();
if (disk_cache_.get())
disk_cache_->Disable();
@@ -1058,7 +1140,7 @@
if (cache->owning_group()) {
scoped_refptr<DatabaseTask> update_task(
new UpdateGroupLastAccessTimeTask(
- this, cache->owning_group()->group_id(), base::Time::Now()));
+ this, cache->owning_group(), base::Time::Now()));
update_task->Schedule();
}
return;
@@ -1087,7 +1169,7 @@
delegate->OnGroupLoaded(group, manifest_url);
scoped_refptr<DatabaseTask> update_task(
new UpdateGroupLastAccessTimeTask(
- this, group->group_id(), base::Time::Now()));
+ this, group, base::Time::Now()));
update_task->Schedule();
return;
}
@@ -1098,8 +1180,7 @@
return;
}
- if (origins_with_groups_.find(manifest_url.GetOrigin()) ==
- origins_with_groups_.end()) {
+ if (usage_map_.find(manifest_url.GetOrigin()) == usage_map_.end()) {
// No need to query the database, return a new group immediately.
scoped_refptr<AppCacheGroup> group(new AppCacheGroup(
service_, manifest_url, NewGroupId()));
@@ -1124,7 +1205,7 @@
scoped_refptr<StoreGroupAndCacheTask> task(
new StoreGroupAndCacheTask(this, group, newest_cache));
task->AddDelegate(GetOrCreateDelegateReference(delegate));
- task->Schedule();
+ task->GetQuotaThenSchedule();
}
void AppCacheStorageImpl::FindResponseForMainRequest(
@@ -1168,8 +1249,7 @@
}
}
- if (IsInitTaskComplete() &&
- origins_with_groups_.find(origin) == origins_with_groups_.end()) {
+ if (IsInitTaskComplete() && usage_map_.find(origin) == usage_map_.end()) {
// No need to query the database, return async'ly but without going thru
// the DB thread.
scoped_refptr<AppCacheGroup> no_group;
« no previous file with comments | « webkit/appcache/appcache_storage_impl.h ('k') | webkit/appcache/appcache_storage_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698