diff options
author | rvargas <rvargas@chromium.org> | 2015-03-04 19:35:04 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-05 03:35:52 +0000 |
commit | 4f2eab7cd613d87c79a192bfc5183f79483d95bf (patch) | |
tree | c5168a97a3becc6bc3f1d6d88ddaffa7832486f0 | |
parent | ea82a5686c5810a40d610ae6439e29d994fe9f35 (diff) | |
download | chromium_src-4f2eab7cd613d87c79a192bfc5183f79483d95bf.zip chromium_src-4f2eab7cd613d87c79a192bfc5183f79483d95bf.tar.gz chromium_src-4f2eab7cd613d87c79a192bfc5183f79483d95bf.tar.bz2 |
Disk cache: Re-initialize stats counters if they are zero on-disk.
Stats are saved to disk every five minutes. If a client is initializing
the cache, and it crashes before saving the stats for the first time,
the next run will see an empty stats storage, and will discard the cache
because it may indicate that the storage address was invalid.
Now, we check the contents to see if the storage was empty and re-initialize
things as needed.
BUG=none
TEST=net_unittests
Review URL: https://codereview.chromium.org/980003002
Cr-Commit-Position: refs/heads/master@{#319204}
-rw-r--r-- | net/disk_cache/blockfile/stats.cc | 14 | ||||
-rw-r--r-- | net/disk_cache/blockfile/stats.h | 3 | ||||
-rw-r--r-- | net/disk_cache/blockfile/stats_unittest.cc | 83 | ||||
-rw-r--r-- | net/net.gypi | 1 |
4 files changed, 98 insertions, 3 deletions
diff --git a/net/disk_cache/blockfile/stats.cc b/net/disk_cache/blockfile/stats.cc index e6b10b8..bb319f5 100644 --- a/net/disk_cache/blockfile/stats.cc +++ b/net/disk_cache/blockfile/stats.cc @@ -107,8 +107,18 @@ bool Stats::Init(void* data, int num_bytes, Addr address) { local_stats.size = sizeof(local_stats); } else if (num_bytes >= static_cast<int>(sizeof(*stats))) { stats = reinterpret_cast<OnDiskStats*>(data); - if (!VerifyStats(stats)) - return false; + if (!VerifyStats(stats)) { + memset(&local_stats, 0, sizeof(local_stats)); + if (memcmp(stats, &local_stats, sizeof(local_stats))) { + return false; + } else { + // The storage is empty which means that SerializeStats() was never + // called on the last run. Just re-initialize everything. + local_stats.signature = kDiskSignature; + local_stats.size = sizeof(local_stats); + stats = &local_stats; + } + } } else { return false; } diff --git a/net/disk_cache/blockfile/stats.h b/net/disk_cache/blockfile/stats.h index 8e1293d..769c171 100644 --- a/net/disk_cache/blockfile/stats.h +++ b/net/disk_cache/blockfile/stats.h @@ -9,6 +9,7 @@ #include <vector> #include "base/basictypes.h" +#include "net/base/net_export.h" #include "net/disk_cache/blockfile/addr.h" namespace base { @@ -20,7 +21,7 @@ namespace disk_cache { typedef std::vector<std::pair<std::string, std::string> > StatsItems; // This class stores cache-specific usage information, for tunning purposes. -class Stats { +class NET_EXPORT_PRIVATE Stats { public: static const int kDataSizesLength = 28; enum Counters { diff --git a/net/disk_cache/blockfile/stats_unittest.cc b/net/disk_cache/blockfile/stats_unittest.cc new file mode 100644 index 0000000..fe47bdd --- /dev/null +++ b/net/disk_cache/blockfile/stats_unittest.cc @@ -0,0 +1,83 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/disk_cache/blockfile/stats.h" + +#include "base/memory/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(DiskCacheStatsTest, Init) { + disk_cache::Stats stats; + EXPECT_TRUE(stats.Init(nullptr, 0, disk_cache::Addr())); + EXPECT_EQ(0, stats.GetCounter(disk_cache::Stats::TRIM_ENTRY)); +} + +TEST(DiskCacheStatsTest, InitWithEmptyBuffer) { + disk_cache::Stats stats; + int required_len = stats.StorageSize(); + scoped_ptr<char[]> storage(new char[required_len]); + memset(storage.get(), 0, required_len); + + ASSERT_TRUE(stats.Init(storage.get(), required_len, disk_cache::Addr())); + EXPECT_EQ(0, stats.GetCounter(disk_cache::Stats::TRIM_ENTRY)); +} + +TEST(DiskCacheStatsTest, FailsInit) { + disk_cache::Stats stats; + int required_len = stats.StorageSize(); + scoped_ptr<char[]> storage(new char[required_len]); + memset(storage.get(), 0, required_len); + + // Try a small buffer. + EXPECT_LT(200, required_len); + disk_cache::Addr addr; + EXPECT_FALSE(stats.Init(storage.get(), 200, addr)); + + // Try a buffer with garbage. + memset(storage.get(), 'a', required_len); + EXPECT_FALSE(stats.Init(storage.get(), required_len, addr)); +} + +TEST(DiskCacheStatsTest, SaveRestore) { + scoped_ptr<disk_cache::Stats> stats(new disk_cache::Stats); + + disk_cache::Addr addr(5); + ASSERT_TRUE(stats->Init(nullptr, 0, addr)); + stats->SetCounter(disk_cache::Stats::CREATE_ERROR, 11); + stats->SetCounter(disk_cache::Stats::DOOM_ENTRY, 13); + stats->OnEvent(disk_cache::Stats::MIN_COUNTER); + stats->OnEvent(disk_cache::Stats::TRIM_ENTRY); + stats->OnEvent(disk_cache::Stats::DOOM_RECENT); + + int required_len = stats->StorageSize(); + scoped_ptr<char[]> storage(new char[required_len]); + disk_cache::Addr out_addr; + int real_len = stats->SerializeStats(storage.get(), required_len, &out_addr); + EXPECT_GE(required_len, real_len); + EXPECT_EQ(out_addr, addr); + + stats.reset(new disk_cache::Stats); + ASSERT_TRUE(stats->Init(storage.get(), real_len, addr)); + EXPECT_EQ(1, stats->GetCounter(disk_cache::Stats::MIN_COUNTER)); + EXPECT_EQ(1, stats->GetCounter(disk_cache::Stats::TRIM_ENTRY)); + EXPECT_EQ(1, stats->GetCounter(disk_cache::Stats::DOOM_RECENT)); + EXPECT_EQ(0, stats->GetCounter(disk_cache::Stats::OPEN_HIT)); + EXPECT_EQ(0, stats->GetCounter(disk_cache::Stats::READ_DATA)); + EXPECT_EQ(0, stats->GetCounter(disk_cache::Stats::LAST_REPORT_TIMER)); + EXPECT_EQ(11, stats->GetCounter(disk_cache::Stats::CREATE_ERROR)); + EXPECT_EQ(13, stats->GetCounter(disk_cache::Stats::DOOM_ENTRY)); + + // Now pass the whole buffer. It shoulod not matter that there is unused + // space at the end. + stats.reset(new disk_cache::Stats); + ASSERT_TRUE(stats->Init(storage.get(), required_len, addr)); + EXPECT_EQ(1, stats->GetCounter(disk_cache::Stats::MIN_COUNTER)); + EXPECT_EQ(1, stats->GetCounter(disk_cache::Stats::TRIM_ENTRY)); + EXPECT_EQ(1, stats->GetCounter(disk_cache::Stats::DOOM_RECENT)); + EXPECT_EQ(0, stats->GetCounter(disk_cache::Stats::OPEN_HIT)); + EXPECT_EQ(0, stats->GetCounter(disk_cache::Stats::READ_DATA)); + EXPECT_EQ(0, stats->GetCounter(disk_cache::Stats::LAST_REPORT_TIMER)); + EXPECT_EQ(11, stats->GetCounter(disk_cache::Stats::CREATE_ERROR)); + EXPECT_EQ(13, stats->GetCounter(disk_cache::Stats::DOOM_ENTRY)); +} diff --git a/net/net.gypi b/net/net.gypi index ef68f7b..796d43d 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -1335,6 +1335,7 @@ 'disk_cache/blockfile/block_files_unittest.cc', 'disk_cache/blockfile/index_table_v3_unittest.cc', 'disk_cache/blockfile/mapped_file_unittest.cc', + 'disk_cache/blockfile/stats_unittest.cc', 'disk_cache/blockfile/storage_block_unittest.cc', 'disk_cache/cache_util_unittest.cc', 'disk_cache/entry_unittest.cc', |