1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/backend_impl.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_path.h"
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_util.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/field_trial.h"
11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/metrics/stats_counters.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/rand_util.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/sys_info.h"
173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/worker_pool.h"
183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h"
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/time.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/timer.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/cache_util.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/entry_impl.h"
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/errors.h"
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/disk_cache/experiments.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/file.h"
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/disk_cache/hash.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/disk_cache/mem_backend_impl.h"
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This has to be defined before including histogram_macros.h from this file.
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NET_DISK_CACHE_BACKEND_IMPL_CC_
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/histogram_macros.h"
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time;
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeDelta;
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks;
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* kIndexName = "index";
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kMaxOldFolders = 100;
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Seems like ~240 MB correspond to less than 50k entries for 99% of the people.
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Note that the actual target is to keep the index table load factor under 55%
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// for most users.
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int k64kEntriesStore = 240 * 1000 * 1000;
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kBaseTableLen = 64 * 1024;
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kDefaultCacheSize = 80 * 1024 * 1024;
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint DesiredIndexTableLen(int32 storage_size) {
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (storage_size <= k64kEntriesStore)
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kBaseTableLen;
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (storage_size <= k64kEntriesStore * 2)
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kBaseTableLen * 2;
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (storage_size <= k64kEntriesStore * 4)
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kBaseTableLen * 4;
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (storage_size <= k64kEntriesStore * 8)
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kBaseTableLen * 8;
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The biggest storage_size for int32 requires a 4 MB table.
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return kBaseTableLen * 16;
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MaxStorageSizeForTable(int table_len) {
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return table_len * (k64kEntriesStore / kBaseTableLen);
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t GetIndexSize(int table_len) {
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t table_size = sizeof(disk_cache::CacheAddr) * table_len;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return sizeof(disk_cache::IndexHeader) + table_size;
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns a fully qualified name from path and name, using a given name prefix
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and index number. For instance, if the arguments are "/foo", "bar" and 5, it
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// will return "/foo/old_bar_005".
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath GetPrefixedName(const FilePath& path, const std::string& name,
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         int index) {
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string tmp = base::StringPrintf("%s%s_%03d", "old_",
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       name.c_str(), index);
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return path.AppendASCII(tmp);
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is a simple Task to cleanup old caches.
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass CleanupTask : public Task {
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CleanupTask(const FilePath& path, const std::string& name)
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : path_(path), name_(name) {}
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run();
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path_;
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string name_;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CleanupTask);
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid CleanupTask::Run() {
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kMaxOldFolders; i++) {
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FilePath to_delete = GetPrefixedName(path_, name_, i);
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    disk_cache::DeleteCache(to_delete, true);
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns a full path to rename the current cache, in order to delete it. path
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is the current folder location, and name is the current folder name.
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath GetTempCacheName(const FilePath& path, const std::string& name) {
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We'll attempt to have up to kMaxOldFolders folders for deletion.
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kMaxOldFolders; i++) {
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FilePath to_delete = GetPrefixedName(path, name, i);
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!file_util::PathExists(to_delete))
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return to_delete;
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return FilePath();
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Moves the cache files to a new folder and creates a task to delete them.
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool DelayedCacheCleanup(const FilePath& full_path) {
120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // GetTempCacheName() and MoveCache() use synchronous file
121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // operations.
122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  base::ThreadRestrictions::ScopedAllowIO allow_io;
123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath current_path = full_path.StripTrailingSeparators();
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path = current_path.DirName();
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath name = current_path.BaseName();
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX)
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string name_str = name.value();
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_WIN)
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We created this file so it should only contain ASCII.
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string name_str = WideToASCII(name.value());
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath to_delete = GetTempCacheName(path, name_str);
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (to_delete.empty()) {
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Unable to get another cache folder";
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!disk_cache::MoveCache(full_path, to_delete)) {
142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(ERROR) << "Unable to move cache folder";
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::WorkerPool::PostTask(FROM_HERE, new CleanupTask(path, name_str), true);
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Sets group for the current experiment. Returns false if the files should be
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// discarded.
152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InitExperiment(disk_cache::IndexHeader* header) {
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (header->experiment == disk_cache::EXPERIMENT_OLD_FILE1 ||
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      header->experiment == disk_cache::EXPERIMENT_OLD_FILE2) {
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Discard current cache.
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // See if we already defined the group for this profile.
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (header->experiment >= disk_cache::EXPERIMENT_DELETED_LIST_OUT)
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return true;
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // The experiment is closed.
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  header->experiment = disk_cache::EXPERIMENT_DELETED_LIST_OUT;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Initializes the field trial structures to allow performance measurements
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// for the current cache configuration.
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SetFieldTrialInfo(int size_group) {
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static bool first = true;
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!first)
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Field trials involve static objects so we have to do this only once.
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  first = false;
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string group1 = base::StringPrintf("CacheSizeGroup_%d", size_group);
17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int totalProbability = 10;
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_refptr<base::FieldTrial> trial1(
18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      new base::FieldTrial("CacheSize", totalProbability, group1, 2011, 6, 30));
18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  trial1->AppendGroup(group1, totalProbability);
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------------------------------------------------
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class takes care of building an instance of the backend.
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CacheCreator {
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CacheCreator(const FilePath& path, bool force, int max_bytes,
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               net::CacheType type, uint32 flags,
1913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen               base::MessageLoopProxy* thread, net::NetLog* net_log,
1923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen               disk_cache::Backend** backend,
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               net::CompletionCallback* callback)
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : path_(path), force_(force), retry_(false), max_bytes_(max_bytes),
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        type_(type), flags_(flags), thread_(thread), backend_(backend),
1963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        callback_(callback), cache_(NULL), net_log_(net_log),
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ALLOW_THIS_IN_INITIALIZER_LIST(
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            my_callback_(this, &CacheCreator::OnIOComplete)) {
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~CacheCreator() {}
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Creates the backend.
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int Run();
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Callback implementation.
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnIOComplete(int result);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void DoCallback(int result);
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const FilePath& path_;
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool force_;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool retry_;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int max_bytes_;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CacheType type_;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  uint32 flags_;
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<base::MessageLoopProxy> thread_;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::Backend** backend_;
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CompletionCallback* callback_;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::BackendImpl* cache_;
2213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  net::NetLog* net_log_;
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CompletionCallbackImpl<CacheCreator> my_callback_;
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CacheCreator);
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CacheCreator::Run() {
2283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  cache_ = new disk_cache::BackendImpl(path_, thread_, net_log_);
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cache_->SetMaxSize(max_bytes_);
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cache_->SetType(type_);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cache_->SetFlags(flags_);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = cache_->Init(&my_callback_);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(net::ERR_IO_PENDING, rv);
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CacheCreator::OnIOComplete(int result) {
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result == net::OK || !force_ || retry_)
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return DoCallback(result);
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is a failure and we are supposed to try again, so delete the object,
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // delete all the files, and try again.
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  retry_ = true;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete cache_;
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cache_ = NULL;
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!DelayedCacheCleanup(path_))
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return DoCallback(result);
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The worker thread will start deleting files soon, but the original folder
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // is not there anymore... let's create a new set of files.
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = Run();
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(net::ERR_IO_PENDING, rv);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CacheCreator::DoCallback(int result) {
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(net::ERR_IO_PENDING, result);
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result == net::OK) {
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *backend_ = cache_;
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Unable to create cache";
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *backend_ = NULL;
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete cache_;
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  callback_->Run(result);
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete this;
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------------------------------------------------
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A task to perform final cleanup on the background thread.
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass FinalCleanup : public Task {
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit FinalCleanup(disk_cache::BackendImpl* backend) : backend_(backend) {}
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~FinalCleanup() {}
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void Run();
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::BackendImpl* backend_;
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_EVIL_CONSTRUCTORS(FinalCleanup);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FinalCleanup::Run() {
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  backend_->CleanupCache();
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache {
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CreateCacheBackend(net::CacheType type, const FilePath& path, int max_bytes,
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       bool force, base::MessageLoopProxy* thread,
2943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                       net::NetLog* net_log, Backend** backend,
2953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                       CompletionCallback* callback) {
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(callback);
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (type == net::MEMORY_CACHE) {
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *backend = MemBackendImpl::CreateBackend(max_bytes, net_log);
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return *backend ? net::OK : net::ERR_FAILED;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(thread);
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return BackendImpl::CreateBackend(path, force, max_bytes, type, kNone, thread,
3043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                    net_log, backend, callback);
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the preferred maximum number of bytes for the cache given the
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// number of available bytes.
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint PreferedCacheSize(int64 available) {
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return 80% of the available space if there is not enough space to use
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // kDefaultCacheSize.
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (available < kDefaultCacheSize * 10 / 8)
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return static_cast<int32>(available * 8 / 10);
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return kDefaultCacheSize if it uses 80% to 10% of the available space.
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (available < kDefaultCacheSize * 10)
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kDefaultCacheSize;
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return 10% of the available space if the target size
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (2.5 * kDefaultCacheSize) is more than 10%.
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (available < static_cast<int64>(kDefaultCacheSize) * 25)
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return static_cast<int32>(available / 10);
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return the target size (2.5 * kDefaultCacheSize) if it uses 10% to 1%
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of the available space.
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (available < static_cast<int64>(kDefaultCacheSize) * 250)
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kDefaultCacheSize * 5 / 2;
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return 1% of the available space if it does not exceed kint32max.
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (available < static_cast<int64>(kint32max) * 100)
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return static_cast<int32>(available / 100);
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return kint32max;
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3383345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBackendImpl::BackendImpl(const FilePath& path,
3393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         base::MessageLoopProxy* cache_thread,
3403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         net::NetLog* net_log)
3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : ALLOW_THIS_IN_INITIALIZER_LIST(background_queue_(this, cache_thread)),
3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      path_(path),
3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      block_files_(path),
3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      mask_(0),
3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      max_size_(0),
3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      io_delay_(0),
3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cache_type_(net::DISK_CACHE),
3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      uma_report_(0),
3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      user_flags_(0),
3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      init_(false),
3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      restarted_(false),
3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      unit_test_(false),
3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      read_only_(false),
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      disabled_(false),
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new_eviction_(false),
3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      first_timer_(true),
3573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      net_log_(net_log),
3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      done_(true, false),
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)),
3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {
3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBackendImpl::BackendImpl(const FilePath& path,
3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         uint32 mask,
3653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         base::MessageLoopProxy* cache_thread,
3663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         net::NetLog* net_log)
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : ALLOW_THIS_IN_INITIALIZER_LIST(background_queue_(this, cache_thread)),
3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      path_(path),
3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      block_files_(path),
3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      mask_(mask),
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      max_size_(0),
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      io_delay_(0),
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cache_type_(net::DISK_CACHE),
3743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      uma_report_(0),
3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      user_flags_(kMask),
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      init_(false),
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      restarted_(false),
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      unit_test_(false),
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      read_only_(false),
380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      disabled_(false),
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new_eviction_(false),
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      first_timer_(true),
3833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      net_log_(net_log),
3843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      done_(true, false),
3853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)),
3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBackendImpl::~BackendImpl() {
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  background_queue_.WaitForPendingIO();
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (background_queue_.BackgroundIsCurrentThread()) {
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Unit tests may use the same thread for everything.
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CleanupCache();
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    background_queue_.background_thread()->PostTask(FROM_HERE,
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                    new FinalCleanup(this));
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    done_.Wait();
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// If the initialization of the cache fails, and force is true, we will discard
40372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// the whole cache and create a new one. In order to process a potentially large
40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// number of files, we'll rename the cache folder to old_ + original_name +
40572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// number, (located on the same parent folder), and spawn a worker thread to
40672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// delete all the files on all the stale cache folders. The whole process can
40772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// still fail if we are not able to rename the cache folder (for instance due to
40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// a sharing violation), and in that case a cache for this profile (on the
40972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// desired path) cannot be created.
41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//
41172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Static.
41272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint BackendImpl::CreateBackend(const FilePath& full_path, bool force,
41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               int max_bytes, net::CacheType type,
41472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               uint32 flags, base::MessageLoopProxy* thread,
41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               net::NetLog* net_log, Backend** backend,
41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               CompletionCallback* callback) {
41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(callback);
41872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CacheCreator* creator = new CacheCreator(full_path, force, max_bytes, type,
41972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                           flags, thread, net_log, backend,
42072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                           callback);
42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // This object will self-destroy when finished.
42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return creator->Run();
42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint BackendImpl::Init(CompletionCallback* callback) {
42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  background_queue_.Init(callback);
42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return net::ERR_IO_PENDING;
42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncInit() {
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!init_);
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (init_)
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool create_files = false;
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!InitBackingStore(&create_files)) {
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportError(ERR_STORAGE_ERROR);
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_refs_ = num_pending_io_ = max_refs_ = 0;
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_ = byte_count_ = 0;
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!restarted_) {
4453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buffer_bytes_ = 0;
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    trace_object_ = TraceObject::GetTraceObject();
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Create a recurrent timer of 30 secs.
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int timer_delay = unit_test_ ? 1000 : 30000;
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    timer_.Start(TimeDelta::FromMilliseconds(timer_delay), this,
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                 &BackendImpl::OnStatsTimer);
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  init_ = true;
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (data_->header.experiment != NO_EXPERIMENT &&
4563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cache_type_ != net::DISK_CACHE) {
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No experiment for other caches.
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!(user_flags_ & disk_cache::kNoRandom)) {
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The unit test controls directly what to test.
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    new_eviction_ = (cache_type_ == net::DISK_CACHE);
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!CheckIndex()) {
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportError(ERR_INIT_FAILED);
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!(user_flags_ & disk_cache::kNoRandom) &&
4723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cache_type_ == net::DISK_CACHE &&
473731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      !InitExperiment(&data_->header))
4743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return net::ERR_FAILED;
4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We don't care if the value overflows. The only thing we care about is that
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the id cannot be zero, because that value is used as "not dirty".
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Increasing the value once per second gives us many years before we start
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // having collisions.
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.this_id++;
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!data_->header.this_id)
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->header.this_id++;
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data_->header.crash) {
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportError(ERR_PREVIOUS_CRASH);
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportError(0);
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->header.crash = 1;
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!block_files_.Init(create_files))
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We want to minimize the changes to cache for an AppCache.
4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (cache_type() == net::APP_CACHE) {
4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(!new_eviction_);
4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    read_only_ = true;
4983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
500dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Setup load-time data only for the main cache.
501dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (cache_type() == net::DISK_CACHE)
502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SetFieldTrialInfo(GetSizeGroup());
503dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
504dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  eviction_.Init(this);
505dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // stats_ and rankings_ may end up calling back to us so we better be enabled.
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disabled_ = false;
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!stats_.Init(this, &data_->header.stats))
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disabled_ = !rankings_.Init(this, new_eviction_);
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return disabled_ ? net::ERR_FAILED : net::OK;
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackendImpl::CleanupCache() {
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Trace("Backend Cleanup");
5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  eviction_.Stop();
5193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  timer_.Stop();
5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (init_) {
5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    stats_.Store();
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (data_)
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data_->header.crash = 0;
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    File::WaitForPendingIO(&num_pending_io_);
5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (user_flags_ & kNoRandom) {
5283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // This is a net_unittest, verify that we are not 'leaking' entries.
5293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(!num_refs_);
5303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  block_files_.CloseFiles();
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  factory_.RevokeAll();
5343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ptr_factory_.InvalidateWeakPtrs();
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  done_.Signal();
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::OpenPrevEntry(void** iter, Entry** prev_entry,
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               CompletionCallback* callback) {
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(callback);
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  background_queue_.OpenPrevEntry(iter, prev_entry, callback);
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncOpenEntry(const std::string& key, Entry** entry) {
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(entry);
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *entry = OpenEntryImpl(key);
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (*entry) ? net::OK : net::ERR_FAILED;
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncCreateEntry(const std::string& key, Entry** entry) {
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(entry);
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *entry = CreateEntryImpl(key);
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (*entry) ? net::OK : net::ERR_FAILED;
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncDoomEntry(const std::string& key) {
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (disabled_)
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EntryImpl* entry = OpenEntryImpl(key);
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!entry)
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->DoomImpl();
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->Release();
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::OK;
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncDoomAllEntries() {
5733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This is not really an error, but it is an interesting condition.
5743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ReportError(ERR_CACHE_DOOMED);
5753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats_.OnEvent(Stats::DOOM_CACHE);
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!num_refs_) {
5773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    RestartCache(false);
5783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return disabled_ ? net::ERR_FAILED : net::OK;
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (disabled_)
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return net::ERR_FAILED;
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    eviction_.TrimCache(true);
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::OK;
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncDoomEntriesBetween(const base::Time initial_time,
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        const base::Time end_time) {
5903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_NE(net::APP_CACHE, cache_type_);
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (end_time.is_null())
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return SyncDoomEntriesSince(initial_time);
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(end_time >= initial_time);
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (disabled_)
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EntryImpl* node;
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void* iter = NULL;
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EntryImpl* next = OpenNextEntryImpl(&iter);
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!next)
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::OK;
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (next) {
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node = next;
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next = OpenNextEntryImpl(&iter);
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (node->GetLastUsed() >= initial_time &&
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        node->GetLastUsed() < end_time) {
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      node->DoomImpl();
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (node->GetLastUsed() < initial_time) {
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (next)
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        next->Release();
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next = NULL;
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SyncEndEnumeration(iter);
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node->Release();
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::OK;
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We use OpenNextEntryImpl to retrieve elements from the cache, until we get
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// entries that are too old.
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncDoomEntriesSince(const base::Time initial_time) {
6283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_NE(net::APP_CACHE, cache_type_);
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats_.OnEvent(Stats::DOOM_RECENT);
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (;;) {
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* iter = NULL;
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EntryImpl* entry = OpenNextEntryImpl(&iter);
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!entry)
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return net::OK;
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (initial_time > entry->GetLastUsed()) {
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      entry->Release();
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SyncEndEnumeration(iter);
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return net::OK;
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    entry->DoomImpl();
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    entry->Release();
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SyncEndEnumeration(iter);  // Dooming the entry invalidates the iterator.
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncOpenNextEntry(void** iter, Entry** next_entry) {
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *next_entry = OpenNextEntryImpl(iter);
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (*next_entry) ? net::OK : net::ERR_FAILED;
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncOpenPrevEntry(void** iter, Entry** prev_entry) {
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *prev_entry = OpenPrevEntryImpl(iter);
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (*prev_entry) ? net::OK : net::ERR_FAILED;
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackendImpl::SyncEndEnumeration(void* iter) {
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<Rankings::Iterator> iterator(
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      reinterpret_cast<Rankings::Iterator*>(iter));
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::OpenEntryImpl(const std::string& key) {
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (disabled_)
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint32 hash = Hash(key);
6723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("Open hash 0x%x", hash);
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool error;
67572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EntryImpl* cache_entry = MatchEntry(key, hash, false, Addr(), &error);
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry) {
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::OPEN_MISS);
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ENTRY_NORMAL != cache_entry->entry()->Data()->state) {
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The entry was already evicted.
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cache_entry->Release();
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::OPEN_MISS);
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnOpenEntry(cache_entry);
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_++;
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(AGE_MS, "OpenTime", GetSizeGroup(), start);
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::OPEN_HIT);
693dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SIMPLE_STATS_COUNTER("disk_cache.hit");
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return cache_entry;
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::CreateEntryImpl(const std::string& key) {
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_ || key.empty())
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint32 hash = Hash(key);
7033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("Create hash 0x%x", hash);
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<EntryImpl> parent;
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr entry_address(data_->table[hash & mask_]);
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (entry_address.is_initialized()) {
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We have an entry already. It could be the one we are looking for, or just
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // a hash conflict.
71072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    bool error;
71172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EntryImpl* old_entry = MatchEntry(key, hash, false, Addr(), &error);
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (old_entry)
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResurrectEntry(old_entry);
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EntryImpl* parent_entry = MatchEntry(key, hash, true, Addr(), &error);
71672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(!error);
7173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (parent_entry) {
7183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      parent.swap(&parent_entry);
7193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (data_->table[hash & mask_]) {
7203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // We should have corrected the problem.
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NOTREACHED();
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return NULL;
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
726ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // The general flow is to allocate disk space and initialize the entry data,
727ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // followed by saving that to disk, then linking the entry though the index
728ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // and finally through the lists. If there is a crash in this process, we may
729ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // end up with:
730ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // a. Used, unreferenced empty blocks on disk (basically just garbage).
731ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // b. Used, unreferenced but meaningful data on disk (more garbage).
732ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // c. A fully formed entry, reachable only through the index.
733ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // d. A fully formed entry, also reachable through the lists, but still dirty.
734ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  //
735ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // Anything after (b) can be automatically cleaned up. We may consider saving
736ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // the current operation (as we do while manipulating the lists) so that we
737ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // can detect and cleanup (a) and (b).
738ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen
739ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen  int num_blocks = EntryImpl::NumBlocksForEntry(key.size());
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!block_files_.CreateBlock(BLOCK_256, num_blocks, &entry_address)) {
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Create entry failed " << key.c_str();
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::CREATE_ERROR);
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr node_address(0);
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!block_files_.CreateBlock(RANKINGS, 1, &node_address)) {
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    block_files_.DeleteBlock(entry_address, false);
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Create entry failed " << key.c_str();
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::CREATE_ERROR);
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<EntryImpl> cache_entry(
7553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new EntryImpl(this, entry_address, false));
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IncreaseNumRefs();
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry->CreateEntry(node_address, key, hash)) {
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    block_files_.DeleteBlock(entry_address, false);
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    block_files_.DeleteBlock(node_address, false);
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Create entry failed " << key.c_str();
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::CREATE_ERROR);
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  cache_entry->BeginLogging(net_log_, true);
7673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We are not failing the operation; let's add this to the map.
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  open_entries_[entry_address.value()] = cache_entry;
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
771ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // Save the entry.
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  block_files_.GetFile(entry_address)->Store(cache_entry->entry());
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  block_files_.GetFile(node_address)->Store(cache_entry->rankings());
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IncreaseNumEntries();
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_++;
776ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen
777ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // Link this entry through the index.
778ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  if (parent.get()) {
779ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    parent->SetNextAddress(entry_address);
780ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  } else {
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->table[hash & mask_] = entry_address.value();
782ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  }
783ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen
784ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  // Link this entry through the lists.
785ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  eviction_.OnCreateEntry(cache_entry);
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(AGE_MS, "CreateTime", GetSizeGroup(), start);
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::CREATE_HIT);
789dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SIMPLE_STATS_COUNTER("disk_cache.miss");
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("create entry hit ");
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return cache_entry.release();
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
794c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::OpenNextEntryImpl(void** iter) {
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OpenFollowingEntry(true, iter);
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
798c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::OpenPrevEntryImpl(void** iter) {
799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OpenFollowingEntry(false, iter);
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::SetMaxSize(int max_bytes) {
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  COMPILE_ASSERT(sizeof(max_bytes) == sizeof(max_size_), unsupported_int_model);
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_bytes < 0)
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Zero size means use the default.
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!max_bytes)
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Avoid a DCHECK later on.
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_bytes >= kint32max - kint32max / 10)
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_bytes = kint32max - kint32max / 10 - 1;
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= kMaxSize;
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  max_size_ = max_bytes;
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetType(net::CacheType type) {
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(type != net::MEMORY_CACHE);
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cache_type_ = type;
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath BackendImpl::GetFileName(Addr address) const {
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!address.is_separate_file() || !address.is_initialized()) {
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return FilePath();
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string tmp = base::StringPrintf("f_%06x", address.FileNumber());
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return path_.AppendASCII(tmp);
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMappedFile* BackendImpl::File(Addr address) {
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return block_files_.GetFile(address);
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CreateExternalFile(Addr* address) {
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int file_number = data_->header.last_file + 1;
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr file_address(0);
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool success = false;
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < 0x0fffffff; i++, file_number++) {
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!file_address.SetFileNumber(file_number)) {
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      file_number = 1;
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FilePath name = GetFileName(file_address);
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int flags = base::PLATFORM_FILE_READ |
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                base::PLATFORM_FILE_WRITE |
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                base::PLATFORM_FILE_CREATE |
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                base::PLATFORM_FILE_EXCLUSIVE_WRITE;
855dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    base::PlatformFileError error;
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    scoped_refptr<disk_cache::File> file(new disk_cache::File(
857dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        base::CreatePlatformFile(name, flags, NULL, &error)));
858dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!file->IsValid()) {
859dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (error != base::PLATFORM_FILE_ERROR_EXISTS)
860dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        return false;
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
862dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    success = true;
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    break;
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(success);
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!success)
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.last_file = file_number;
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  address->set_value(file_address.value());
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CreateBlock(FileType block_type, int block_count,
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             Addr* block_address) {
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return block_files_.CreateBlock(block_type, block_count, block_address);
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DeleteBlock(Addr block_address, bool deep) {
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  block_files_.DeleteBlock(block_address, deep);
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottLruData* BackendImpl::GetLruData() {
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return &data_->header.lru;
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::UpdateRank(EntryImpl* entry, bool modified) {
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!read_only_) {
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    eviction_.UpdateRank(entry, modified);
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::RecoveredEntry(CacheRankingsBlock* rankings) {
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(rankings->Data()->contents);
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntryImpl* cache_entry = NULL;
899dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (NewEntry(address, &cache_entry))
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint32 hash = cache_entry->GetHash();
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cache_entry->Release();
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Anything on the table means that this entry is there.
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data_->table[hash & mask_])
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->table[hash & mask_] = address.value();
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::InternalDoomEntry(EntryImpl* entry) {
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint32 hash = entry->GetHash();
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string key = entry->GetKey();
91572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Addr entry_addr = entry->entry()->address();
91672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool error;
91772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EntryImpl* parent_entry = MatchEntry(key, hash, true, entry_addr, &error);
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheAddr child(entry->GetNextAddress());
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Doom entry 0x%p", entry);
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
922dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!entry->doomed()) {
923dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We may have doomed this entry from within MatchEntry.
924dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    eviction_.OnDoomEntry(entry);
925dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    entry->InternalDoom();
926dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!new_eviction_) {
927dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      DecreaseNumEntries();
928dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
929dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stats_.OnEvent(Stats::DOOM_ENTRY);
930dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (parent_entry) {
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent_entry->SetNextAddress(Addr(child));
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent_entry->Release();
93572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (!error) {
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->table[hash & mask_] = child;
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// An entry may be linked on the DELETED list for a while after being doomed.
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This function is called when we want to remove it.
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::RemoveEntry(EntryImpl* entry) {
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!new_eviction_)
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ENTRY_NORMAL != entry->entry()->Data()->state);
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Remove entry 0x%p", entry);
949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnDestroyEntry(entry);
950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DecreaseNumEntries();
951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackendImpl::OnEntryDestroyBegin(Addr address) {
954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntriesMap::iterator it = open_entries_.find(address.value());
955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != open_entries_.end())
956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    open_entries_.erase(it);
9573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
9583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
9593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackendImpl::OnEntryDestroyEnd() {
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DecreaseNumRefs();
9613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (data_->header.num_bytes > max_size_ && !read_only_)
9623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    eviction_.TrimCache(false);
963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEntryImpl* BackendImpl::GetOpenEntry(CacheRankingsBlock* rankings) const {
966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(rankings->HasData());
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntriesMap::const_iterator it =
968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      open_entries_.find(rankings->Data()->contents);
969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != open_entries_.end()) {
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We have this entry in memory.
971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return it->second;
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NULL;
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint32 BackendImpl::GetCurrentEntryId() const {
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return data_->header.this_id;
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::MaxFileSize() const {
982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return max_size_ / 8;
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::ModifyStorageSize(int32 old_size, int32 new_size) {
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_ || old_size == new_size)
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (old_size > new_size)
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SubstractStorageSize(old_size - new_size);
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AddStorageSize(new_size - old_size);
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Update the usage statistics.
994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.ModifyStorageStats(old_size, new_size);
995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::TooMuchStorageRequested(int32 size) {
998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.ModifyStorageStats(0, size);
999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BackendImpl::IsAllocAllowed(int current_size, int new_size) {
10023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GT(new_size, current_size);
10033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (user_flags_ & kNoBuffering)
10043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
10053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int to_add = new_size - current_size;
10073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (buffer_bytes_ + to_add > MaxBuffersSize())
10083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
10093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  buffer_bytes_ += to_add;
10113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(COUNTS_50000, "BufferBytes", 0, buffer_bytes_ / 1024);
10123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
10133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
10143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackendImpl::BufferDeleted(int size) {
10163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  buffer_bytes_ -= size;
10173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(size, 0);
10183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
10193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::IsLoaded() const {
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "PendingIO", GetSizeGroup(), num_pending_io_);
1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (user_flags_ & kNoLoadProtection)
1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return num_pending_io_ > 5;
1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string BackendImpl::HistogramName(const char* name, int experiment) const {
1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!experiment)
10303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return base::StringPrintf("DiskCache.%d.%s", cache_type_, name);
10313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return base::StringPrintf("DiskCache.%d.%s_%d", cache_type_,
10323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            name, experiment);
10333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
10343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbase::WeakPtr<BackendImpl> BackendImpl::GetWeakPtr() {
10363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ptr_factory_.GetWeakPtr();
1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::GetSizeGroup() const {
1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We want to report times grouped by the current cache size (50 MB groups).
1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int group = data_->header.num_bytes / (50 * 1024 * 1024);
1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (group > 6)
1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    group = 6;  // Limit the number of groups, just in case.
1047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return group;
1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We want to remove biases from some histograms so we only send data once per
1051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// week.
1052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::ShouldReportAgain() {
1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (uma_report_)
1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return uma_report_ == 2;
1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uma_report_++;
1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 last_report = stats_.GetCounter(Stats::LAST_REPORT);
1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Time last_time = Time::FromInternalValue(last_report);
1059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!last_report || (Time::Now() - last_time).InDays() >= 7) {
1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.SetCounter(Stats::LAST_REPORT, Time::Now().ToInternalValue());
1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uma_report_++;
1062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
1063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return false;
1065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::FirstEviction() {
1068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(data_->header.create_time);
1069dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!GetEntryCount())
1070dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;  // This is just for unit tests.
1071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Time create_time = Time::FromInternalValue(data_->header.create_time);
1073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(AGE, "FillupAge", 0, create_time);
1074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 use_time = stats_.GetCounter(Stats::TIMER);
1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(HOURS, "FillupTime", 0, static_cast<int>(use_time / 120));
1077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(PERCENTAGE, "FirstHitRatio", 0, stats_.GetHitRatio());
1078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!use_time)
1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    use_time = 1;
1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS_10000, "FirstEntryAccessRate", 0,
1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            static_cast<int>(data_->header.num_entries / use_time));
1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS, "FirstByteIORate", 0,
1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            static_cast<int>((data_->header.num_bytes / 1024) / use_time));
1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int avg_size = data_->header.num_bytes / GetEntryCount();
1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "FirstEntrySize", 0, avg_size);
1088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int large_entries_bytes = stats_.GetLargeEntriesSize();
1090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int large_ratio = large_entries_bytes * 100 / data_->header.num_bytes;
1091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(PERCENTAGE, "FirstLargeEntriesRatio", 0, large_ratio);
1092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (new_eviction_) {
1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "FirstResurrectRatio", 0, stats_.GetResurrectRatio());
1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "FirstNoUseRatio", 0,
1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[0] * 100 / data_->header.num_entries);
1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "FirstLowUseRatio", 0,
1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[1] * 100 / data_->header.num_entries);
1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "FirstHighUseRatio", 0,
1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[2] * 100 / data_->header.num_entries);
1101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.ResetRatios();
1104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::CriticalError(int error) {
1107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(ERROR) << "Critical error found " << error;
1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats_.OnEvent(Stats::FATAL_ERROR);
1112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LogStats();
1113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ReportError(error);
1114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Setting the index table length to an invalid value will force re-creation
1116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of the cache files.
1117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.table_len = 1;
1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disabled_ = true;
1119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!num_refs_)
1121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    MessageLoop::current()->PostTask(FROM_HERE,
11223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        factory_.NewRunnableMethod(&BackendImpl::RestartCache, true));
1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::ReportError(int error) {
1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We transmit positive numbers, instead of direct error codes.
1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_LE(error, 0);
1128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(CACHE_ERROR, "Error", 0, error * -1);
1129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::OnEvent(Stats::Counters an_event) {
1132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(an_event);
1133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackendImpl::OnRead(int32 bytes) {
1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(bytes, 0);
1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  byte_count_ += bytes;
1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (byte_count_ < 0)
1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    byte_count_ = kint32max;
1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackendImpl::OnWrite(int32 bytes) {
1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We use the same implementation as OnRead... just log the number of bytes.
1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OnRead(bytes);
1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::OnStatsTimer() {
1148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::TIMER);
1149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 time = stats_.GetCounter(Stats::TIMER);
1150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 current = stats_.GetCounter(Stats::OPEN_ENTRIES);
1151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // OPEN_ENTRIES is a sampled average of the number of open entries, avoiding
1153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the bias towards 0.
1154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (num_refs_ && (current != num_refs_)) {
1155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int64 diff = (num_refs_ - current) / 50;
1156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!diff)
1157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      diff = num_refs_ > current ? 1 : -1;
1158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current = current + diff;
1159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.SetCounter(Stats::OPEN_ENTRIES, current);
1160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.SetCounter(Stats::MAX_ENTRIES, max_refs_);
1161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "NumberOfReferences", 0, num_refs_);
1164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS_10000, "EntryAccessRate", 0, entry_count_);
1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS, "ByteIORate", 0, byte_count_ / 1024);
1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_ = 0;
1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  byte_count_ = 0;
1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!data_)
1171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    first_timer_ = false;
1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (first_timer_) {
1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    first_timer_ = false;
1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (ShouldReportAgain())
1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ReportStats();
1176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Save stats to disk at 5 min intervals.
1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (time % 10 == 0)
1180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.Store();
1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::IncrementIoCount() {
1184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_pending_io_++;
1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DecrementIoCount() {
1188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_pending_io_--;
1189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetUnitTestMode() {
1192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= kUnitTestMode;
1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unit_test_ = true;
1194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetUpgradeMode() {
1197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= kUpgradeMode;
1198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_only_ = true;
1199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetNewEviction() {
1202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= kNewEviction;
1203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  new_eviction_ = true;
1204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetFlags(uint32 flags) {
1207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= flags;
1208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::ClearRefCountForTest() {
1211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_refs_ = 0;
1212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::FlushQueueForTest(CompletionCallback* callback) {
1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  background_queue_.FlushQueue(callback);
1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint BackendImpl::RunTaskForTest(Task* task, CompletionCallback* callback) {
12203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  background_queue_.RunTask(task, callback);
12213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return net::ERR_IO_PENDING;
12223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
12233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
122472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BackendImpl::TrimForTest(bool empty) {
122572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  eviction_.SetTestMode();
122672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  eviction_.TrimCache(empty);
122772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
122872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
122972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BackendImpl::TrimDeletedListForTest(bool empty) {
123072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  eviction_.SetTestMode();
123172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  eviction_.TrimDeletedList(empty);
123272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
123372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::SelfCheck() {
1235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!init_) {
1236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Init failed";
1237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INIT_FAILED;
1238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_entries = rankings_.SelfCheck();
1241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (num_entries < 0) {
1242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Invalid rankings list, error " << num_entries;
1243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return num_entries;
1244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (num_entries != data_->header.num_entries) {
1247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Number of entries mismatch";
1248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_NUM_ENTRIES_MISMATCH;
1249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return CheckAllEntries();
1252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
1255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint32 BackendImpl::GetEntryCount() const {
12573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (!index_ || disabled_)
12583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return 0;
12593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // num_entries includes entries already evicted.
12603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  int32 not_deleted = data_->header.num_entries -
12613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                      data_->header.lru.sizes[Rankings::DELETED];
12623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (not_deleted < 0) {
12643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    NOTREACHED();
12653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    not_deleted = 0;
12663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
12673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return not_deleted;
12693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
12703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::OpenEntry(const std::string& key, Entry** entry,
12723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                           CompletionCallback* callback) {
12733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
12743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.OpenEntry(key, entry, callback);
12753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
12763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
12773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::CreateEntry(const std::string& key, Entry** entry,
12793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                             CompletionCallback* callback) {
12803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
12813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.CreateEntry(key, entry, callback);
12823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
12833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
12843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::DoomEntry(const std::string& key,
12863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                           CompletionCallback* callback) {
12873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
12883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.DoomEntry(key, callback);
12893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
12903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
12913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::DoomAllEntries(CompletionCallback* callback) {
12933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
12943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.DoomAllEntries(callback);
12953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
12963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
12973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::DoomEntriesBetween(const base::Time initial_time,
12993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                    const base::Time end_time,
13003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                    CompletionCallback* callback) {
13013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.DoomEntriesBetween(initial_time, end_time, callback);
13033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::DoomEntriesSince(const base::Time initial_time,
13073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                  CompletionCallback* callback) {
13083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.DoomEntriesSince(initial_time, callback);
13103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::OpenNextEntry(void** iter, Entry** next_entry,
13143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                               CompletionCallback* callback) {
13153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.OpenNextEntry(iter, next_entry, callback);
13173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BackendImpl::EndEnumeration(void** iter) {
13213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.EndEnumeration(*iter);
13223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  *iter = NULL;
13233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BackendImpl::GetStats(StatsItems* stats) {
13263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (disabled_)
13273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return;
13283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  std::pair<std::string, std::string> item;
13303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.first = "Entries";
13323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.second = base::StringPrintf("%d", data_->header.num_entries);
13333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats->push_back(item);
13343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.first = "Pending IO";
13363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.second = base::StringPrintf("%d", num_pending_io_);
13373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats->push_back(item);
13383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.first = "Max size";
13403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.second = base::StringPrintf("%d", max_size_);
13413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats->push_back(item);
13423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.first = "Current size";
13443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.second = base::StringPrintf("%d", data_->header.num_bytes);
13453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats->push_back(item);
13463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats_.GetItems(stats);
13483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// ------------------------------------------------------------------------
13513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We just created a new file so we're going to write the header and set the
1353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// file length to include the hash table (zero filled).
1354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CreateBackingStore(disk_cache::File* file) {
1355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AdjustMaxCacheSize(0);
1356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IndexHeader header;
1358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  header.table_len = DesiredIndexTableLen(max_size_);
1359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We need file version 2.1 for the new eviction algorithm.
1361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (new_eviction_)
1362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    header.version = 0x20001;
1363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  header.create_time = Time::Now().ToInternalValue();
1365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file->Write(&header, sizeof(header), 0))
1367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return file->SetLength(GetIndexSize(header.table_len));
1370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::InitBackingStore(bool* file_created) {
1373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file_util::CreateDirectory(path_);
1374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath index_name = path_.AppendASCII(kIndexName);
1376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int flags = base::PLATFORM_FILE_READ |
1378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              base::PLATFORM_FILE_WRITE |
1379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              base::PLATFORM_FILE_OPEN_ALWAYS |
1380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              base::PLATFORM_FILE_EXCLUSIVE_WRITE;
1381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<disk_cache::File> file(new disk_cache::File(
13823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::CreatePlatformFile(index_name, flags, file_created, NULL)));
1383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file->IsValid())
1385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ret = true;
1388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (*file_created)
1389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ret = CreateBackingStore(file);
1390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file = NULL;
1392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ret)
1393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  index_ = new MappedFile();
1396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_ = reinterpret_cast<Index*>(index_->Init(index_name, 0));
1397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!data_) {
1398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Unable to map Index file";
1399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index_->GetLength() < sizeof(Index)) {
1403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We verify this again on CheckIndex() but it's easier to make sure now
1404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // that the header is there.
1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Corrupt Index file";
1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
1410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The maximum cache size will be either set explicitly by the caller, or
1413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// calculated by this code.
1414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::AdjustMaxCacheSize(int table_len) {
1415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_size_)
1416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If table_len is provided, the index file exists.
1419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!table_len || data_->header.magic);
1420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The user is not setting the size, let's figure it out.
142200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#ifdef ANDROID
142300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int64 available = 10 * 1024 * 1024; // 10 MB
142400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#else
1425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 available = base::SysInfo::AmountOfFreeDiskSpace(path_);
142600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#endif
1427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (available < 0) {
1428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_size_ = kDefaultCacheSize;
1429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (table_len)
1433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    available += data_->header.num_bytes;
1434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  max_size_ = PreferedCacheSize(available);
1436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Let's not use more than the default size while we tune-up the performance
1438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of bigger caches. TODO(rvargas): remove this limit.
1439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_size_ > kDefaultCacheSize * 4)
1440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_size_ = kDefaultCacheSize * 4;
1441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!table_len)
1443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If we already have a table, adjust the size to it.
1446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int current_max_size = MaxStorageSizeForTable(table_len);
1447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_size_ > current_max_size)
1448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_size_= current_max_size;
1449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BackendImpl::RestartCache(bool failure) {
1452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 errors = stats_.GetCounter(Stats::FATAL_ERROR);
14533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  int64 full_dooms = stats_.GetCounter(Stats::DOOM_CACHE);
14543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  int64 partial_dooms = stats_.GetCounter(Stats::DOOM_RECENT);
145572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int64 last_report = stats_.GetCounter(Stats::LAST_REPORT);
14563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
14573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  PrepareForRestart();
14583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (failure) {
14593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DCHECK(!num_refs_);
14603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DCHECK(!open_entries_.size());
14613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DelayedCacheCleanup(path_);
14623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  } else {
14633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DeleteCache(path_, false);
14643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
1465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Don't call Init() if directed by the unit test: we are simulating a failure
1467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // trying to re-enable the cache.
1468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (unit_test_)
1469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    init_ = true;  // Let the destructor do proper cleanup.
14703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  else if (SyncInit() == net::OK) {
14713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    stats_.SetCounter(Stats::FATAL_ERROR, errors);
14723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    stats_.SetCounter(Stats::DOOM_CACHE, full_dooms);
14733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    stats_.SetCounter(Stats::DOOM_RECENT, partial_dooms);
147472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    stats_.SetCounter(Stats::LAST_REPORT, last_report);
14753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
1476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::PrepareForRestart() {
1479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Reset the mask_ if it was not given by the user.
1480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!(user_flags_ & kMask))
1481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    mask_ = 0;
1482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!(user_flags_ & kNewEviction))
1484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    new_eviction_ = false;
1485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  disabled_ = true;
1487a7f1721675b8b6e0389732f1e25788012f7c20b7Magnus Hallqvist#ifdef ANDROID
1488a7f1721675b8b6e0389732f1e25788012f7c20b7Magnus Hallqvist  if (data_) {
1489a7f1721675b8b6e0389732f1e25788012f7c20b7Magnus Hallqvist#endif
1490a7f1721675b8b6e0389732f1e25788012f7c20b7Magnus Hallqvist    data_->header.crash = 0;
1491a7f1721675b8b6e0389732f1e25788012f7c20b7Magnus Hallqvist#ifdef ANDROID
1492a7f1721675b8b6e0389732f1e25788012f7c20b7Magnus Hallqvist  }
1493a7f1721675b8b6e0389732f1e25788012f7c20b7Magnus Hallqvist#endif
1494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  index_ = NULL;
1495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_ = NULL;
1496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  block_files_.CloseFiles();
1497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rankings_.Reset();
1498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  init_ = false;
1499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  restarted_ = true;
1500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint BackendImpl::NewEntry(Addr address, EntryImpl** entry) {
1503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntriesMap::iterator it = open_entries_.find(address.value());
1504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != open_entries_.end()) {
1505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Easy job. This entry is already in memory.
1506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EntryImpl* this_entry = it->second;
1507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    this_entry->AddRef();
1508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *entry = this_entry;
1509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
1510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<EntryImpl> cache_entry(
15133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new EntryImpl(this, address, read_only_));
1514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IncreaseNumRefs();
1515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *entry = NULL;
1516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!address.is_initialized() || address.is_separate_file() ||
1518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      address.file_type() != BLOCK_256) {
1519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(WARNING) << "Wrong entry address.";
1520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INVALID_ADDRESS;
1521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
1524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry->entry()->Load())
1525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_READ_FAILURE;
1526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsLoaded()) {
1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CACHE_UMA(AGE_MS, "LoadTime", GetSizeGroup(), start);
1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry->SanityCheck()) {
1532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(WARNING) << "Messed up entry found.";
1533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INVALID_ENTRY;
1534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry->LoadNodeAddress())
1537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_READ_FAILURE;
1538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Prevent overwriting the dirty flag on the destructor.
1540dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  cache_entry->SetDirtyFlag(GetCurrentEntryId());
1541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1542ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  if (!rankings_.SanityCheck(cache_entry->rankings(), false)) {
1543ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    cache_entry->SetDirtyFlag(0);
1544ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    // Don't remove this from the list (it is not linked properly). Instead,
1545ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    // break the link back to the entry because it is going away, and leave the
1546ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    // rankings node to be deleted if we find it through a list.
1547ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    rankings_.SetContents(cache_entry->rankings(), 0);
1548ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  } else if (!rankings_.DataSanityCheck(cache_entry->rankings(), false)) {
1549ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    cache_entry->SetDirtyFlag(0);
1550ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    rankings_.SetContents(cache_entry->rankings(), address.value());
1551ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  }
1552ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen
1553ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  if (!cache_entry->DataSanityCheck()) {
1554ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    LOG(WARNING) << "Messed up entry found.";
1555ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    cache_entry->SetDirtyFlag(0);
1556ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    cache_entry->FixForDelete();
1557ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  }
1558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (cache_entry->dirty()) {
15603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    Trace("Dirty entry 0x%p 0x%x", reinterpret_cast<void*>(cache_entry.get()),
15613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          address.value());
15623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  open_entries_[address.value()] = cache_entry;
1565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
15663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  cache_entry->BeginLogging(net_log_, false);
1567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cache_entry.swap(entry);
1568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return 0;
1569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEntryImpl* BackendImpl::MatchEntry(const std::string& key, uint32 hash,
157272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   bool find_parent, Addr entry_addr,
157372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   bool* match_error) {
1574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(data_->table[hash & mask_]);
1575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<EntryImpl> cache_entry, parent_entry;
1576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntryImpl* tmp = NULL;
1577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool found = false;
157872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::set<CacheAddr> visited;
157972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  *match_error = false;
1580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (;;) {
1582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (disabled_)
1583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
158572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (visited.find(address.value()) != visited.end()) {
158672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // It's possible for a buggy version of the code to write a loop. Just
158772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // break it.
158872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      Trace("Hash collision loop 0x%x", address.value());
158972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      address.set_value(0);
159072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      parent_entry->SetNextAddress(address);
159172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
159272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    visited.insert(address.value());
159372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!address.is_initialized()) {
1595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (find_parent)
1596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        found = true;
1597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int error = NewEntry(address, &tmp);
1601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cache_entry.swap(&tmp);
1602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (error || cache_entry->dirty()) {
1604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // This entry is dirty on disk (it was not properly closed): we cannot
1605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // trust it.
1606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Addr child(0);
1607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!error)
1608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        child.set_value(cache_entry->GetNextAddress());
1609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (parent_entry) {
1611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        parent_entry->SetNextAddress(child);
1612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        parent_entry = NULL;
1613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
1614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        data_->table[hash & mask_] = child.value();
1615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
1616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1617dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      Trace("MatchEntry dirty %d 0x%x 0x%x", find_parent, entry_addr.value(),
1618dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            address.value());
1619dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!error) {
1621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // It is important to call DestroyInvalidEntry after removing this
1622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // entry from the table.
1623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DestroyInvalidEntry(cache_entry);
1624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cache_entry = NULL;
1625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
1626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Trace("NewEntry failed on MatchEntry 0x%x", address.value());
1627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
1628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Restart the search.
1630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      address.set_value(data_->table[hash & mask_]);
163172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      visited.clear();
1632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
1633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK_EQ(hash & mask_, cache_entry->entry()->Data()->hash & mask_);
1636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (cache_entry->IsSameEntry(key, hash)) {
1637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!cache_entry->Update())
1638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cache_entry = NULL;
1639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      found = true;
164072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (find_parent && entry_addr.value() != address.value()) {
164172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        Trace("Entry not on the index 0x%x", address.value());
164272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        *match_error = true;
164372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        parent_entry = NULL;
164472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
1645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!cache_entry->Update())
1648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cache_entry = NULL;
1649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent_entry = cache_entry;
1650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cache_entry = NULL;
1651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!parent_entry)
1652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    address.set_value(parent_entry->GetNextAddress());
1655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (parent_entry && (!find_parent || !found))
1658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent_entry = NULL;
1659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1660dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (find_parent && entry_addr.is_initialized() && !cache_entry) {
1661dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    *match_error = true;
1662dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    parent_entry = NULL;
1663dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1664dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cache_entry && (find_parent || !found))
1666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cache_entry = NULL;
1667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  find_parent ? parent_entry.swap(&tmp) : cache_entry.swap(&tmp);
1669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return tmp;
1670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is the actual implementation for OpenNextEntry and OpenPrevEntry.
1673c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::OpenFollowingEntry(bool forward, void** iter) {
1674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
1675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
1676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(iter);
1678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int kListsToSearch = 3;
1680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<EntryImpl> entries[kListsToSearch];
1681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<Rankings::Iterator> iterator(
1682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<Rankings::Iterator*>(*iter));
1683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *iter = NULL;
1684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!iterator.get()) {
1686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    iterator.reset(new Rankings::Iterator(&rankings_));
1687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool ret = false;
1688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Get an entry from each list.
1690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int i = 0; i < kListsToSearch; i++) {
1691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EntryImpl* temp = NULL;
1692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ret |= OpenFollowingEntryFromList(forward, static_cast<Rankings::List>(i),
1693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                        &iterator->nodes[i], &temp);
1694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      entries[i].swap(&temp);  // The entry was already addref'd.
1695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!ret)
1697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return NULL;
1698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
1699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Get the next entry from the last list, and the actual entries for the
1700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // elements on the other lists.
1701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int i = 0; i < kListsToSearch; i++) {
1702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EntryImpl* temp = NULL;
1703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (iterator->list == i) {
1704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          OpenFollowingEntryFromList(forward, iterator->list,
1705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     &iterator->nodes[i], &temp);
1706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
1707ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen        temp = GetEnumeratedEntry(iterator->nodes[i],
1708ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen                                  static_cast<Rankings::List>(i));
1709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
1710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      entries[i].swap(&temp);  // The entry was already addref'd.
1712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int newest = -1;
1716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int oldest = -1;
1717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Time access_times[kListsToSearch];
1718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kListsToSearch; i++) {
1719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (entries[i].get()) {
1720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      access_times[i] = entries[i]->GetLastUsed();
1721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (newest < 0) {
1722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK_LT(oldest, 0);
1723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        newest = oldest = i;
1724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        continue;
1725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
1726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (access_times[i] > access_times[newest])
1727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        newest = i;
1728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (access_times[i] < access_times[oldest])
1729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        oldest = i;
1730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (newest < 0 || oldest < 0)
1734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
1735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EntryImpl* next_entry;
1737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (forward) {
1738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_entry = entries[newest].release();
1739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    iterator->list = static_cast<Rankings::List>(newest);
1740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
1741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_entry = entries[oldest].release();
1742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    iterator->list = static_cast<Rankings::List>(oldest);
1743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *iter = iterator.release();
1746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return next_entry;
1747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::OpenFollowingEntryFromList(bool forward, Rankings::List list,
1750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                             CacheRankingsBlock** from_entry,
1751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                             EntryImpl** next_entry) {
1752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
1753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!new_eviction_ && Rankings::NO_USE != list)
1756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Rankings::ScopedRankingsBlock rankings(&rankings_, *from_entry);
1759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheRankingsBlock* next_block = forward ?
1760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rankings_.GetNext(rankings.get(), list) :
1761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rankings_.GetPrev(rankings.get(), list);
1762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Rankings::ScopedRankingsBlock next(&rankings_, next_block);
1763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *from_entry = NULL;
1764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1765ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  *next_entry = GetEnumeratedEntry(next.get(), list);
1766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!*next_entry)
1767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *from_entry = next.release();
1770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
1771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1773ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian MonsenEntryImpl* BackendImpl::GetEnumeratedEntry(CacheRankingsBlock* next,
1774ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen                                           Rankings::List list) {
1775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!next || disabled_)
1776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
1777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntryImpl* entry;
1779ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  int rv = NewEntry(Addr(next->Data()->contents), &entry);
1780ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen  if (rv) {
1781ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    rankings_.Remove(next, list, false);
1782ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    if (rv == ERR_INVALID_ADDRESS) {
1783ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen      // There is nothing linked from the index. Delete the rankings node.
1784ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen      DeleteBlock(next->address(), true);
1785ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen    }
1786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
1787dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1789dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (entry->dirty()) {
1790dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We cannot trust this entry.
1791dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    InternalDoomEntry(entry);
1792dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    entry->Release();
1793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
1794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
179672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!entry->Update()) {
1797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry->Release();
1798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
1799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
180172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Note that it is unfortunate (but possible) for this entry to be clean, but
180272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // not actually the real entry. In other words, we could have lost this entry
180372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // from the index, and it could have been replaced with a newer one. It's not
180472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // worth checking that this entry is "the real one", so we just return it and
180572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // let the enumeration continue; this entry will be evicted at some point, and
180672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // the regular path will work with the real entry. With time, this problem
180772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // will disasappear because this scenario is just a bug.
180872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure that we save the key for later.
1810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->GetKey();
1811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return entry;
1813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1815c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::ResurrectEntry(EntryImpl* deleted_entry) {
1816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ENTRY_NORMAL == deleted_entry->entry()->Data()->state) {
1817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    deleted_entry->Release();
1818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::CREATE_MISS);
1819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Trace("create entry miss ");
1820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
1821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We are attempting to create an entry and found out that the entry was
1824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // previously deleted.
1825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnCreateEntry(deleted_entry);
1827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_++;
1828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  stats_.OnEvent(Stats::RESURRECT_HIT);
1830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Resurrect entry hit ");
1831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return deleted_entry;
1832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DestroyInvalidEntry(EntryImpl* entry) {
1835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(WARNING) << "Destroying invalid entry.";
1836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Destroying invalid entry 0x%p", entry);
1837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->SetPointerForInvalidEntry(GetCurrentEntryId());
1839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnDoomEntry(entry);
1841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->InternalDoom();
1842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!new_eviction_)
1844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DecreaseNumEntries();
1845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::INVALID_ENTRY);
1846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::AddStorageSize(int32 bytes) {
1849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.num_bytes += bytes;
1850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(data_->header.num_bytes, 0);
1851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SubstractStorageSize(int32 bytes) {
1854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.num_bytes -= bytes;
1855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(data_->header.num_bytes, 0);
1856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::IncreaseNumRefs() {
1859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_refs_++;
1860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_refs_ < num_refs_)
1861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_refs_ = num_refs_;
1862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DecreaseNumRefs() {
1865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(num_refs_);
1866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_refs_--;
1867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!num_refs_ && disabled_)
1869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    MessageLoop::current()->PostTask(FROM_HERE,
18703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        factory_.NewRunnableMethod(&BackendImpl::RestartCache, true));
1871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::IncreaseNumEntries() {
1874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.num_entries++;
1875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GT(data_->header.num_entries, 0);
1876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DecreaseNumEntries() {
1879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.num_entries--;
1880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data_->header.num_entries < 0) {
1881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
1882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->header.num_entries = 0;
1883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::LogStats() {
1887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  StatsItems stats;
1888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GetStats(&stats);
1889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1890731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (size_t index = 0; index < stats.size(); index++)
1891731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    VLOG(1) << stats[index].first << ": " << stats[index].second;
1892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::ReportStats() {
1895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "Entries", 0, data_->header.num_entries);
18963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int current_size = data_->header.num_bytes / (1024 * 1024);
18983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int max_size = max_size_ / (1024 * 1024);
18993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(COUNTS_10000, "Size2", 0, current_size);
19003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(COUNTS_10000, "MaxSize2", 0, max_size);
19013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!max_size)
19023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    max_size++;
19033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(PERCENTAGE, "UsedSpace", 0, current_size * 100 / max_size);
1904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS_10000, "AverageOpenEntries2", 0,
1906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            static_cast<int>(stats_.GetCounter(Stats::OPEN_ENTRIES)));
1907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS_10000, "MaxOpenEntries2", 0,
1908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            static_cast<int>(stats_.GetCounter(Stats::MAX_ENTRIES)));
1909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.SetCounter(Stats::MAX_ENTRIES, 0);
1910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  CACHE_UMA(COUNTS_10000, "TotalFatalErrors", 0,
19123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            static_cast<int>(stats_.GetCounter(Stats::FATAL_ERROR)));
19133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  CACHE_UMA(COUNTS_10000, "TotalDoomCache", 0,
19143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            static_cast<int>(stats_.GetCounter(Stats::DOOM_CACHE)));
19153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  CACHE_UMA(COUNTS_10000, "TotalDoomRecentEntries", 0,
19163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            static_cast<int>(stats_.GetCounter(Stats::DOOM_RECENT)));
191772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  stats_.SetCounter(Stats::FATAL_ERROR, 0);
191872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  stats_.SetCounter(Stats::DOOM_CACHE, 0);
191972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  stats_.SetCounter(Stats::DOOM_RECENT, 0);
19203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
19213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  int64 total_hours = stats_.GetCounter(Stats::TIMER) / 120;
19223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!data_->header.create_time || !data_->header.lru.filled) {
19233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int cause = data_->header.create_time ? 0 : 1;
19243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!data_->header.lru.filled)
19253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cause |= 2;
19263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CACHE_UMA(CACHE_ERROR, "ShortReport", 0, cause);
19273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    CACHE_UMA(HOURS, "TotalTimeNotFull", 0, static_cast<int>(total_hours));
1928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
19293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This is an up to date client that will report FirstEviction() data. After
1932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // that event, start reporting this:
1933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(HOURS, "TotalTime", 0, static_cast<int>(total_hours));
1935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 use_hours = stats_.GetCounter(Stats::LAST_REPORT_TIMER) / 120;
1937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.SetCounter(Stats::LAST_REPORT_TIMER, stats_.GetCounter(Stats::TIMER));
1938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We may see users with no use_hours at this point if this is the first time
1940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we are running this code.
1941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (use_hours)
1942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    use_hours = total_hours - use_hours;
1943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!use_hours || !GetEntryCount() || !data_->header.num_bytes)
1945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(HOURS, "UseTime", 0, static_cast<int>(use_hours));
19483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(PERCENTAGE, "HitRatio", data_->header.experiment,
19493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            stats_.GetHitRatio());
1950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 trim_rate = stats_.GetCounter(Stats::TRIM_ENTRY) / use_hours;
1952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "TrimRate", 0, static_cast<int>(trim_rate));
1953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int avg_size = data_->header.num_bytes / GetEntryCount();
1955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "EntrySize", 0, avg_size);
1956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS, "EntriesFull", 0, data_->header.num_entries);
1957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(PERCENTAGE, "IndexLoad", 0,
1959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            data_->header.num_entries * 100 / (mask_ + 1));
1960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int large_entries_bytes = stats_.GetLargeEntriesSize();
1962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int large_ratio = large_entries_bytes * 100 / data_->header.num_bytes;
1963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(PERCENTAGE, "LargeEntriesRatio", 0, large_ratio);
1964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (new_eviction_) {
19663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CACHE_UMA(PERCENTAGE, "ResurrectRatio", data_->header.experiment,
19673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              stats_.GetResurrectRatio());
1968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "NoUseRatio", 0,
1969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[0] * 100 / data_->header.num_entries);
1970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "LowUseRatio", 0,
1971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[1] * 100 / data_->header.num_entries);
1972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "HighUseRatio", 0,
1973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[2] * 100 / data_->header.num_entries);
19743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CACHE_UMA(PERCENTAGE, "DeletedRatio", data_->header.experiment,
1975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[4] * 100 / data_->header.num_entries);
1976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.ResetRatios();
1979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.SetCounter(Stats::TRIM_ENTRY, 0);
1980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cache_type_ == net::DISK_CACHE)
1982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    block_files_.ReportStats();
1983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::UpgradeTo2_1() {
1986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // 2.1 is basically the same as 2.0, except that new fields are actually
1987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // updated by the new eviction algorithm.
1988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(0x20000 == data_->header.version);
1989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.version = 0x20001;
1990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.lru.sizes[Rankings::NO_USE] = data_->header.num_entries;
1991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CheckIndex() {
1994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(data_);
1995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t current_size = index_->GetLength();
1997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (current_size < sizeof(Index)) {
1998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Corrupt Index file";
1999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (new_eviction_) {
2003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We support versions 2.0 and 2.1, upgrading 2.0 to 2.1.
2004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (kIndexMagic != data_->header.magic ||
2005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        kCurrentVersion >> 16 != data_->header.version >> 16) {
2006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(ERROR) << "Invalid file version or magic";
2007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
2008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (kCurrentVersion == data_->header.version) {
2010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // We need file version 2.1 for the new eviction algorithm.
2011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      UpgradeTo2_1();
2012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
2014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (kIndexMagic != data_->header.magic ||
2015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        kCurrentVersion != data_->header.version) {
2016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(ERROR) << "Invalid file version or magic";
2017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
2018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!data_->header.table_len) {
2022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Invalid table size";
2023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (current_size < GetIndexSize(data_->header.table_len) ||
2027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      data_->header.table_len & (kBaseTableLen - 1)) {
2028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Corrupt Index file";
2029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AdjustMaxCacheSize(data_->header.table_len);
2033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data_->header.num_bytes < 0 ||
2035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (max_size_ < kint32max - kDefaultCacheSize &&
2036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       data_->header.num_bytes > max_size_ + kDefaultCacheSize)) {
2037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Invalid cache (current) size";
2038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data_->header.num_entries < 0) {
2042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Invalid number of entries";
2043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!mask_)
2047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    mask_ = data_->header.table_len - 1;
2048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Load the table into memory with a single read.
2050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_array<char> buf(new char[current_size]);
2051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return index_->Read(buf.get(), current_size, 0);
2052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::CheckAllEntries() {
2055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_dirty = 0;
2056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_entries = 0;
2057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(mask_ < kuint32max);
2058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i <= static_cast<int>(mask_); i++) {
2059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Addr address(data_->table[i]);
2060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!address.is_initialized())
2061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
2062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (;;) {
2063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EntryImpl* tmp;
2064dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      int ret = NewEntry(address, &tmp);
2065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (ret)
2066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ret;
2067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      scoped_refptr<EntryImpl> cache_entry;
2068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cache_entry.swap(&tmp);
2069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2070dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (cache_entry->dirty())
2071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        num_dirty++;
2072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else if (CheckEntry(cache_entry.get()))
2073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        num_entries++;
2074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else
2075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ERR_INVALID_ENTRY;
2076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      address.set_value(cache_entry->GetNextAddress());
2078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!address.is_initialized())
2079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
2080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("CheckAllEntries End");
2084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (num_entries + num_dirty != data_->header.num_entries) {
2085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Number of entries mismatch";
2086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_NUM_ENTRIES_MISMATCH;
2087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return num_dirty;
2090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CheckEntry(EntryImpl* cache_entry) {
20933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool ok = block_files_.IsValid(cache_entry->entry()->address());
20943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ok = ok && block_files_.IsValid(cache_entry->rankings()->address());
20953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EntryStore* data = cache_entry->entry()->Data();
20963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (size_t i = 0; i < arraysize(data->data_addr); i++) {
20973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (data->data_addr[i]) {
20983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      Addr address(data->data_addr[i]);
20993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (address.is_block_file())
21003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ok = ok && block_files_.IsValid(address);
21013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
21023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
21033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RankingsNode* rankings = cache_entry->rankings()->Data();
21053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ok && !rankings->dummy;
21063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
21073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint BackendImpl::MaxBuffersSize() {
21093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static int64 total_memory = base::SysInfo::AmountOfPhysicalMemory();
21103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static bool done = false;
21113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!done) {
21133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const int kMaxBuffersSize = 30 * 1024 * 1024;
21143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // We want to use up to 2% of the computer's memory.
21163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    total_memory = total_memory * 2 / 100;
21173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (total_memory > kMaxBuffersSize || total_memory <= 0)
21183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      total_memory = kMaxBuffersSize;
21193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    done = true;
21213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
21223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return static_cast<int>(total_memory);
2124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace disk_cache
2127