Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: net/disk_cache/eviction.cc

Issue 155951: Disk cache: Fix handling of invalid entries that are detected... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/disk_cache/backend_unittest.cc ('k') | net/disk_cache/rankings.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 // The eviction policy is a very simple pure LRU, so the elements at the end of 5 // The eviction policy is a very simple pure LRU, so the elements at the end of
6 // the list are evicted until kCleanUpMargin free space is available. There is 6 // the list are evicted until kCleanUpMargin free space is available. There is
7 // only one list in use (Rankings::NO_USE), and elements are sent to the front 7 // only one list in use (Rankings::NO_USE), and elements are sent to the front
8 // of the list whenever they are accessed. 8 // of the list whenever they are accessed.
9 9
10 // The new (in-development) eviction policy ads re-use as a factor to evict 10 // The new (in-development) eviction policy ads re-use as a factor to evict
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 new_eviction_ = backend->new_eviction_; 66 new_eviction_ = backend->new_eviction_;
67 first_trim_ = true; 67 first_trim_ = true;
68 trimming_ = false; 68 trimming_ = false;
69 delay_trim_ = false; 69 delay_trim_ = false;
70 } 70 }
71 71
72 void Eviction::TrimCache(bool empty) { 72 void Eviction::TrimCache(bool empty) {
73 if (new_eviction_) 73 if (new_eviction_)
74 return TrimCacheV2(empty); 74 return TrimCacheV2(empty);
75 75
76 Trace("*** Trim Cache ***");
77 if (backend_->disabled_ || trimming_) 76 if (backend_->disabled_ || trimming_)
78 return; 77 return;
79 78
80 if (!empty && backend_->IsLoaded()) 79 if (!empty && backend_->IsLoaded())
81 return PostDelayedTrim(); 80 return PostDelayedTrim();
82 81
82 Trace("*** Trim Cache ***");
83 trimming_ = true; 83 trimming_ = true;
84 Time start = Time::Now(); 84 Time start = Time::Now();
85 Rankings::ScopedRankingsBlock node(rankings_); 85 Rankings::ScopedRankingsBlock node(rankings_);
86 Rankings::ScopedRankingsBlock next(rankings_, 86 Rankings::ScopedRankingsBlock next(rankings_,
87 rankings_->GetPrev(node.get(), Rankings::NO_USE)); 87 rankings_->GetPrev(node.get(), Rankings::NO_USE));
88 DCHECK(next.get());
89 int target_size = empty ? 0 : max_size_; 88 int target_size = empty ? 0 : max_size_;
90 while (header_->num_bytes > target_size && next.get()) { 89 while (header_->num_bytes > target_size && next.get()) {
90 // The iterator could be invalidated within EvictEntry().
91 if (!next->HasData())
92 break;
91 node.reset(next.release()); 93 node.reset(next.release());
92 next.reset(rankings_->GetPrev(node.get(), Rankings::NO_USE)); 94 next.reset(rankings_->GetPrev(node.get(), Rankings::NO_USE));
93 if (!node->Data()->pointer || empty) { 95 if (!node->Data()->pointer || empty) {
94 // This entry is not being used by anybody. 96 // This entry is not being used by anybody.
97 // Do NOT use node as an iterator after this point.
98 rankings_->TrackRankingsBlock(node.get(), false);
95 if (!EvictEntry(node.get(), empty)) 99 if (!EvictEntry(node.get(), empty))
96 continue; 100 continue;
97 101
98 if (!empty) { 102 if (!empty) {
99 backend_->OnEvent(Stats::TRIM_ENTRY); 103 backend_->OnEvent(Stats::TRIM_ENTRY);
100 104
101 if ((Time::Now() - start).InMilliseconds() > 20) { 105 if ((Time::Now() - start).InMilliseconds() > 20) {
102 MessageLoop::current()->PostTask(FROM_HERE, 106 MessageLoop::current()->PostTask(FROM_HERE,
103 factory_.NewRunnableMethod(&Eviction::TrimCache, false)); 107 factory_.NewRunnableMethod(&Eviction::TrimCache, false));
104 break; 108 break;
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 header_->create_time = Time::FromLocalExploded(old).ToInternalValue(); 188 header_->create_time = Time::FromLocalExploded(old).ToInternalValue();
185 } 189 }
186 } 190 }
187 } 191 }
188 192
189 Rankings::List Eviction::GetListForEntry(EntryImpl* entry) { 193 Rankings::List Eviction::GetListForEntry(EntryImpl* entry) {
190 return Rankings::NO_USE; 194 return Rankings::NO_USE;
191 } 195 }
192 196
193 bool Eviction::EvictEntry(CacheRankingsBlock* node, bool empty) { 197 bool Eviction::EvictEntry(CacheRankingsBlock* node, bool empty) {
194 EntryImpl* entry; 198 EntryImpl* entry = backend_->GetEnumeratedEntry(node, true);
195 bool dirty; 199 if (!entry) {
196 if (backend_->NewEntry(Addr(node->Data()->contents), &entry, &dirty)) {
197 Trace("NewEntry failed on Trim 0x%x", node->address().value()); 200 Trace("NewEntry failed on Trim 0x%x", node->address().value());
198 return false; 201 return false;
199 } 202 }
200 203
201 if (node->Data()->pointer) {
202 // We ignore the failure; we're removing the entry anyway.
203 entry->Update();
204 }
205 ReportTrimTimes(entry); 204 ReportTrimTimes(entry);
206 if (empty || !new_eviction_) { 205 if (empty || !new_eviction_) {
207 entry->Doom(); 206 entry->Doom();
208 } else { 207 } else {
209 entry->DeleteEntryData(false); 208 entry->DeleteEntryData(false);
210 EntryStore* info = entry->entry()->Data(); 209 EntryStore* info = entry->entry()->Data();
211 DCHECK(ENTRY_NORMAL == info->state); 210 DCHECK(ENTRY_NORMAL == info->state);
212 211
213 rankings_->Remove(entry->rankings(), GetListForEntryV2(entry)); 212 rankings_->Remove(entry->rankings(), GetListForEntryV2(entry));
214 info->state = ENTRY_EVICTED; 213 info->state = ENTRY_EVICTED;
215 entry->entry()->Store(); 214 entry->entry()->Store();
216 rankings_->Insert(entry->rankings(), true, Rankings::DELETED); 215 rankings_->Insert(entry->rankings(), true, Rankings::DELETED);
217 backend_->OnEvent(Stats::TRIM_ENTRY); 216 backend_->OnEvent(Stats::TRIM_ENTRY);
218 } 217 }
219 entry->Release(); 218 entry->Release();
220 219
221 return true; 220 return true;
222 } 221 }
223 222
224 // ----------------------------------------------------------------------- 223 // -----------------------------------------------------------------------
225 224
226 void Eviction::TrimCacheV2(bool empty) { 225 void Eviction::TrimCacheV2(bool empty) {
227 Trace("*** Trim Cache ***");
228 if (backend_->disabled_ || trimming_) 226 if (backend_->disabled_ || trimming_)
229 return; 227 return;
230 228
231 if (!empty && backend_->IsLoaded()) 229 if (!empty && backend_->IsLoaded())
232 return PostDelayedTrim(); 230 return PostDelayedTrim();
233 231
232 Trace("*** Trim Cache ***");
234 trimming_ = true; 233 trimming_ = true;
235 Time start = Time::Now(); 234 Time start = Time::Now();
236 235
237 const int kListsToSearch = 3; 236 const int kListsToSearch = 3;
238 Rankings::ScopedRankingsBlock next[kListsToSearch]; 237 Rankings::ScopedRankingsBlock next[kListsToSearch];
239 int list = Rankings::LAST_ELEMENT; 238 int list = Rankings::LAST_ELEMENT;
240 239
241 // Get a node from each list. 240 // Get a node from each list.
242 for (int i = 0; i < kListsToSearch; i++) { 241 for (int i = 0; i < kListsToSearch; i++) {
243 bool done = false; 242 bool done = false;
(...skipping 19 matching lines...) Expand all
263 } 262 }
264 263
265 if (empty) 264 if (empty)
266 list = 0; 265 list = 0;
267 266
268 Rankings::ScopedRankingsBlock node(rankings_); 267 Rankings::ScopedRankingsBlock node(rankings_);
269 268
270 int target_size = empty ? 0 : max_size_; 269 int target_size = empty ? 0 : max_size_;
271 for (; list < kListsToSearch; list++) { 270 for (; list < kListsToSearch; list++) {
272 while (header_->num_bytes > target_size && next[list].get()) { 271 while (header_->num_bytes > target_size && next[list].get()) {
272 // The iterator could be invalidated within EvictEntry().
273 if (!next[list]->HasData())
274 break;
273 node.reset(next[list].release()); 275 node.reset(next[list].release());
274 next[list].reset(rankings_->GetPrev(node.get(), 276 next[list].reset(rankings_->GetPrev(node.get(),
275 static_cast<Rankings::List>(list))); 277 static_cast<Rankings::List>(list)));
276 if (!node->Data()->pointer || empty) { 278 if (!node->Data()->pointer || empty) {
277 // This entry is not being used by anybody. 279 // This entry is not being used by anybody.
280 // Do NOT use node as an iterator after this point.
281 rankings_->TrackRankingsBlock(node.get(), false);
278 if (!EvictEntry(node.get(), empty)) 282 if (!EvictEntry(node.get(), empty))
279 continue; 283 continue;
280 284
281 if (!empty && (Time::Now() - start).InMilliseconds() > 20) { 285 if (!empty && (Time::Now() - start).InMilliseconds() > 20) {
282 MessageLoop::current()->PostTask(FROM_HERE, 286 MessageLoop::current()->PostTask(FROM_HERE,
283 factory_.NewRunnableMethod(&Eviction::TrimCache, false)); 287 factory_.NewRunnableMethod(&Eviction::TrimCache, false));
284 break; 288 break;
285 } 289 }
286 } 290 }
287 } 291 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 } 416 }
413 417
414 bool Eviction::RemoveDeletedNode(CacheRankingsBlock* node) { 418 bool Eviction::RemoveDeletedNode(CacheRankingsBlock* node) {
415 EntryImpl* entry; 419 EntryImpl* entry;
416 bool dirty; 420 bool dirty;
417 if (backend_->NewEntry(Addr(node->Data()->contents), &entry, &dirty)) { 421 if (backend_->NewEntry(Addr(node->Data()->contents), &entry, &dirty)) {
418 Trace("NewEntry failed on Trim 0x%x", node->address().value()); 422 Trace("NewEntry failed on Trim 0x%x", node->address().value());
419 return false; 423 return false;
420 } 424 }
421 425
426 // TODO(rvargas): figure out how to deal with corruption at this point (dirty
427 // entries that live in this list).
422 if (node->Data()->pointer) { 428 if (node->Data()->pointer) {
423 // We ignore the failure; we're removing the entry anyway. 429 // We ignore the failure; we're removing the entry anyway.
424 entry->Update(); 430 entry->Update();
425 } 431 }
426 entry->entry()->Data()->state = ENTRY_DOOMED; 432 entry->entry()->Data()->state = ENTRY_DOOMED;
427 entry->Doom(); 433 entry->Doom();
428 entry->Release(); 434 entry->Release();
429 return true; 435 return true;
430 } 436 }
431 437
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 Time::FromInternalValue(last2.get()->Data()->last_used)); 479 Time::FromInternalValue(last2.get()->Data()->last_used));
474 if (last3.get()) 480 if (last3.get())
475 CACHE_UMA(AGE, "HighUseAge", header_->experiment, 481 CACHE_UMA(AGE, "HighUseAge", header_->experiment,
476 Time::FromInternalValue(last3.get()->Data()->last_used)); 482 Time::FromInternalValue(last3.get()->Data()->last_used));
477 if (last4.get()) 483 if (last4.get())
478 CACHE_UMA(AGE, "DeletedAge", header_->experiment, 484 CACHE_UMA(AGE, "DeletedAge", header_->experiment,
479 Time::FromInternalValue(last4.get()->Data()->last_used)); 485 Time::FromInternalValue(last4.get()->Data()->last_used));
480 } 486 }
481 487
482 } // namespace disk_cache 488 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/backend_unittest.cc ('k') | net/disk_cache/rankings.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698