| 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 | 
|---|