| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/quota/quota_temporary_storage_evictor.h" | 5 #include "webkit/quota/quota_temporary_storage_evictor.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 8 |
| 9 #include "base/bind.h" |
| 7 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 8 #include "googleurl/src/gurl.h" | 11 #include "googleurl/src/gurl.h" |
| 9 #include "webkit/quota/quota_manager.h" | 12 #include "webkit/quota/quota_manager.h" |
| 10 | 13 |
| 11 #define UMA_HISTOGRAM_MBYTES(name, sample) \ | 14 #define UMA_HISTOGRAM_MBYTES(name, sample) \ |
| 12 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 15 UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 13 (name), static_cast<int>((sample) / kMBytes), \ | 16 (name), static_cast<int>((sample) / kMBytes), \ |
| 14 1, 10 * 1024 * 1024 /* 10TB */, 100) | 17 1, 10 * 1024 * 1024 /* 10TB */, 100) |
| 15 | 18 |
| 16 #define UMA_HISTOGRAM_MINUTES(name, sample) \ | 19 #define UMA_HISTOGRAM_MINUTES(name, sample) \ |
| (...skipping 17 matching lines...) Expand all Loading... |
| 34 base::TimeDelta::FromMilliseconds(60 * 60 * 1000); // 1 hour | 37 base::TimeDelta::FromMilliseconds(60 * 60 * 1000); // 1 hour |
| 35 | 38 |
| 36 QuotaTemporaryStorageEvictor::QuotaTemporaryStorageEvictor( | 39 QuotaTemporaryStorageEvictor::QuotaTemporaryStorageEvictor( |
| 37 QuotaEvictionHandler* quota_eviction_handler, | 40 QuotaEvictionHandler* quota_eviction_handler, |
| 38 int64 interval_ms) | 41 int64 interval_ms) |
| 39 : min_available_disk_space_to_start_eviction_( | 42 : min_available_disk_space_to_start_eviction_( |
| 40 kDefaultMinAvailableDiskSpaceToStartEviction), | 43 kDefaultMinAvailableDiskSpaceToStartEviction), |
| 41 quota_eviction_handler_(quota_eviction_handler), | 44 quota_eviction_handler_(quota_eviction_handler), |
| 42 interval_ms_(interval_ms), | 45 interval_ms_(interval_ms), |
| 43 repeated_eviction_(true), | 46 repeated_eviction_(true), |
| 44 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 47 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 45 DCHECK(quota_eviction_handler); | 48 DCHECK(quota_eviction_handler); |
| 46 } | 49 } |
| 47 | 50 |
| 48 QuotaTemporaryStorageEvictor::~QuotaTemporaryStorageEvictor() { | 51 QuotaTemporaryStorageEvictor::~QuotaTemporaryStorageEvictor() { |
| 49 } | 52 } |
| 50 | 53 |
| 51 void QuotaTemporaryStorageEvictor::GetStatistics( | 54 void QuotaTemporaryStorageEvictor::GetStatistics( |
| 52 std::map<std::string, int64>* statistics) { | 55 std::map<std::string, int64>* statistics) { |
| 53 DCHECK(statistics); | 56 DCHECK(statistics); |
| 54 | 57 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 if (eviction_timer_.IsRunning()) | 139 if (eviction_timer_.IsRunning()) |
| 137 return; | 140 return; |
| 138 eviction_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms), | 141 eviction_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms), |
| 139 this, &QuotaTemporaryStorageEvictor::ConsiderEviction); | 142 this, &QuotaTemporaryStorageEvictor::ConsiderEviction); |
| 140 } | 143 } |
| 141 | 144 |
| 142 void QuotaTemporaryStorageEvictor::ConsiderEviction() { | 145 void QuotaTemporaryStorageEvictor::ConsiderEviction() { |
| 143 OnEvictionRoundStarted(); | 146 OnEvictionRoundStarted(); |
| 144 | 147 |
| 145 // Get usage and disk space, then continue. | 148 // Get usage and disk space, then continue. |
| 146 quota_eviction_handler_->GetUsageAndQuotaForEviction(callback_factory_. | 149 quota_eviction_handler_->GetUsageAndQuotaForEviction( |
| 147 NewCallback( | 150 base::Bind(&QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction, |
| 148 &QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction)); | 151 weak_factory_.GetWeakPtr())); |
| 149 } | 152 } |
| 150 | 153 |
| 151 void QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction( | 154 void QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction( |
| 152 QuotaStatusCode status, | 155 QuotaStatusCode status, |
| 153 int64 usage, | 156 int64 usage, |
| 154 int64 unlimited_usage, | 157 int64 unlimited_usage, |
| 155 int64 quota, | 158 int64 quota, |
| 156 int64 available_disk_space) { | 159 int64 available_disk_space) { |
| 157 DCHECK(CalledOnValidThread()); | 160 DCHECK(CalledOnValidThread()); |
| 158 DCHECK_GE(usage, unlimited_usage); // unlimited_usage is a subset of usage | 161 DCHECK_GE(usage, unlimited_usage); // unlimited_usage is a subset of usage |
| (...skipping 18 matching lines...) Expand all Loading... |
| 177 round_statistics_.is_initialized = true; | 180 round_statistics_.is_initialized = true; |
| 178 } | 181 } |
| 179 round_statistics_.usage_on_end_of_round = usage; | 182 round_statistics_.usage_on_end_of_round = usage; |
| 180 | 183 |
| 181 int64 amount_to_evict = std::max(usage_overage, diskspace_shortage); | 184 int64 amount_to_evict = std::max(usage_overage, diskspace_shortage); |
| 182 if (status == kQuotaStatusOk && amount_to_evict > 0) { | 185 if (status == kQuotaStatusOk && amount_to_evict > 0) { |
| 183 // Space is getting tight. Get the least recently used origin and continue. | 186 // Space is getting tight. Get the least recently used origin and continue. |
| 184 // TODO(michaeln): if the reason for eviction is low physical disk space, | 187 // TODO(michaeln): if the reason for eviction is low physical disk space, |
| 185 // make 'unlimited' origins subject to eviction too. | 188 // make 'unlimited' origins subject to eviction too. |
| 186 quota_eviction_handler_->GetLRUOrigin(kStorageTypeTemporary, | 189 quota_eviction_handler_->GetLRUOrigin(kStorageTypeTemporary, |
| 187 callback_factory_.NewCallback( | 190 base::Bind(&QuotaTemporaryStorageEvictor::OnGotLRUOrigin, |
| 188 &QuotaTemporaryStorageEvictor::OnGotLRUOrigin)); | 191 weak_factory_.GetWeakPtr())); |
| 189 } else { | 192 } else { |
| 190 if (repeated_eviction_) { | 193 if (repeated_eviction_) { |
| 191 // No action required, sleep for a while and check again later. | 194 // No action required, sleep for a while and check again later. |
| 192 if (statistics_.num_errors_on_getting_usage_and_quota < | 195 if (statistics_.num_errors_on_getting_usage_and_quota < |
| 193 kThresholdOfErrorsToStopEviction) { | 196 kThresholdOfErrorsToStopEviction) { |
| 194 StartEvictionTimerWithDelay(interval_ms_); | 197 StartEvictionTimerWithDelay(interval_ms_); |
| 195 } else { | 198 } else { |
| 196 // TODO(dmikurube): Try restarting eviction after a while. | 199 // TODO(dmikurube): Try restarting eviction after a while. |
| 197 LOG(WARNING) << "Stopped eviction of temporary storage due to errors " | 200 LOG(WARNING) << "Stopped eviction of temporary storage due to errors " |
| 198 "in GetUsageAndQuotaForEviction."; | 201 "in GetUsageAndQuotaForEviction."; |
| 199 } | 202 } |
| 200 } | 203 } |
| 201 OnEvictionRoundFinished(); | 204 OnEvictionRoundFinished(); |
| 202 } | 205 } |
| 203 | 206 |
| 204 // TODO(dmikurube): Add error handling for the case status != kQuotaStatusOk. | 207 // TODO(dmikurube): Add error handling for the case status != kQuotaStatusOk. |
| 205 } | 208 } |
| 206 | 209 |
| 207 void QuotaTemporaryStorageEvictor::OnGotLRUOrigin(const GURL& origin) { | 210 void QuotaTemporaryStorageEvictor::OnGotLRUOrigin(const GURL& origin) { |
| 208 DCHECK(CalledOnValidThread()); | 211 DCHECK(CalledOnValidThread()); |
| 209 | 212 |
| 210 if (origin.is_empty()) { | 213 if (origin.is_empty()) { |
| 211 if (repeated_eviction_) | 214 if (repeated_eviction_) |
| 212 StartEvictionTimerWithDelay(interval_ms_); | 215 StartEvictionTimerWithDelay(interval_ms_); |
| 213 OnEvictionRoundFinished(); | 216 OnEvictionRoundFinished(); |
| 214 return; | 217 return; |
| 215 } | 218 } |
| 216 | 219 |
| 217 quota_eviction_handler_->EvictOriginData(origin, kStorageTypeTemporary, | 220 quota_eviction_handler_->EvictOriginData(origin, kStorageTypeTemporary, |
| 218 callback_factory_.NewCallback( | 221 base::Bind( |
| 219 &QuotaTemporaryStorageEvictor::OnEvictionComplete)); | 222 &QuotaTemporaryStorageEvictor::OnEvictionComplete, |
| 223 weak_factory_.GetWeakPtr())); |
| 220 } | 224 } |
| 221 | 225 |
| 222 void QuotaTemporaryStorageEvictor::OnEvictionComplete( | 226 void QuotaTemporaryStorageEvictor::OnEvictionComplete( |
| 223 QuotaStatusCode status) { | 227 QuotaStatusCode status) { |
| 224 DCHECK(CalledOnValidThread()); | 228 DCHECK(CalledOnValidThread()); |
| 225 | 229 |
| 226 // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is | 230 // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is |
| 227 // ok. No need to deal with the case that all of the Delete operations fail | 231 // ok. No need to deal with the case that all of the Delete operations fail |
| 228 // for a certain origin. It doesn't result in trying to evict the same | 232 // for a certain origin. It doesn't result in trying to evict the same |
| 229 // origin permanently. The evictor skips origins which had deletion errors | 233 // origin permanently. The evictor skips origins which had deletion errors |
| 230 // a few times. | 234 // a few times. |
| 231 | 235 |
| 232 if (status == kQuotaStatusOk) { | 236 if (status == kQuotaStatusOk) { |
| 233 ++statistics_.num_evicted_origins; | 237 ++statistics_.num_evicted_origins; |
| 234 ++round_statistics_.num_evicted_origins_in_round; | 238 ++round_statistics_.num_evicted_origins_in_round; |
| 235 // We many need to get rid of more space so reconsider immediately. | 239 // We many need to get rid of more space so reconsider immediately. |
| 236 ConsiderEviction(); | 240 ConsiderEviction(); |
| 237 } else { | 241 } else { |
| 238 ++statistics_.num_errors_on_evicting_origin; | 242 ++statistics_.num_errors_on_evicting_origin; |
| 239 if (repeated_eviction_) { | 243 if (repeated_eviction_) { |
| 240 // Sleep for a while and retry again until we see too many errors. | 244 // Sleep for a while and retry again until we see too many errors. |
| 241 StartEvictionTimerWithDelay(interval_ms_); | 245 StartEvictionTimerWithDelay(interval_ms_); |
| 242 } | 246 } |
| 243 OnEvictionRoundFinished(); | 247 OnEvictionRoundFinished(); |
| 244 } | 248 } |
| 245 } | 249 } |
| 246 | 250 |
| 247 } // namespace quota | 251 } // namespace quota |
| OLD | NEW |