| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "webkit/browser/quota/quota_temporary_storage_evictor.h" | 5 #include "storage/browser/quota/quota_temporary_storage_evictor.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "url/gurl.h" | 11 #include "url/gurl.h" |
| 12 #include "webkit/browser/quota/quota_manager.h" | 12 #include "storage/browser/quota/quota_manager.h" |
| 13 | 13 |
| 14 #define UMA_HISTOGRAM_MBYTES(name, sample) \ | 14 #define UMA_HISTOGRAM_MBYTES(name, sample) \ |
| 15 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 15 UMA_HISTOGRAM_CUSTOM_COUNTS((name), \ |
| 16 (name), static_cast<int>((sample) / kMBytes), \ | 16 static_cast<int>((sample) / kMBytes), \ |
| 17 1, 10 * 1024 * 1024 /* 10TB */, 100) | 17 1, \ |
| 18 10 * 1024 * 1024 /* 10TB */, \ |
| 19 100) |
| 18 | 20 |
| 19 #define UMA_HISTOGRAM_MINUTES(name, sample) \ | 21 #define UMA_HISTOGRAM_MINUTES(name, sample) \ |
| 20 UMA_HISTOGRAM_CUSTOM_TIMES( \ | 22 UMA_HISTOGRAM_CUSTOM_TIMES((name), \ |
| 21 (name), (sample), \ | 23 (sample), \ |
| 22 base::TimeDelta::FromMinutes(1), \ | 24 base::TimeDelta::FromMinutes(1), \ |
| 23 base::TimeDelta::FromDays(1), 50) | 25 base::TimeDelta::FromDays(1), \ |
| 26 50) |
| 24 | 27 |
| 25 namespace { | 28 namespace { |
| 26 const int64 kMBytes = 1024 * 1024; | 29 const int64 kMBytes = 1024 * 1024; |
| 27 const double kUsageRatioToStartEviction = 0.7; | 30 const double kUsageRatioToStartEviction = 0.7; |
| 28 const int kThresholdOfErrorsToStopEviction = 5; | 31 const int kThresholdOfErrorsToStopEviction = 5; |
| 29 const int kHistogramReportIntervalMinutes = 60; | 32 const int kHistogramReportIntervalMinutes = 60; |
| 30 } | 33 } |
| 31 | 34 |
| 32 namespace quota { | 35 namespace quota { |
| 33 | 36 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 60 } | 63 } |
| 61 | 64 |
| 62 void QuotaTemporaryStorageEvictor::GetStatistics( | 65 void QuotaTemporaryStorageEvictor::GetStatistics( |
| 63 std::map<std::string, int64>* statistics) { | 66 std::map<std::string, int64>* statistics) { |
| 64 DCHECK(statistics); | 67 DCHECK(statistics); |
| 65 | 68 |
| 66 (*statistics)["errors-on-evicting-origin"] = | 69 (*statistics)["errors-on-evicting-origin"] = |
| 67 statistics_.num_errors_on_evicting_origin; | 70 statistics_.num_errors_on_evicting_origin; |
| 68 (*statistics)["errors-on-getting-usage-and-quota"] = | 71 (*statistics)["errors-on-getting-usage-and-quota"] = |
| 69 statistics_.num_errors_on_getting_usage_and_quota; | 72 statistics_.num_errors_on_getting_usage_and_quota; |
| 70 (*statistics)["evicted-origins"] = | 73 (*statistics)["evicted-origins"] = statistics_.num_evicted_origins; |
| 71 statistics_.num_evicted_origins; | 74 (*statistics)["eviction-rounds"] = statistics_.num_eviction_rounds; |
| 72 (*statistics)["eviction-rounds"] = | |
| 73 statistics_.num_eviction_rounds; | |
| 74 (*statistics)["skipped-eviction-rounds"] = | 75 (*statistics)["skipped-eviction-rounds"] = |
| 75 statistics_.num_skipped_eviction_rounds; | 76 statistics_.num_skipped_eviction_rounds; |
| 76 } | 77 } |
| 77 | 78 |
| 78 void QuotaTemporaryStorageEvictor::ReportPerRoundHistogram() { | 79 void QuotaTemporaryStorageEvictor::ReportPerRoundHistogram() { |
| 79 DCHECK(round_statistics_.in_round); | 80 DCHECK(round_statistics_.in_round); |
| 80 DCHECK(round_statistics_.is_initialized); | 81 DCHECK(round_statistics_.is_initialized); |
| 81 | 82 |
| 82 base::Time now = base::Time::Now(); | 83 base::Time now = base::Time::Now(); |
| 83 UMA_HISTOGRAM_TIMES("Quota.TimeSpentToAEvictionRound", | 84 UMA_HISTOGRAM_TIMES("Quota.TimeSpentToAEvictionRound", |
| 84 now - round_statistics_.start_time); | 85 now - round_statistics_.start_time); |
| 85 if (!time_of_end_of_last_round_.is_null()) | 86 if (!time_of_end_of_last_round_.is_null()) |
| 86 UMA_HISTOGRAM_MINUTES("Quota.TimeDeltaOfEvictionRounds", | 87 UMA_HISTOGRAM_MINUTES("Quota.TimeDeltaOfEvictionRounds", |
| 87 now - time_of_end_of_last_round_); | 88 now - time_of_end_of_last_round_); |
| 88 UMA_HISTOGRAM_MBYTES("Quota.UsageOverageOfTemporaryGlobalStorage", | 89 UMA_HISTOGRAM_MBYTES("Quota.UsageOverageOfTemporaryGlobalStorage", |
| 89 round_statistics_.usage_overage_at_round); | 90 round_statistics_.usage_overage_at_round); |
| 90 UMA_HISTOGRAM_MBYTES("Quota.DiskspaceShortage", | 91 UMA_HISTOGRAM_MBYTES("Quota.DiskspaceShortage", |
| 91 round_statistics_.diskspace_shortage_at_round); | 92 round_statistics_.diskspace_shortage_at_round); |
| 92 UMA_HISTOGRAM_MBYTES("Quota.EvictedBytesPerRound", | 93 UMA_HISTOGRAM_MBYTES("Quota.EvictedBytesPerRound", |
| 93 round_statistics_.usage_on_beginning_of_round - | 94 round_statistics_.usage_on_beginning_of_round - |
| 94 round_statistics_.usage_on_end_of_round); | 95 round_statistics_.usage_on_end_of_round); |
| 95 UMA_HISTOGRAM_COUNTS("Quota.NumberOfEvictedOriginsPerRound", | 96 UMA_HISTOGRAM_COUNTS("Quota.NumberOfEvictedOriginsPerRound", |
| 96 round_statistics_.num_evicted_origins_in_round); | 97 round_statistics_.num_evicted_origins_in_round); |
| 97 } | 98 } |
| 98 | 99 |
| 99 void QuotaTemporaryStorageEvictor::ReportPerHourHistogram() { | 100 void QuotaTemporaryStorageEvictor::ReportPerHourHistogram() { |
| 100 Statistics stats_in_hour(statistics_); | 101 Statistics stats_in_hour(statistics_); |
| 101 stats_in_hour.subtract_assign(previous_statistics_); | 102 stats_in_hour.subtract_assign(previous_statistics_); |
| 102 previous_statistics_ = statistics_; | 103 previous_statistics_ = statistics_; |
| 103 | 104 |
| 104 UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnEvictingOriginPerHour", | 105 UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnEvictingOriginPerHour", |
| (...skipping 29 matching lines...) Expand all Loading... |
| 134 } | 135 } |
| 135 | 136 |
| 136 void QuotaTemporaryStorageEvictor::Start() { | 137 void QuotaTemporaryStorageEvictor::Start() { |
| 137 DCHECK(CalledOnValidThread()); | 138 DCHECK(CalledOnValidThread()); |
| 138 StartEvictionTimerWithDelay(0); | 139 StartEvictionTimerWithDelay(0); |
| 139 | 140 |
| 140 if (histogram_timer_.IsRunning()) | 141 if (histogram_timer_.IsRunning()) |
| 141 return; | 142 return; |
| 142 | 143 |
| 143 histogram_timer_.Start( | 144 histogram_timer_.Start( |
| 144 FROM_HERE, base::TimeDelta::FromMinutes(kHistogramReportIntervalMinutes), | 145 FROM_HERE, |
| 145 this, &QuotaTemporaryStorageEvictor::ReportPerHourHistogram); | 146 base::TimeDelta::FromMinutes(kHistogramReportIntervalMinutes), |
| 147 this, |
| 148 &QuotaTemporaryStorageEvictor::ReportPerHourHistogram); |
| 146 } | 149 } |
| 147 | 150 |
| 148 void QuotaTemporaryStorageEvictor::StartEvictionTimerWithDelay(int delay_ms) { | 151 void QuotaTemporaryStorageEvictor::StartEvictionTimerWithDelay(int delay_ms) { |
| 149 if (eviction_timer_.IsRunning()) | 152 if (eviction_timer_.IsRunning()) |
| 150 return; | 153 return; |
| 151 eviction_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms), | 154 eviction_timer_.Start(FROM_HERE, |
| 152 this, &QuotaTemporaryStorageEvictor::ConsiderEviction); | 155 base::TimeDelta::FromMilliseconds(delay_ms), |
| 156 this, |
| 157 &QuotaTemporaryStorageEvictor::ConsiderEviction); |
| 153 } | 158 } |
| 154 | 159 |
| 155 void QuotaTemporaryStorageEvictor::ConsiderEviction() { | 160 void QuotaTemporaryStorageEvictor::ConsiderEviction() { |
| 156 OnEvictionRoundStarted(); | 161 OnEvictionRoundStarted(); |
| 157 | 162 |
| 158 // Get usage and disk space, then continue. | 163 // Get usage and disk space, then continue. |
| 159 quota_eviction_handler_->GetUsageAndQuotaForEviction( | 164 quota_eviction_handler_->GetUsageAndQuotaForEviction( |
| 160 base::Bind(&QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction, | 165 base::Bind(&QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction, |
| 161 weak_factory_.GetWeakPtr())); | 166 weak_factory_.GetWeakPtr())); |
| 162 } | 167 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 void QuotaTemporaryStorageEvictor::OnGotLRUOrigin(const GURL& origin) { | 225 void QuotaTemporaryStorageEvictor::OnGotLRUOrigin(const GURL& origin) { |
| 221 DCHECK(CalledOnValidThread()); | 226 DCHECK(CalledOnValidThread()); |
| 222 | 227 |
| 223 if (origin.is_empty()) { | 228 if (origin.is_empty()) { |
| 224 if (repeated_eviction_) | 229 if (repeated_eviction_) |
| 225 StartEvictionTimerWithDelay(interval_ms_); | 230 StartEvictionTimerWithDelay(interval_ms_); |
| 226 OnEvictionRoundFinished(); | 231 OnEvictionRoundFinished(); |
| 227 return; | 232 return; |
| 228 } | 233 } |
| 229 | 234 |
| 230 quota_eviction_handler_->EvictOriginData(origin, kStorageTypeTemporary, | 235 quota_eviction_handler_->EvictOriginData( |
| 231 base::Bind( | 236 origin, |
| 232 &QuotaTemporaryStorageEvictor::OnEvictionComplete, | 237 kStorageTypeTemporary, |
| 233 weak_factory_.GetWeakPtr())); | 238 base::Bind(&QuotaTemporaryStorageEvictor::OnEvictionComplete, |
| 239 weak_factory_.GetWeakPtr())); |
| 234 } | 240 } |
| 235 | 241 |
| 236 void QuotaTemporaryStorageEvictor::OnEvictionComplete( | 242 void QuotaTemporaryStorageEvictor::OnEvictionComplete(QuotaStatusCode status) { |
| 237 QuotaStatusCode status) { | |
| 238 DCHECK(CalledOnValidThread()); | 243 DCHECK(CalledOnValidThread()); |
| 239 | 244 |
| 240 // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is | 245 // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is |
| 241 // ok. No need to deal with the case that all of the Delete operations fail | 246 // ok. No need to deal with the case that all of the Delete operations fail |
| 242 // for a certain origin. It doesn't result in trying to evict the same | 247 // for a certain origin. It doesn't result in trying to evict the same |
| 243 // origin permanently. The evictor skips origins which had deletion errors | 248 // origin permanently. The evictor skips origins which had deletion errors |
| 244 // a few times. | 249 // a few times. |
| 245 | 250 |
| 246 if (status == kQuotaStatusOk) { | 251 if (status == kQuotaStatusOk) { |
| 247 ++statistics_.num_evicted_origins; | 252 ++statistics_.num_evicted_origins; |
| 248 ++round_statistics_.num_evicted_origins_in_round; | 253 ++round_statistics_.num_evicted_origins_in_round; |
| 249 // We many need to get rid of more space so reconsider immediately. | 254 // We many need to get rid of more space so reconsider immediately. |
| 250 ConsiderEviction(); | 255 ConsiderEviction(); |
| 251 } else { | 256 } else { |
| 252 ++statistics_.num_errors_on_evicting_origin; | 257 ++statistics_.num_errors_on_evicting_origin; |
| 253 if (repeated_eviction_) { | 258 if (repeated_eviction_) { |
| 254 // Sleep for a while and retry again until we see too many errors. | 259 // Sleep for a while and retry again until we see too many errors. |
| 255 StartEvictionTimerWithDelay(interval_ms_); | 260 StartEvictionTimerWithDelay(interval_ms_); |
| 256 } | 261 } |
| 257 OnEvictionRoundFinished(); | 262 OnEvictionRoundFinished(); |
| 258 } | 263 } |
| 259 } | 264 } |
| 260 | 265 |
| 261 } // namespace quota | 266 } // namespace quota |
| OLD | NEW |