Skip to content

Commit

Permalink
Disk cache: Update stress_cache to perform deeper testsing.
Browse files Browse the repository at this point in the history
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/8352013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106538 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
rvargas@google.com committed Oct 20, 2011
1 parent 794d83c commit ea9080b
Show file tree
Hide file tree
Showing 12 changed files with 242 additions and 39 deletions.
83 changes: 79 additions & 4 deletions net/disk_cache/backend_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@ int BackendImpl::Init(OldCompletionCallback* callback) {
}

int BackendImpl::SyncInit() {
#if defined(NET_BUILD_STRESS_CACHE)
// Start evictions right away.
up_ticks_ = kTrimDelay * 2;
#endif
DCHECK(!init_);
if (init_)
return net::ERR_FAILED;
Expand All @@ -476,6 +480,7 @@ int BackendImpl::SyncInit() {
}

init_ = true;
Trace("Init");

if (data_->header.experiment != NO_EXPERIMENT &&
cache_type_ != net::DISK_CACHE) {
Expand Down Expand Up @@ -531,6 +536,14 @@ int BackendImpl::SyncInit() {

disabled_ = !rankings_.Init(this, new_eviction_);

#if defined(STRESS_CACHE_EXTENDED_VALIDATION)
trace_object_->EnableTracing(false);
int sc = SelfCheck();
if (sc < 0 && sc != ERR_NUM_ENTRIES_MISMATCH)
NOTREACHED();
trace_object_->EnableTracing(true);
#endif

return disabled_ ? net::ERR_FAILED : net::OK;
}

Expand Down Expand Up @@ -931,8 +944,10 @@ void BackendImpl::UpdateRank(EntryImpl* entry, bool modified) {
void BackendImpl::RecoveredEntry(CacheRankingsBlock* rankings) {
Addr address(rankings->Data()->contents);
EntryImpl* cache_entry = NULL;
if (NewEntry(address, &cache_entry))
if (NewEntry(address, &cache_entry)) {
STRESS_NOTREACHED();
return;
}

uint32 hash = cache_entry->GetHash();
cache_entry->Release();
Expand Down Expand Up @@ -972,9 +987,44 @@ void BackendImpl::InternalDoomEntry(EntryImpl* entry) {
}
}

#if defined(NET_BUILD_STRESS_CACHE)

CacheAddr BackendImpl::GetNextAddr(Addr address) {
EntriesMap::iterator it = open_entries_.find(address.value());
if (it != open_entries_.end()) {
EntryImpl* this_entry = it->second;
return this_entry->GetNextAddress();
}
DCHECK(block_files_.IsValid(address));
DCHECK(!address.is_separate_file() && address.file_type() == BLOCK_256);

CacheEntryBlock entry(File(address), address);
CHECK(entry.Load());
return entry.Data()->next;
}

void BackendImpl::NotLinked(EntryImpl* entry) {
Addr entry_addr = entry->entry()->address();
uint32 i = entry->GetHash() & mask_;
Addr address(data_->table[i]);
if (!address.is_initialized())
return;

for (;;) {
DCHECK(entry_addr.value() != address.value());
address.set_value(GetNextAddr(address));
if (!address.is_initialized())
break;
}
}
#endif // NET_BUILD_STRESS_CACHE

// An entry may be linked on the DELETED list for a while after being doomed.
// This function is called when we want to remove it.
void BackendImpl::RemoveEntry(EntryImpl* entry) {
#if defined(NET_BUILD_STRESS_CACHE)
NotLinked(entry);
#endif
if (!new_eviction_)
return;

Expand Down Expand Up @@ -1147,6 +1197,7 @@ void BackendImpl::FirstEviction() {
}

void BackendImpl::CriticalError(int error) {
STRESS_NOTREACHED();
LOG(ERROR) << "Critical error found " << error;
if (disabled_)
return;
Expand All @@ -1166,6 +1217,8 @@ void BackendImpl::CriticalError(int error) {
}

void BackendImpl::ReportError(int error) {
STRESS_DCHECK(!error || error == ERR_PREVIOUS_CRASH);

// We transmit positive numbers, instead of direct error codes.
DCHECK_LE(error, 0);
CACHE_UMA(CACHE_ERROR, "Error", 0, error * -1);
Expand Down Expand Up @@ -1284,12 +1337,16 @@ int BackendImpl::SelfCheck() {
int num_entries = rankings_.SelfCheck();
if (num_entries < 0) {
LOG(ERROR) << "Invalid rankings list, error " << num_entries;
#if !defined(NET_BUILD_STRESS_CACHE)
return num_entries;
#endif
}

if (num_entries != data_->header.num_entries) {
LOG(ERROR) << "Number of entries mismatch";
#if !defined(NET_BUILD_STRESS_CACHE)
return ERR_NUM_ENTRIES_MISMATCH;
#endif
}

return CheckAllEntries();
Expand Down Expand Up @@ -1547,9 +1604,12 @@ int BackendImpl::NewEntry(Addr address, EntryImpl** entry) {
return 0;
}

STRESS_DCHECK(block_files_.IsValid(address));

if (!address.is_initialized() || address.is_separate_file() ||
address.file_type() != BLOCK_256) {
LOG(WARNING) << "Wrong entry address.";
STRESS_NOTREACHED();
return ERR_INVALID_ADDRESS;
}

Expand All @@ -1568,22 +1628,28 @@ int BackendImpl::NewEntry(Addr address, EntryImpl** entry) {

if (!cache_entry->SanityCheck()) {
LOG(WARNING) << "Messed up entry found.";
STRESS_NOTREACHED();
return ERR_INVALID_ENTRY;
}

STRESS_DCHECK(block_files_.IsValid(
Addr(cache_entry->entry()->Data()->rankings_node)));

if (!cache_entry->LoadNodeAddress())
return ERR_READ_FAILURE;

// Prevent overwriting the dirty flag on the destructor.
cache_entry->SetDirtyFlag(GetCurrentEntryId());

if (!rankings_.SanityCheck(cache_entry->rankings(), false)) {
STRESS_NOTREACHED();
cache_entry->SetDirtyFlag(0);
// Don't remove this from the list (it is not linked properly). Instead,
// break the link back to the entry because it is going away, and leave the
// rankings node to be deleted if we find it through a list.
rankings_.SetContents(cache_entry->rankings(), 0);
} else if (!rankings_.DataSanityCheck(cache_entry->rankings(), false)) {
STRESS_NOTREACHED();
cache_entry->SetDirtyFlag(0);
rankings_.SetContents(cache_entry->rankings(), address.value());
}
Expand Down Expand Up @@ -1816,6 +1882,7 @@ EntryImpl* BackendImpl::GetEnumeratedEntry(CacheRankingsBlock* next,
EntryImpl* entry;
int rv = NewEntry(Addr(next->Data()->contents), &entry);
if (rv) {
STRESS_NOTREACHED();
rankings_.Remove(next, list, false);
if (rv == ERR_INVALID_ADDRESS) {
// There is nothing linked from the index. Delete the rankings node.
Expand All @@ -1832,6 +1899,7 @@ EntryImpl* BackendImpl::GetEnumeratedEntry(CacheRankingsBlock* next,
}

if (!entry->Update()) {
STRESS_NOTREACHED();
entry->Release();
return NULL;
}
Expand Down Expand Up @@ -2069,12 +2137,14 @@ bool BackendImpl::CheckIndex() {

AdjustMaxCacheSize(data_->header.table_len);

#if !defined(NET_BUILD_STRESS_CACHE)
if (data_->header.num_bytes < 0 ||
(max_size_ < kint32max - kDefaultCacheSize &&
data_->header.num_bytes > max_size_ + kDefaultCacheSize)) {
LOG(ERROR) << "Invalid cache (current) size";
return false;
}
#endif

if (data_->header.num_entries < 0) {
LOG(ERROR) << "Invalid number of entries";
Expand All @@ -2093,15 +2163,17 @@ int BackendImpl::CheckAllEntries() {
int num_dirty = 0;
int num_entries = 0;
DCHECK(mask_ < kuint32max);
for (int i = 0; i <= static_cast<int>(mask_); i++) {
for (unsigned int i = 0; i <= mask_; i++) {
Addr address(data_->table[i]);
if (!address.is_initialized())
continue;
for (;;) {
EntryImpl* tmp;
int ret = NewEntry(address, &tmp);
if (ret)
if (ret) {
STRESS_NOTREACHED();
return ret;
}
scoped_refptr<EntryImpl> cache_entry;
cache_entry.swap(&tmp);

Expand All @@ -2112,6 +2184,7 @@ int BackendImpl::CheckAllEntries() {
else
return ERR_INVALID_ENTRY;

DCHECK_EQ(i, cache_entry->entry()->Data()->hash & mask_);
address.set_value(cache_entry->GetNextAddress());
if (!address.is_initialized())
break;
Expand All @@ -2120,7 +2193,9 @@ int BackendImpl::CheckAllEntries() {

Trace("CheckAllEntries End");
if (num_entries + num_dirty != data_->header.num_entries) {
LOG(ERROR) << "Number of entries mismatch";
LOG(ERROR) << "Number of entries " << num_entries << " " << num_dirty <<
" " << data_->header.num_entries;
DCHECK_LT(num_entries, data_->header.num_entries);
return ERR_NUM_ENTRIES_MISMATCH;
}

Expand Down
9 changes: 9 additions & 0 deletions net/disk_cache/backend_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "net/disk_cache/in_flight_backend_io.h"
#include "net/disk_cache/rankings.h"
#include "net/disk_cache/stats.h"
#include "net/disk_cache/stress_support.h"
#include "net/disk_cache/trace.h"

namespace net {
Expand Down Expand Up @@ -127,6 +128,14 @@ class NET_EXPORT_PRIVATE BackendImpl : public Backend {
// Permanently deletes an entry, but still keeps track of it.
void InternalDoomEntry(EntryImpl* entry);

#if defined(NET_BUILD_STRESS_CACHE)
// Returns the address of the entry linked to the entry at a given |address|.
CacheAddr GetNextAddr(Addr address);

// Verifies that |entry| is not currently reachable through the index.
void NotLinked(EntryImpl* entry);
#endif

// Removes all references to this entry.
void RemoveEntry(EntryImpl* entry);

Expand Down
8 changes: 5 additions & 3 deletions net/disk_cache/backend_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1199,14 +1199,16 @@ void DiskCacheBackendTest::BackendTransaction(const std::string& name,
ASSERT_TRUE(CopyTestCache(name));
DisableFirstCleanup();

uint32 mask;
if (load) {
SetMask(0xf);
mask = 0xf;
SetMaxSize(0x100000);
} else {
// Clear the settings from the previous run.
SetMask(0);
mask = 0;
SetMaxSize(0);
}
SetMask(mask);

InitCache();
ASSERT_EQ(num_entries + 1, cache_->GetEntryCount());
Expand All @@ -1227,7 +1229,7 @@ void DiskCacheBackendTest::BackendTransaction(const std::string& name,
cache_ = NULL;
cache_impl_ = NULL;

ASSERT_TRUE(CheckCacheIntegrity(GetCacheFilePath(), new_eviction_));
ASSERT_TRUE(CheckCacheIntegrity(GetCacheFilePath(), new_eviction_, mask));
success_ = true;
}

Expand Down
4 changes: 2 additions & 2 deletions net/disk_cache/disk_cache_test_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void DiskCacheTestWithCache::SimulateCrash() {

delete cache_impl_;
FilePath path = GetCacheFilePath();
EXPECT_TRUE(CheckCacheIntegrity(path, new_eviction_));
EXPECT_TRUE(CheckCacheIntegrity(path, new_eviction_, mask_));

InitDiskCacheImpl(path);
}
Expand Down Expand Up @@ -213,7 +213,7 @@ void DiskCacheTestWithCache::TearDown() {

if (!memory_only_ && integrity_) {
FilePath path = GetCacheFilePath();
EXPECT_TRUE(CheckCacheIntegrity(path, new_eviction_));
EXPECT_TRUE(CheckCacheIntegrity(path, new_eviction_, mask_));
}

PlatformTest::TearDown();
Expand Down
4 changes: 2 additions & 2 deletions net/disk_cache/disk_cache_test_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ bool CopyTestCache(const std::string& name) {
return file_util::CopyDirectory(path, dest, false);
}

bool CheckCacheIntegrity(const FilePath& path, bool new_eviction) {
bool CheckCacheIntegrity(const FilePath& path, bool new_eviction, uint32 mask) {
scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(
path, base::MessageLoopProxy::current(), NULL));
path, mask, base::MessageLoopProxy::current(), NULL));
if (!cache.get())
return false;
if (new_eviction)
Expand Down
2 changes: 1 addition & 1 deletion net/disk_cache/disk_cache_test_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void CacheTestFillBuffer(char* buffer, size_t len, bool no_nulls);
std::string GenerateKey(bool same_length);

// Returns true if the cache is not corrupt.
bool CheckCacheIntegrity(const FilePath& path, bool new_eviction);
bool CheckCacheIntegrity(const FilePath& path, bool new_eviction, uint32 mask);

// Helper class which ensures that the cache dir returned by GetCacheFilePath
// exists and is clear in ctor and that the directory gets deleted in dtor.
Expand Down
9 changes: 8 additions & 1 deletion net/disk_cache/entry_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,11 @@ bool EntryImpl::SanityCheck() {

Addr next_addr(stored->next);
if (next_addr.is_initialized() &&
(next_addr.is_separate_file() || next_addr.file_type() != BLOCK_256))
(next_addr.is_separate_file() || next_addr.file_type() != BLOCK_256)) {
STRESS_NOTREACHED();
return false;
}
STRESS_DCHECK(next_addr.value() != entry_.address().value());

if (!rankings_addr.SanityCheck() || !next_addr.SanityCheck())
return false;
Expand Down Expand Up @@ -658,6 +661,7 @@ void EntryImpl::FixForDelete() {
if ((data_size <= kMaxBlockSize && data_addr.is_separate_file()) ||
(data_size > kMaxBlockSize && data_addr.is_block_file()) ||
!data_addr.SanityCheck()) {
STRESS_NOTREACHED();
// The address is weird so don't attempt to delete it.
stored->data_addr[i] = 0;
// In general, trust the stored size as it should be in sync with the
Expand Down Expand Up @@ -896,6 +900,9 @@ EntryImpl::~EntryImpl() {
if (doomed_) {
DeleteEntryData(true);
} else {
#if defined(NET_BUILD_STRESS_CACHE)
SanityCheck();
#endif
net_log_.AddEvent(net::NetLog::TYPE_ENTRY_CLOSE, NULL);
bool ret = true;
for (int index = 0; index < kNumStreams; index++) {
Expand Down
8 changes: 7 additions & 1 deletion net/disk_cache/rankings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "net/disk_cache/entry_impl.h"
#include "net/disk_cache/errors.h"
#include "net/disk_cache/histogram_macros.h"
#include "net/disk_cache/stress_support.h"

using base::Time;
using base::TimeTicks;
Expand Down Expand Up @@ -313,14 +314,17 @@ void Rankings::Remove(CacheRankingsBlock* node, List list, bool strict) {
!prev_addr.is_initialized() || prev_addr.is_separate_file()) {
if (next_addr.is_initialized() || prev_addr.is_initialized()) {
LOG(ERROR) << "Invalid rankings info.";
STRESS_NOTREACHED();
}
return;
}

CacheRankingsBlock next(backend_->File(next_addr), next_addr);
CacheRankingsBlock prev(backend_->File(prev_addr), prev_addr);
if (!GetRanking(&next) || !GetRanking(&prev))
if (!GetRanking(&next) || !GetRanking(&prev)) {
STRESS_NOTREACHED();
return;
}

if (!CheckLinks(node, &prev, &next, &list))
return;
Expand Down Expand Up @@ -758,6 +762,8 @@ bool Rankings::CheckLinks(CacheRankingsBlock* node, CacheRankingsBlock* prev,
}

LOG(ERROR) << "Inconsistent LRU.";
STRESS_NOTREACHED();

backend_->CriticalError(ERR_INVALID_LINKS);
return false;
}
Expand Down
Loading

0 comments on commit ea9080b

Please sign in to comment.