summaryrefslogtreecommitdiffstats
path: root/storage
diff options
context:
space:
mode:
authorcalamity <calamity@chromium.org>2015-10-19 17:24:42 -0700
committerCommit bot <commit-bot@chromium.org>2015-10-20 00:25:32 +0000
commit9c79f8034ba1029a359be35be1ef0f95bcf72647 (patch)
tree54d82cd2fbe1f27af6593ff7cec4781aa575bfee /storage
parent392396974b125f81324e3af4ed5579a934fa9ed6 (diff)
downloadchromium_src-9c79f8034ba1029a359be35be1ef0f95bcf72647.zip
chromium_src-9c79f8034ba1029a359be35be1ef0f95bcf72647.tar.gz
chromium_src-9c79f8034ba1029a359be35be1ef0f95bcf72647.tar.bz2
Add Quota.TimeSinceOriginEvicted UMA histogram.
This CL adds a UMA histogram that tracks the amount of time since an origin last had its temporary storage evicted. The last eviction time data is stored by adding a table to the QuotaManager database which tracks the last eviction time for an origin. BUG=542075 Review URL: https://codereview.chromium.org/1403673002 Cr-Commit-Position: refs/heads/master@{#354932}
Diffstat (limited to 'storage')
-rw-r--r--storage/browser/quota/quota_database.cc115
-rw-r--r--storage/browser/quota/quota_database.h8
-rw-r--r--storage/browser/quota/quota_manager.cc92
-rw-r--r--storage/browser/quota/quota_manager.h12
4 files changed, 183 insertions, 44 deletions
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc
index aff5602..f1fefb6 100644
--- a/storage/browser/quota/quota_database.cc
+++ b/storage/browser/quota/quota_database.cc
@@ -21,11 +21,12 @@ namespace {
// Definitions for database schema.
-const int kCurrentVersion = 4;
+const int kCurrentVersion = 5;
const int kCompatibleVersion = 2;
const char kHostQuotaTable[] = "HostQuotaTable";
const char kOriginInfoTable[] = "OriginInfoTable";
+const char kEvictionInfoTable[] = "EvictionInfoTable";
const char kIsOriginTableBootstrapped[] = "IsOriginTableBootstrapped";
bool VerifyValidQuotaConfig(const char* key) {
@@ -62,19 +63,23 @@ const char QuotaDatabase::kTemporaryQuotaOverrideKey[] =
"TemporaryQuotaOverride";
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))" },
-};
+ {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))"},
+ {kEvictionInfoTable,
+ "(origin TEXT NOT NULL,"
+ " type INTEGER NOT NULL,"
+ " last_eviction_time INTEGER DEFAULT 0,"
+ " UNIQUE(origin, type))"}};
// static
const QuotaDatabase::IndexSchema QuotaDatabase::kIndexes[] = {
@@ -264,6 +269,71 @@ bool QuotaDatabase::SetOriginLastModifiedTime(
return true;
}
+bool QuotaDatabase::GetOriginLastEvictionTime(const GURL& origin,
+ StorageType type,
+ base::Time* last_modified_time) {
+ DCHECK(last_modified_time);
+ if (!LazyOpen(false))
+ return false;
+
+ const char kSql[] =
+ "SELECT last_eviction_time"
+ " FROM EvictionInfoTable"
+ " WHERE origin = ? AND type = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindString(0, origin.spec());
+ statement.BindInt(1, static_cast<int>(type));
+
+ if (!statement.Step())
+ return statement.Succeeded();
+
+ *last_modified_time = base::Time::FromInternalValue(statement.ColumnInt64(0));
+ return true;
+}
+
+bool QuotaDatabase::SetOriginLastEvictionTime(const GURL& origin,
+ StorageType type,
+ base::Time last_modified_time) {
+ if (!LazyOpen(true))
+ return false;
+
+ const char kSql[] =
+ "INSERT OR REPLACE INTO EvictionInfoTable"
+ " (last_eviction_time, origin, type)"
+ " VALUES (?, ?, ?)";
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ 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::DeleteOriginLastEvictionTime(const GURL& origin,
+ StorageType type) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char kSql[] =
+ "DELETE FROM EvictionInfoTable"
+ " WHERE origin = ? AND type = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindString(0, origin.spec());
+ statement.BindInt(1, 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))
@@ -617,6 +687,23 @@ bool QuotaDatabase::UpgradeSchema(int current_version) {
return false;
}
Commit();
+
+ return true;
+ } else if (current_version < 5) {
+ const QuotaDatabase::TableSchema& eviction_table_schema = kTables[2];
+ DCHECK_EQ(strcmp(kEvictionInfoTable, eviction_table_schema.table_name), 0);
+
+ std::string sql("CREATE TABLE ");
+ sql += eviction_table_schema.table_name;
+ sql += eviction_table_schema.columns;
+ if (!db_->Execute(sql.c_str())) {
+ VLOG(1) << "Failed to execute " << sql;
+ return false;
+ }
+
+ meta_table_->SetVersionNumber(5);
+ Commit();
+
return true;
}
return false;
diff --git a/storage/browser/quota/quota_database.h b/storage/browser/quota/quota_database.h
index 02a76fc..09e90b3 100644
--- a/storage/browser/quota/quota_database.h
+++ b/storage/browser/quota/quota_database.h
@@ -58,6 +58,14 @@ class STORAGE_EXPORT_PRIVATE QuotaDatabase {
StorageType type,
base::Time last_modified_time);
+ bool GetOriginLastEvictionTime(const GURL& origin,
+ StorageType type,
+ base::Time* last_eviction_time);
+ bool SetOriginLastEvictionTime(const GURL& origin,
+ StorageType type,
+ base::Time last_eviction_time);
+ bool DeleteOriginLastEvictionTime(const GURL& origin, StorageType type);
+
// Register initial |origins| info |type| to the database.
// This method is assumed to be called only after the installation or
// the database schema reset.
diff --git a/storage/browser/quota/quota_manager.cc b/storage/browser/quota/quota_manager.cc
index c2ccb26..3187621 100644
--- a/storage/browser/quota/quota_manager.cc
+++ b/storage/browser/quota/quota_manager.cc
@@ -74,6 +74,9 @@ int64 QuotaManager::kMinimumPreserveForSystem = 1024 * kMBytes;
const int QuotaManager::kEvictionIntervalInMilliSeconds =
30 * kMinutesInMilliSeconds;
+const char QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram[] =
+ "Quota.TimeBetweenRepeatedOriginEvictions";
+
// Heuristics: assuming average cloud server allows a few Gigs storage
// on the server side and the storage needs to be shared for user data
// and by multiple apps.
@@ -153,9 +156,29 @@ bool GetLRUOriginOnDBThread(StorageType type,
bool DeleteOriginInfoOnDBThread(const GURL& origin,
StorageType type,
+ bool is_eviction,
QuotaDatabase* database) {
DCHECK(database);
- return database->DeleteOriginInfo(origin, type);
+ if (!database->DeleteOriginInfo(origin, type))
+ return false;
+
+ // If the deletion is not due to an eviction, delete the entry in the eviction
+ // table as well due to privacy concerns.
+ if (!is_eviction)
+ return database->DeleteOriginLastEvictionTime(origin, type);
+
+ base::Time last_eviction_time;
+ if (!database->GetOriginLastEvictionTime(origin, type, &last_eviction_time))
+ return false;
+
+ base::Time now = base::Time::Now();
+ if (last_eviction_time != base::Time()) {
+ UMA_HISTOGRAM_LONG_TIMES(
+ QuotaManager::kTimeBetweenRepeatedOriginEvictionsHistogram,
+ now - last_eviction_time);
+ }
+
+ return database->SetOriginLastEvictionTime(origin, type, now);
}
bool InitializeTemporaryOriginsInfoOnDBThread(const std::set<GURL>* origins,
@@ -551,6 +574,7 @@ class QuotaManager::OriginDataDeleter : public QuotaTask {
const GURL& origin,
StorageType type,
int quota_client_mask,
+ bool is_eviction,
const StatusCallback& callback)
: QuotaTask(manager),
origin_(origin),
@@ -559,6 +583,7 @@ class QuotaManager::OriginDataDeleter : public QuotaTask {
error_count_(0),
remaining_clients_(-1),
skipped_clients_(0),
+ is_eviction_(is_eviction),
callback_(callback),
weak_factory_(this) {}
@@ -588,7 +613,7 @@ class QuotaManager::OriginDataDeleter : public QuotaTask {
// Only remove the entire origin if we didn't skip any client types.
if (skipped_clients_ == 0)
- manager()->DeleteOriginFromDatabase(origin_, type_);
+ manager()->DeleteOriginFromDatabase(origin_, type_, is_eviction_);
callback_.Run(kQuotaStatusOk);
} else {
// crbug.com/349708
@@ -625,6 +650,7 @@ class QuotaManager::OriginDataDeleter : public QuotaTask {
int error_count_;
int remaining_clients_;
int skipped_clients_;
+ bool is_eviction_;
StatusCallback callback_;
base::WeakPtrFactory<OriginDataDeleter> weak_factory_;
@@ -700,11 +726,10 @@ class QuotaManager::HostDataDeleter : public QuotaTask {
for (std::set<GURL>::const_iterator p = origins_.begin();
p != origins_.end();
++p) {
- OriginDataDeleter* deleter =
- new OriginDataDeleter(
- manager(), *p, type_, quota_client_mask_,
- base::Bind(&HostDataDeleter::DidDeleteOriginData,
- weak_factory_.GetWeakPtr()));
+ OriginDataDeleter* deleter = new OriginDataDeleter(
+ manager(), *p, type_, quota_client_mask_, false,
+ base::Bind(&HostDataDeleter::DidDeleteOriginData,
+ weak_factory_.GetWeakPtr()));
deleter->Start();
}
}
@@ -959,20 +984,11 @@ void QuotaManager::SetTemporaryStorageEvictionPolicy(
temporary_storage_eviction_policy_ = policy.Pass();
}
-void QuotaManager::DeleteOriginData(
- const GURL& origin, StorageType type, int quota_client_mask,
- const StatusCallback& callback) {
- LazyInitialize();
-
- if (origin.is_empty() || clients_.empty()) {
- callback.Run(kQuotaStatusOk);
- return;
- }
-
- DCHECK(origin == origin.GetOrigin());
- OriginDataDeleter* deleter =
- new OriginDataDeleter(this, origin, type, quota_client_mask, callback);
- deleter->Start();
+void QuotaManager::DeleteOriginData(const GURL& origin,
+ StorageType type,
+ int quota_client_mask,
+ const StatusCallback& callback) {
+ DeleteOriginDataInternal(origin, type, quota_client_mask, false, callback);
}
void QuotaManager::DeleteHostData(const std::string& host,
@@ -1390,17 +1406,17 @@ void QuotaManager::StartEviction() {
temporary_storage_evictor_->Start();
}
-void QuotaManager::DeleteOriginFromDatabase(
- const GURL& origin, StorageType type) {
+void QuotaManager::DeleteOriginFromDatabase(const GURL& origin,
+ StorageType type,
+ bool is_eviction) {
LazyInitialize();
if (db_disabled_)
return;
PostTaskAndReplyWithResultForDBThread(
FROM_HERE,
- base::Bind(&DeleteOriginInfoOnDBThread, origin, type),
- base::Bind(&QuotaManager::DidDatabaseWork,
- weak_factory_.GetWeakPtr()));
+ base::Bind(&DeleteOriginInfoOnDBThread, origin, type, is_eviction),
+ base::Bind(&QuotaManager::DidDatabaseWork, weak_factory_.GetWeakPtr()));
}
void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) {
@@ -1417,6 +1433,24 @@ void QuotaManager::DidOriginDataEvicted(QuotaStatusCode status) {
eviction_context_.evict_origin_data_callback.Reset();
}
+void QuotaManager::DeleteOriginDataInternal(const GURL& origin,
+ StorageType type,
+ int quota_client_mask,
+ bool is_eviction,
+ const StatusCallback& callback) {
+ LazyInitialize();
+
+ if (origin.is_empty() || clients_.empty()) {
+ callback.Run(kQuotaStatusOk);
+ return;
+ }
+
+ DCHECK(origin == origin.GetOrigin());
+ OriginDataDeleter* deleter = new OriginDataDeleter(
+ this, origin, type, quota_client_mask, is_eviction, callback);
+ deleter->Start();
+}
+
void QuotaManager::ReportHistogram() {
GetGlobalUsage(kStorageTypeTemporary,
base::Bind(
@@ -1521,9 +1555,9 @@ void QuotaManager::EvictOriginData(const GURL& origin,
eviction_context_.evicted_type = type;
eviction_context_.evict_origin_data_callback = callback;
- DeleteOriginData(origin, type, QuotaClient::kAllClientsMask,
- base::Bind(&QuotaManager::DidOriginDataEvicted,
- weak_factory_.GetWeakPtr()));
+ DeleteOriginDataInternal(origin, type, QuotaClient::kAllClientsMask, true,
+ base::Bind(&QuotaManager::DidOriginDataEvicted,
+ weak_factory_.GetWeakPtr()));
}
void QuotaManager::GetUsageAndQuotaForEviction(
diff --git a/storage/browser/quota/quota_manager.h b/storage/browser/quota/quota_manager.h
index 0e4884b..5780cbb 100644
--- a/storage/browser/quota/quota_manager.h
+++ b/storage/browser/quota/quota_manager.h
@@ -275,6 +275,8 @@ class STORAGE_EXPORT QuotaManager
static const int kEvictionIntervalInMilliSeconds;
+ static const char kTimeBetweenRepeatedOriginEvictionsHistogram[];
+
// These are kept non-const so that test code can change the value.
// TODO(kinuko): Make this a real const value and add a proper way to set
// the quota for syncable storage. (http://crbug.com/155488)
@@ -371,9 +373,17 @@ class STORAGE_EXPORT QuotaManager
void DumpQuotaTable(const DumpQuotaTableCallback& callback);
void DumpOriginInfoTable(const DumpOriginInfoTableCallback& callback);
+ void DeleteOriginDataInternal(const GURL& origin,
+ StorageType type,
+ int quota_client_mask,
+ bool is_eviction,
+ const StatusCallback& callback);
+
// Methods for eviction logic.
void StartEviction();
- void DeleteOriginFromDatabase(const GURL& origin, StorageType type);
+ void DeleteOriginFromDatabase(const GURL& origin,
+ StorageType type,
+ bool is_eviction);
void DidOriginDataEvicted(QuotaStatusCode status);