summaryrefslogtreecommitdiffstats
path: root/net/disk_cache/eviction.cc
diff options
context:
space:
mode:
authorrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-25 23:52:02 +0000
committerrvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-25 23:52:02 +0000
commitceb61da3987d8b7ed828c88daac779b1fbc8c6f9 (patch)
treebcbf1cdf1a3288ab7f1540bfa66f6d7742b6b154 /net/disk_cache/eviction.cc
parent472ce96a4b839814ed93c26d35d07c78de019b17 (diff)
downloadchromium_src-ceb61da3987d8b7ed828c88daac779b1fbc8c6f9.zip
chromium_src-ceb61da3987d8b7ed828c88daac779b1fbc8c6f9.tar.gz
chromium_src-ceb61da3987d8b7ed828c88daac779b1fbc8c6f9.tar.bz2
Disk cache: Prevent obscure file corruption and deal
with the result of that corruption. 1. Now we mark any open entry as dirty, even if we are supposed to delete the entry right away because if we crash before that, we may end up clearing the dirty flag of a dirty entry. 2. When we look for a parent of a given entry we now double check that the entry is the one that we want (and not just another entry with the same key). 3. If we have a loop on the hash collision list (result of failing to do 1 and 2 above), we figure that out. 4. Now every time we open an entry from an LRU list we end up using the same code path (with the proper handling of dirty entries). BUG=69135 TEST=net_unittests Review URL: http://codereview.chromium.org/6292011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72563 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/disk_cache/eviction.cc')
-rw-r--r--net/disk_cache/eviction.cc42
1 files changed, 27 insertions, 15 deletions
diff --git a/net/disk_cache/eviction.cc b/net/disk_cache/eviction.cc
index 0173c16..6ba053b 100644
--- a/net/disk_cache/eviction.cc
+++ b/net/disk_cache/eviction.cc
@@ -82,6 +82,7 @@ void Eviction::Init(BackendImpl* backend) {
delay_trim_ = false;
trim_delays_ = 0;
init_ = true;
+ test_mode_ = false;
in_experiment_ = (header_->experiment == EXPERIMENT_DELETED_LIST_IN);
}
@@ -125,11 +126,13 @@ void Eviction::TrimCache(bool empty) {
// This entry is not being used by anybody.
// Do NOT use node as an iterator after this point.
rankings_->TrackRankingsBlock(node.get(), false);
- if (!EvictEntry(node.get(), empty))
+ if (!EvictEntry(node.get(), empty) && !test_mode_)
continue;
if (!empty) {
backend_->OnEvent(Stats::TRIM_ENTRY);
+ if (test_mode_)
+ break;
if ((TimeTicks::Now() - start).InMilliseconds() > 20) {
MessageLoop::current()->PostTask(FROM_HERE,
@@ -182,6 +185,15 @@ void Eviction::OnDestroyEntry(EntryImpl* entry) {
return OnDestroyEntryV2(entry);
}
+void Eviction::SetTestMode() {
+ test_mode_ = true;
+}
+
+void Eviction::TrimDeletedList(bool empty) {
+ DCHECK(test_mode_ && new_eviction_);
+ TrimDeleted(empty);
+}
+
void Eviction::PostDelayedTrim() {
// Prevent posting multiple tasks.
if (delay_trim_)
@@ -242,7 +254,7 @@ Rankings::List Eviction::GetListForEntry(EntryImpl* entry) {
}
bool Eviction::EvictEntry(CacheRankingsBlock* node, bool empty) {
- EntryImpl* entry = backend_->GetEnumeratedEntry(node, true);
+ EntryImpl* entry = backend_->GetEnumeratedEntry(node);
if (!entry) {
Trace("NewEntry failed on Trim 0x%x", node->address().value());
return false;
@@ -320,9 +332,12 @@ void Eviction::TrimCacheV2(bool empty) {
// This entry is not being used by anybody.
// Do NOT use node as an iterator after this point.
rankings_->TrackRankingsBlock(node.get(), false);
- if (!EvictEntry(node.get(), empty))
+ if (!EvictEntry(node.get(), empty) && !test_mode_)
continue;
+ if (!empty && test_mode_)
+ break;
+
if (!empty && (TimeTicks::Now() - start).InMilliseconds() > 20) {
MessageLoop::current()->PostTask(FROM_HERE,
factory_.NewRunnableMethod(&Eviction::TrimCache, false));
@@ -336,7 +351,8 @@ void Eviction::TrimCacheV2(bool empty) {
if (empty) {
TrimDeleted(true);
- } else if (header_->lru.sizes[Rankings::DELETED] > header_->num_entries / 4) {
+ } else if (header_->lru.sizes[Rankings::DELETED] > header_->num_entries / 4 &&
+ !test_mode_) {
MessageLoop::current()->PostTask(FROM_HERE,
factory_.NewRunnableMethod(&Eviction::TrimDeleted, empty));
}
@@ -451,6 +467,8 @@ void Eviction::TrimDeleted(bool empty) {
node.reset(next.release());
next.reset(rankings_->GetPrev(node.get(), Rankings::DELETED));
deleted |= RemoveDeletedNode(node.get());
+ if (test_mode_)
+ break;
}
// Normally we use 25% for each list. The experiment doubles the number of
@@ -459,10 +477,11 @@ void Eviction::TrimDeleted(bool empty) {
// lists intact.
int max_length = in_experiment_ ? header_->num_entries * 2 / 5 :
header_->num_entries / 4;
- if (deleted && !empty &&
- header_->lru.sizes[Rankings::DELETED] > max_length)
+ if (deleted && !empty && !test_mode_ &&
+ header_->lru.sizes[Rankings::DELETED] > max_length) {
MessageLoop::current()->PostTask(FROM_HERE,
factory_.NewRunnableMethod(&Eviction::TrimDeleted, false));
+ }
CACHE_UMA(AGE_MS, "TotalTrimDeletedTime", 0, start);
Trace("*** Trim Deleted end ***");
@@ -470,19 +489,12 @@ void Eviction::TrimDeleted(bool empty) {
}
bool Eviction::RemoveDeletedNode(CacheRankingsBlock* node) {
- EntryImpl* entry;
- bool dirty;
- if (backend_->NewEntry(Addr(node->Data()->contents), &entry, &dirty)) {
+ EntryImpl* entry = backend_->GetEnumeratedEntry(node);
+ if (!entry) {
Trace("NewEntry failed on Trim 0x%x", node->address().value());
return false;
}
- // TODO(rvargas): figure out how to deal with corruption at this point (dirty
- // entries that live in this list).
- if (node->Data()->dirty) {
- // We ignore the failure; we're removing the entry anyway.
- entry->Update();
- }
bool doomed = (entry->entry()->Data()->state == ENTRY_DOOMED);
entry->entry()->Data()->state = ENTRY_DOOMED;
entry->DoomImpl();