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 "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
8 #include "googleurl/src/gurl.h" | 8 #include "googleurl/src/gurl.h" |
9 #include "webkit/quota/quota_manager.h" | 9 #include "webkit/quota/quota_manager.h" |
10 | 10 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
57 (*statistics)["errors-on-getting-usage-and-quota"] = | 57 (*statistics)["errors-on-getting-usage-and-quota"] = |
58 statistics_.num_errors_on_getting_usage_and_quota; | 58 statistics_.num_errors_on_getting_usage_and_quota; |
59 (*statistics)["evicted-origins"] = | 59 (*statistics)["evicted-origins"] = |
60 statistics_.num_evicted_origins; | 60 statistics_.num_evicted_origins; |
61 (*statistics)["eviction-rounds"] = | 61 (*statistics)["eviction-rounds"] = |
62 statistics_.num_eviction_rounds; | 62 statistics_.num_eviction_rounds; |
63 (*statistics)["skipped-eviction-rounds"] = | 63 (*statistics)["skipped-eviction-rounds"] = |
64 statistics_.num_skipped_eviction_rounds; | 64 statistics_.num_skipped_eviction_rounds; |
65 } | 65 } |
66 | 66 |
67 void QuotaTemporaryStorageEvictor::ReportHistogram() { | 67 void QuotaTemporaryStorageEvictor::ReportPerRoundHistogram() { |
68 UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnEvictingOrigin", | 68 base::Time now = base::Time::Now(); |
69 UMA_HISTOGRAM_TIMES("Quota.TimeSpentToAEvictionRound", | |
70 now - round_statistics_.start_time); | |
71 if (!time_of_end_of_last_round_.is_null()) | |
72 UMA_HISTOGRAM_MINUTES("Quota.TimeDeltaOfEvictionRounds", | |
73 now - time_of_end_of_last_round_); | |
74 UMA_HISTOGRAM_MBYTES("Quota.AmountOfOverageOfTemporaryGlobalStorage", | |
75 round_statistics_.amount_of_usage_overage); | |
76 UMA_HISTOGRAM_MBYTES("Quota.AmountOfShortageOfDiskspace", | |
77 round_statistics_.amount_of_diskspace_shortage); | |
78 UMA_HISTOGRAM_MBYTES("Quota.EvictedBytesPerRound", | |
79 round_statistics_.usage_on_beginning_of_round - | |
80 round_statistics_.usage_on_end_of_round); | |
81 UMA_HISTOGRAM_COUNTS("Quota.NumberOfEvictedOriginsPerRound", | |
82 round_statistics_.num_evicted_origins); | |
83 round_statistics_ = EvictionRoundStatistics(); | |
84 } | |
85 | |
86 void QuotaTemporaryStorageEvictor::ReportPerHourHistogram() { | |
87 UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnEvictingOriginPerHour", | |
69 statistics_.num_errors_on_evicting_origin); | 88 statistics_.num_errors_on_evicting_origin); |
70 UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnGettingUsageAndQuota", | 89 UMA_HISTOGRAM_COUNTS("Quota.ErrorsOnGettingUsageAndQuotaPerHour", |
71 statistics_.num_errors_on_getting_usage_and_quota); | 90 statistics_.num_errors_on_getting_usage_and_quota); |
72 UMA_HISTOGRAM_COUNTS("Quota.EvictedOrigins", | 91 UMA_HISTOGRAM_COUNTS("Quota.EvictedOriginsPerHour", |
73 statistics_.num_evicted_origins); | 92 statistics_.num_evicted_origins); |
74 UMA_HISTOGRAM_COUNTS("Quota.EvictionRounds", | 93 UMA_HISTOGRAM_COUNTS("Quota.EvictionRoundsPerHour", |
75 statistics_.num_eviction_rounds); | 94 statistics_.num_eviction_rounds); |
76 UMA_HISTOGRAM_COUNTS("Quota.SkippedEvictionRounds", | 95 UMA_HISTOGRAM_COUNTS("Quota.SkippedEvictionRoundsPerHour", |
77 statistics_.num_skipped_eviction_rounds); | 96 statistics_.num_skipped_eviction_rounds); |
97 statistics_ = Statistics(); | |
Dai Mikurube (NOT FULLTIME)
2011/08/11 09:17:19
Values in statistics_ are used not only for histog
tzik
2011/08/12 01:24:29
Done.
| |
98 } | |
78 | 99 |
79 statistics_ = Statistics(); | 100 void QuotaTemporaryStorageEvictor::OnEvictionRoundStarted() { |
101 if (round_statistics_.started) | |
102 return; | |
103 round_statistics_.started = true; | |
104 round_statistics_.start_time = base::Time::Now(); | |
105 ++statistics_.num_eviction_rounds; | |
106 } | |
107 | |
108 void QuotaTemporaryStorageEvictor::OnEvictionRoundFinished() { | |
109 // Check if skipped round | |
110 if (round_statistics_.num_evicted_origins) { | |
111 ReportPerRoundHistogram(); | |
112 time_of_last_nonskipped_round_ = base::Time::Now(); | |
113 } else { | |
114 ++statistics_.num_skipped_eviction_rounds; | |
115 round_statistics_ = EvictionRoundStatistics(); | |
116 } | |
80 } | 117 } |
81 | 118 |
82 void QuotaTemporaryStorageEvictor::Start() { | 119 void QuotaTemporaryStorageEvictor::Start() { |
83 DCHECK(CalledOnValidThread()); | 120 DCHECK(CalledOnValidThread()); |
84 StartEvictionTimerWithDelay(0); | 121 StartEvictionTimerWithDelay(0); |
85 | 122 |
86 if (histogram_timer_.IsRunning()) | 123 if (histogram_timer_.IsRunning()) |
87 return; | 124 return; |
88 histogram_timer_.Start(kHistogramReportInterval, this, | 125 histogram_timer_.Start(kHistogramReportInterval, this, |
89 &QuotaTemporaryStorageEvictor::ReportHistogram); | 126 &QuotaTemporaryStorageEvictor::ReportPerHourHistogram); |
90 } | 127 } |
91 | 128 |
92 void QuotaTemporaryStorageEvictor::StartEvictionTimerWithDelay(int delay_ms) { | 129 void QuotaTemporaryStorageEvictor::StartEvictionTimerWithDelay(int delay_ms) { |
93 if (eviction_timer_.IsRunning()) | 130 if (eviction_timer_.IsRunning()) |
94 return; | 131 return; |
95 num_evicted_origins_in_round_ = 0; | |
96 usage_on_beginning_of_round_ = -1; | |
97 time_of_beginning_of_round_ = base::Time::Now(); | |
98 ++statistics_.num_eviction_rounds; | |
99 eviction_timer_.Start(base::TimeDelta::FromMilliseconds(delay_ms), this, | 132 eviction_timer_.Start(base::TimeDelta::FromMilliseconds(delay_ms), this, |
100 &QuotaTemporaryStorageEvictor::ConsiderEviction); | 133 &QuotaTemporaryStorageEvictor::ConsiderEviction); |
101 } | 134 } |
102 | 135 |
103 void QuotaTemporaryStorageEvictor::ConsiderEviction() { | 136 void QuotaTemporaryStorageEvictor::ConsiderEviction() { |
137 OnEvictionRoundStarted(); | |
138 | |
104 // Get usage and disk space, then continue. | 139 // Get usage and disk space, then continue. |
105 quota_eviction_handler_->GetUsageAndQuotaForEviction(callback_factory_. | 140 quota_eviction_handler_->GetUsageAndQuotaForEviction(callback_factory_. |
106 NewCallback( | 141 NewCallback( |
107 &QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction)); | 142 &QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction)); |
108 } | 143 } |
109 | 144 |
110 void QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction( | 145 void QuotaTemporaryStorageEvictor::OnGotUsageAndQuotaForEviction( |
111 QuotaStatusCode status, | 146 QuotaStatusCode status, |
112 int64 usage, | 147 int64 usage, |
113 int64 unlimited_usage, | 148 int64 unlimited_usage, |
114 int64 quota, | 149 int64 quota, |
115 int64 available_disk_space) { | 150 int64 available_disk_space) { |
116 DCHECK(CalledOnValidThread()); | 151 DCHECK(CalledOnValidThread()); |
117 DCHECK_GE(usage, unlimited_usage); // unlimited_usage is a subset of usage | 152 DCHECK_GE(usage, unlimited_usage); // unlimited_usage is a subset of usage |
118 | 153 |
119 usage -= unlimited_usage; | 154 usage -= unlimited_usage; |
120 | 155 |
121 if (status != kQuotaStatusOk) | 156 if (status != kQuotaStatusOk) |
122 ++statistics_.num_errors_on_getting_usage_and_quota; | 157 ++statistics_.num_errors_on_getting_usage_and_quota; |
123 | 158 |
124 int64 amount_to_evict = std::max( | 159 int64 amount_of_usage_overage = std::max( |
125 usage - static_cast<int64>(quota * kUsageRatioToStartEviction), | 160 static_cast<int64>(0), |
161 usage - static_cast<int64>(quota * kUsageRatioToStartEviction)); | |
162 round_statistics_.put_usage_overage(amount_of_usage_overage); | |
163 | |
164 int64 amount_of_diskspace_shortage = std::max( | |
165 static_cast<int64>(0), | |
126 min_available_disk_space_to_start_eviction_ - available_disk_space); | 166 min_available_disk_space_to_start_eviction_ - available_disk_space); |
167 round_statistics_.put_diskspace_shortage(amount_of_diskspace_shortage); | |
168 round_statistics_.put_usage(usage); | |
169 | |
170 int64 amount_to_evict = std::max(amount_of_usage_overage, | |
171 amount_of_diskspace_shortage); | |
127 if (status == kQuotaStatusOk && amount_to_evict > 0) { | 172 if (status == kQuotaStatusOk && amount_to_evict > 0) { |
128 // Space is getting tight. Get the least recently used origin and continue. | 173 // Space is getting tight. Get the least recently used origin and continue. |
129 // TODO(michaeln): if the reason for eviction is low physical disk space, | 174 // TODO(michaeln): if the reason for eviction is low physical disk space, |
130 // make 'unlimited' origins subject to eviction too. | 175 // make 'unlimited' origins subject to eviction too. |
131 | |
132 if (usage_on_beginning_of_round_ < 0) { | |
133 usage_on_beginning_of_round_ = usage; | |
134 UMA_HISTOGRAM_MBYTES("Quota.TemporaryStorageSizeToEvict", | |
135 amount_to_evict); | |
136 } | |
137 | |
138 quota_eviction_handler_->GetLRUOrigin(kStorageTypeTemporary, | 176 quota_eviction_handler_->GetLRUOrigin(kStorageTypeTemporary, |
139 callback_factory_.NewCallback( | 177 callback_factory_.NewCallback( |
140 &QuotaTemporaryStorageEvictor::OnGotLRUOrigin)); | 178 &QuotaTemporaryStorageEvictor::OnGotLRUOrigin)); |
141 } else if (repeated_eviction_) { | 179 } else { |
142 // No action required, sleep for a while and check again later. | 180 if (repeated_eviction_) { |
143 if (num_evicted_origins_in_round_ == 0) { | 181 // No action required, sleep for a while and check again later. |
144 ++statistics_.num_skipped_eviction_rounds; | 182 if (statistics_.num_errors_on_getting_usage_and_quota < |
145 } else if (usage_on_beginning_of_round_ >= 0) { | 183 kThresholdOfErrorsToStopEviction) { |
146 int64 evicted_bytes = usage_on_beginning_of_round_ - usage; | 184 StartEvictionTimerWithDelay(interval_ms_); |
147 base::Time now = base::Time::Now(); | 185 } else { |
148 UMA_HISTOGRAM_MBYTES("Quota.EvictedBytesPerRound", evicted_bytes); | 186 // TODO(dmikurube): Try restarting eviction after a while. |
149 UMA_HISTOGRAM_COUNTS("Quota.NumberOfEvictedOriginsPerRound", | 187 LOG(WARNING) << "Stopped eviction of temporary storage due to errors " |
150 num_evicted_origins_in_round_); | 188 "in GetUsageAndQuotaForEviction."; |
151 UMA_HISTOGRAM_TIMES("Quota.TimeSpentToAEvictionRound", | |
152 now - time_of_beginning_of_round_); | |
153 if (!time_of_end_of_last_round_.is_null()) { | |
154 UMA_HISTOGRAM_MINUTES("Quota.TimeDeltaOfEvictionRounds", | |
155 now - time_of_end_of_last_round_); | |
156 } | 189 } |
157 time_of_end_of_last_round_ = now; | |
158 } | 190 } |
159 if (statistics_.num_errors_on_getting_usage_and_quota < | 191 OnEvictionRoundFinished(); |
160 kThresholdOfErrorsToStopEviction) { | |
161 StartEvictionTimerWithDelay(interval_ms_); | |
162 } else { | |
163 // TODO(dmikurube): Try restarting eviction after a while. | |
164 LOG(WARNING) << "Stopped eviction of temporary storage due to errors " | |
165 "in GetUsageAndQuotaForEviction."; | |
166 } | |
167 } | 192 } |
168 | 193 |
169 // TODO(dmikurube): Add error handling for the case status != kQuotaStatusOk. | 194 // TODO(dmikurube): Add error handling for the case status != kQuotaStatusOk. |
170 } | 195 } |
171 | 196 |
172 void QuotaTemporaryStorageEvictor::OnGotLRUOrigin(const GURL& origin) { | 197 void QuotaTemporaryStorageEvictor::OnGotLRUOrigin(const GURL& origin) { |
173 DCHECK(CalledOnValidThread()); | 198 DCHECK(CalledOnValidThread()); |
174 | 199 |
175 if (origin.is_empty()) { | 200 if (origin.is_empty()) { |
176 if (repeated_eviction_) | 201 if (repeated_eviction_) |
177 StartEvictionTimerWithDelay(interval_ms_); | 202 StartEvictionTimerWithDelay(interval_ms_); |
203 OnEvictionRoundFinished(); | |
178 return; | 204 return; |
179 } | 205 } |
180 | 206 |
181 quota_eviction_handler_->EvictOriginData(origin, kStorageTypeTemporary, | 207 quota_eviction_handler_->EvictOriginData(origin, kStorageTypeTemporary, |
182 callback_factory_.NewCallback( | 208 callback_factory_.NewCallback( |
183 &QuotaTemporaryStorageEvictor::OnEvictionComplete)); | 209 &QuotaTemporaryStorageEvictor::OnEvictionComplete)); |
184 } | 210 } |
185 | 211 |
186 void QuotaTemporaryStorageEvictor::OnEvictionComplete( | 212 void QuotaTemporaryStorageEvictor::OnEvictionComplete( |
187 QuotaStatusCode status) { | 213 QuotaStatusCode status) { |
188 DCHECK(CalledOnValidThread()); | 214 DCHECK(CalledOnValidThread()); |
189 | 215 |
190 // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is | 216 // Just calling ConsiderEviction() or StartEvictionTimerWithDelay() here is |
191 // ok. No need to deal with the case that all of the Delete operations fail | 217 // ok. No need to deal with the case that all of the Delete operations fail |
192 // for a certain origin. It doesn't result in trying to evict the same | 218 // for a certain origin. It doesn't result in trying to evict the same |
193 // origin permanently. The evictor skips origins which had deletion errors | 219 // origin permanently. The evictor skips origins which had deletion errors |
194 // a few times. | 220 // a few times. |
195 | 221 |
196 if (status == kQuotaStatusOk) { | 222 if (status == kQuotaStatusOk) { |
197 ++statistics_.num_evicted_origins; | 223 ++statistics_.num_evicted_origins; |
198 ++num_evicted_origins_in_round_; | 224 ++round_statistics_.num_evicted_origins; |
199 // We many need to get rid of more space so reconsider immediately. | 225 // We many need to get rid of more space so reconsider immediately. |
200 ConsiderEviction(); | 226 ConsiderEviction(); |
201 } else { | 227 } else { |
202 ++statistics_.num_errors_on_evicting_origin; | 228 ++statistics_.num_errors_on_evicting_origin; |
203 if (repeated_eviction_) { | 229 if (repeated_eviction_) { |
204 // Sleep for a while and retry again until we see too many errors. | 230 // Sleep for a while and retry again until we see too many errors. |
205 StartEvictionTimerWithDelay(interval_ms_); | 231 StartEvictionTimerWithDelay(interval_ms_); |
206 } | 232 } |
233 OnEvictionRoundFinished(); | |
207 } | 234 } |
208 } | 235 } |
209 | 236 |
210 } // namespace quota | 237 } // namespace quota |
OLD | NEW |