backend_impl.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
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"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/rand_util.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/sys_info.h"
163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/worker_pool.h"
173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h"
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/time.h"
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/timer.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/cache_util.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/entry_impl.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/errors.h"
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/disk_cache/experiments.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/file.h"
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/disk_cache/hash.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/disk_cache/mem_backend_impl.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This has to be defined before including histogram_macros.h from this file.
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NET_DISK_CACHE_BACKEND_IMPL_CC_
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/histogram_macros.h"
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time;
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeDelta;
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks;
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* kIndexName = "index";
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kMaxOldFolders = 100;
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Seems like ~240 MB correspond to less than 50k entries for 99% of the people.
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Note that the actual target is to keep the index table load factor under 55%
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// for most users.
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int k64kEntriesStore = 240 * 1000 * 1000;
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kBaseTableLen = 64 * 1024;
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kDefaultCacheSize = 80 * 1024 * 1024;
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint DesiredIndexTableLen(int32 storage_size) {
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (storage_size <= k64kEntriesStore)
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kBaseTableLen;
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (storage_size <= k64kEntriesStore * 2)
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kBaseTableLen * 2;
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (storage_size <= k64kEntriesStore * 4)
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kBaseTableLen * 4;
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (storage_size <= k64kEntriesStore * 8)
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kBaseTableLen * 8;
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The biggest storage_size for int32 requires a 4 MB table.
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return kBaseTableLen * 16;
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MaxStorageSizeForTable(int table_len) {
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return table_len * (k64kEntriesStore / kBaseTableLen);
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t GetIndexSize(int table_len) {
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t table_size = sizeof(disk_cache::CacheAddr) * table_len;
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return sizeof(disk_cache::IndexHeader) + table_size;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns a fully qualified name from path and name, using a given name prefix
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and index number. For instance, if the arguments are "/foo", "bar" and 5, it
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// will return "/foo/old_bar_005".
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath GetPrefixedName(const FilePath& path, const std::string& name,
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         int index) {
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string tmp = base::StringPrintf("%s%s_%03d", "old_",
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       name.c_str(), index);
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return path.AppendASCII(tmp);
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is a simple Task to cleanup old caches.
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass CleanupTask : public Task {
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CleanupTask(const FilePath& path, const std::string& name)
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : path_(path), name_(name) {}
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void Run();
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path_;
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string name_;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CleanupTask);
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid CleanupTask::Run() {
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kMaxOldFolders; i++) {
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FilePath to_delete = GetPrefixedName(path_, name_, i);
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    disk_cache::DeleteCache(to_delete, true);
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Returns a full path to rename the current cache, in order to delete it. path
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is the current folder location, and name is the current folder name.
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath GetTempCacheName(const FilePath& path, const std::string& name) {
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We'll attempt to have up to kMaxOldFolders folders for deletion.
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kMaxOldFolders; i++) {
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FilePath to_delete = GetPrefixedName(path, name, i);
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!file_util::PathExists(to_delete))
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return to_delete;
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return FilePath();
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Moves the cache files to a new folder and creates a task to delete them.
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool DelayedCacheCleanup(const FilePath& full_path) {
119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // GetTempCacheName() and MoveCache() use synchronous file
120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // operations.
121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  base::ThreadRestrictions::ScopedAllowIO allow_io;
122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath current_path = full_path.StripTrailingSeparators();
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath path = current_path.DirName();
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath name = current_path.BaseName();
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX)
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string name_str = name.value();
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_WIN)
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We created this file so it should only contain ASCII.
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string name_str = WideToASCII(name.value());
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath to_delete = GetTempCacheName(path, name_str);
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (to_delete.empty()) {
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Unable to get another cache folder";
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!disk_cache::MoveCache(full_path, to_delete)) {
141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(ERROR) << "Unable to move cache folder";
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::WorkerPool::PostTask(FROM_HERE, new CleanupTask(path, name_str), true);
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Sets group for the current experiment. Returns false if the files should be
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// discarded.
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool InitExperiment(disk_cache::IndexHeader* header) {
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (header->experiment == disk_cache::EXPERIMENT_OLD_FILE1 ||
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      header->experiment == disk_cache::EXPERIMENT_OLD_FILE2) {
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Discard current cache.
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // See if we already defined the group for this profile.
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (header->experiment >= disk_cache::EXPERIMENT_DELETED_LIST_OUT)
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return true;
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // The experiment is closed.
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  header->experiment = disk_cache::EXPERIMENT_DELETED_LIST_OUT;
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Initializes the field trial structures to allow performance measurements
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// for the current cache configuration. Returns true if we are active part of
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the CacheThrottle field trial.
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SetFieldTrialInfo(int size_group) {
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static bool first = true;
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!first)
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
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);
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // After June 30, 2011 builds, it will always be in default group.
18421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  scoped_refptr<base::FieldTrial> trial2(
18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      new base::FieldTrial(
18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          "CacheThrottle", 100, "CacheThrottle_Default", 2011, 6, 30));
18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int group2a = trial2->AppendGroup("CacheThrottle_On", 10);  // 10 % in.
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  trial2->AppendGroup("CacheThrottle_Off", 10);  // 10 % control.
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return trial2->group() == group2a;
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------------------------------------------------
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class takes care of building an instance of the backend.
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CacheCreator {
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CacheCreator(const FilePath& path, bool force, int max_bytes,
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               net::CacheType type, uint32 flags,
2003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen               base::MessageLoopProxy* thread, net::NetLog* net_log,
2013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen               disk_cache::Backend** backend,
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               net::CompletionCallback* callback)
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : path_(path), force_(force), retry_(false), max_bytes_(max_bytes),
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        type_(type), flags_(flags), thread_(thread), backend_(backend),
2053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        callback_(callback), cache_(NULL), net_log_(net_log),
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ALLOW_THIS_IN_INITIALIZER_LIST(
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            my_callback_(this, &CacheCreator::OnIOComplete)) {
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~CacheCreator() {}
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Creates the backend.
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int Run();
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Callback implementation.
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnIOComplete(int result);
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void DoCallback(int result);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const FilePath& path_;
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool force_;
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool retry_;
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int max_bytes_;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CacheType type_;
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  uint32 flags_;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<base::MessageLoopProxy> thread_;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::Backend** backend_;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CompletionCallback* callback_;
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::BackendImpl* cache_;
2303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  net::NetLog* net_log_;
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::CompletionCallbackImpl<CacheCreator> my_callback_;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CacheCreator);
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CacheCreator::Run() {
2373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  cache_ = new disk_cache::BackendImpl(path_, thread_, net_log_);
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cache_->SetMaxSize(max_bytes_);
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cache_->SetType(type_);
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cache_->SetFlags(flags_);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = cache_->Init(&my_callback_);
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(net::ERR_IO_PENDING, rv);
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CacheCreator::OnIOComplete(int result) {
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result == net::OK || !force_ || retry_)
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return DoCallback(result);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is a failure and we are supposed to try again, so delete the object,
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // delete all the files, and try again.
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  retry_ = true;
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete cache_;
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cache_ = NULL;
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!DelayedCacheCleanup(path_))
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return DoCallback(result);
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The worker thread will start deleting files soon, but the original folder
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // is not there anymore... let's create a new set of files.
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = Run();
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(net::ERR_IO_PENDING, rv);
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CacheCreator::DoCallback(int result) {
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(net::ERR_IO_PENDING, result);
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result == net::OK) {
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *backend_ = cache_;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Unable to create cache";
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *backend_ = NULL;
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete cache_;
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  callback_->Run(result);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete this;
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------------------------------------------------
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A task to perform final cleanup on the background thread.
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass FinalCleanup : public Task {
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit FinalCleanup(disk_cache::BackendImpl* backend) : backend_(backend) {}
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~FinalCleanup() {}
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void Run();
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  disk_cache::BackendImpl* backend_;
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_EVIL_CONSTRUCTORS(FinalCleanup);
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid FinalCleanup::Run() {
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  backend_->CleanupCache();
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache {
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CreateCacheBackend(net::CacheType type, const FilePath& path, int max_bytes,
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       bool force, base::MessageLoopProxy* thread,
3033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                       net::NetLog* net_log, Backend** backend,
3043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                       CompletionCallback* callback) {
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(callback);
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (type == net::MEMORY_CACHE) {
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *backend = MemBackendImpl::CreateBackend(max_bytes);
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return *backend ? net::OK : net::ERR_FAILED;
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(thread);
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return BackendImpl::CreateBackend(path, force, max_bytes, type, kNone, thread,
3133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                    net_log, backend, callback);
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the preferred maximum number of bytes for the cache given the
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// number of available bytes.
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint PreferedCacheSize(int64 available) {
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return 80% of the available space if there is not enough space to use
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // kDefaultCacheSize.
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (available < kDefaultCacheSize * 10 / 8)
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return static_cast<int32>(available * 8 / 10);
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return kDefaultCacheSize if it uses 80% to 10% of the available space.
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (available < kDefaultCacheSize * 10)
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kDefaultCacheSize;
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return 10% of the available space if the target size
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (2.5 * kDefaultCacheSize) is more than 10%.
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (available < static_cast<int64>(kDefaultCacheSize) * 25)
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return static_cast<int32>(available / 10);
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return the target size (2.5 * kDefaultCacheSize) if it uses 10% to 1%
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // of the available space.
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (available < static_cast<int64>(kDefaultCacheSize) * 250)
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return kDefaultCacheSize * 5 / 2;
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return 1% of the available space if it does not exceed kint32max.
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (available < static_cast<int64>(kint32max) * 100)
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return static_cast<int32>(available / 100);
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return kint32max;
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBackendImpl::BackendImpl(const FilePath& path,
3483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         base::MessageLoopProxy* cache_thread,
3493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         net::NetLog* net_log)
3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : ALLOW_THIS_IN_INITIALIZER_LIST(background_queue_(this, cache_thread)),
3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      path_(path),
3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      block_files_(path),
3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      mask_(0),
3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      max_size_(0),
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      io_delay_(0),
3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cache_type_(net::DISK_CACHE),
3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      uma_report_(0),
3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      user_flags_(0),
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      init_(false),
3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      restarted_(false),
3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      unit_test_(false),
3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      read_only_(false),
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new_eviction_(false),
3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      first_timer_(true),
3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      throttle_requests_(false),
3663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      net_log_(net_log),
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      done_(true, false),
3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)),
3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {
3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBackendImpl::BackendImpl(const FilePath& path,
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         uint32 mask,
3743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         base::MessageLoopProxy* cache_thread,
3753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         net::NetLog* net_log)
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : ALLOW_THIS_IN_INITIALIZER_LIST(background_queue_(this, cache_thread)),
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      path_(path),
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      block_files_(path),
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      mask_(mask),
3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      max_size_(0),
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      io_delay_(0),
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cache_type_(net::DISK_CACHE),
3833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      uma_report_(0),
3843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      user_flags_(kMask),
3853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      init_(false),
3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      restarted_(false),
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      unit_test_(false),
3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      read_only_(false),
3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new_eviction_(false),
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      first_timer_(true),
3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      throttle_requests_(false),
3923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen      net_log_(net_log),
3933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      done_(true, false),
3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)),
3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {
3963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBackendImpl::~BackendImpl() {
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  background_queue_.WaitForPendingIO();
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (background_queue_.BackgroundIsCurrentThread()) {
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Unit tests may use the same thread for everything.
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CleanupCache();
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    background_queue_.background_thread()->PostTask(FROM_HERE,
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                    new FinalCleanup(this));
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    done_.Wait();
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// If the initialization of the cache fails, and force is true, we will discard
41272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// the whole cache and create a new one. In order to process a potentially large
41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// number of files, we'll rename the cache folder to old_ + original_name +
41472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// number, (located on the same parent folder), and spawn a worker thread to
41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// delete all the files on all the stale cache folders. The whole process can
41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// still fail if we are not able to rename the cache folder (for instance due to
41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// a sharing violation), and in that case a cache for this profile (on the
41872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// desired path) cannot be created.
41972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//
42072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Static.
42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint BackendImpl::CreateBackend(const FilePath& full_path, bool force,
42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               int max_bytes, net::CacheType type,
42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               uint32 flags, base::MessageLoopProxy* thread,
42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               net::NetLog* net_log, Backend** backend,
42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                               CompletionCallback* callback) {
42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(callback);
42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CacheCreator* creator = new CacheCreator(full_path, force, max_bytes, type,
42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                           flags, thread, net_log, backend,
42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                           callback);
43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // This object will self-destroy when finished.
43172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return creator->Run();
43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
43472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint BackendImpl::Init(CompletionCallback* callback) {
43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  background_queue_.Init(callback);
43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return net::ERR_IO_PENDING;
43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncInit() {
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!init_);
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (init_)
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool create_files = false;
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!InitBackingStore(&create_files)) {
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportError(ERR_STORAGE_ERROR);
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_refs_ = num_pending_io_ = max_refs_ = 0;
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_ = byte_count_ = 0;
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!restarted_) {
4543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buffer_bytes_ = 0;
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    trace_object_ = TraceObject::GetTraceObject();
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Create a recurrent timer of 30 secs.
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int timer_delay = unit_test_ ? 1000 : 30000;
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    timer_.Start(TimeDelta::FromMilliseconds(timer_delay), this,
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                 &BackendImpl::OnStatsTimer);
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  init_ = true;
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (data_->header.experiment != NO_EXPERIMENT &&
4653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cache_type_ != net::DISK_CACHE) {
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // No experiment for other caches.
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!(user_flags_ & disk_cache::kNoRandom)) {
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The unit test controls directly what to test.
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    new_eviction_ = (cache_type_ == net::DISK_CACHE);
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!CheckIndex()) {
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportError(ERR_INIT_FAILED);
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!(user_flags_ & disk_cache::kNoRandom) &&
4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cache_type_ == net::DISK_CACHE &&
482731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      !InitExperiment(&data_->header))
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return net::ERR_FAILED;
4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We don't care if the value overflows. The only thing we care about is that
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the id cannot be zero, because that value is used as "not dirty".
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Increasing the value once per second gives us many years before we start
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // having collisions.
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.this_id++;
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!data_->header.this_id)
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->header.this_id++;
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data_->header.crash) {
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportError(ERR_PREVIOUS_CRASH);
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportError(0);
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->header.crash = 1;
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!block_files_.Init(create_files))
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We want to minimize the changes to cache for an AppCache.
5043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (cache_type() == net::APP_CACHE) {
5053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(!new_eviction_);
5063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    read_only_ = true;
5073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
5083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // stats_ and rankings_ may end up calling back to us so we better be enabled.
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disabled_ = false;
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!stats_.Init(this, &data_->header.stats))
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disabled_ = !rankings_.Init(this, new_eviction_);
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.Init(this);
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Setup load-time data only for the main cache.
5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!throttle_requests_ && cache_type() == net::DISK_CACHE)
5193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    throttle_requests_ = SetFieldTrialInfo(GetSizeGroup());
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return disabled_ ? net::ERR_FAILED : net::OK;
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackendImpl::CleanupCache() {
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Trace("Backend Cleanup");
5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  eviction_.Stop();
5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  timer_.Stop();
5283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (init_) {
5303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    stats_.Store();
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (data_)
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data_->header.crash = 0;
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    File::WaitForPendingIO(&num_pending_io_);
5353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (user_flags_ & kNoRandom) {
5363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // This is a net_unittest, verify that we are not 'leaking' entries.
5373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(!num_refs_);
5383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
5403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  block_files_.CloseFiles();
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  factory_.RevokeAll();
5423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ptr_factory_.InvalidateWeakPtrs();
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  done_.Signal();
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::OpenPrevEntry(void** iter, Entry** prev_entry,
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               CompletionCallback* callback) {
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(callback);
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  background_queue_.OpenPrevEntry(iter, prev_entry, callback);
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncOpenEntry(const std::string& key, Entry** entry) {
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(entry);
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *entry = OpenEntryImpl(key);
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (*entry) ? net::OK : net::ERR_FAILED;
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncCreateEntry(const std::string& key, Entry** entry) {
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(entry);
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *entry = CreateEntryImpl(key);
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (*entry) ? net::OK : net::ERR_FAILED;
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncDoomEntry(const std::string& key) {
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (disabled_)
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EntryImpl* entry = OpenEntryImpl(key);
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!entry)
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->DoomImpl();
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->Release();
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::OK;
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncDoomAllEntries() {
5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This is not really an error, but it is an interesting condition.
5823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ReportError(ERR_CACHE_DOOMED);
5833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats_.OnEvent(Stats::DOOM_CACHE);
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!num_refs_) {
5853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    RestartCache(false);
5863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return disabled_ ? net::ERR_FAILED : net::OK;
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (disabled_)
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return net::ERR_FAILED;
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    eviction_.TrimCache(true);
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::OK;
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncDoomEntriesBetween(const base::Time initial_time,
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        const base::Time end_time) {
5983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_NE(net::APP_CACHE, cache_type_);
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (end_time.is_null())
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return SyncDoomEntriesSince(initial_time);
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(end_time >= initial_time);
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (disabled_)
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EntryImpl* node;
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void* iter = NULL;
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EntryImpl* next = OpenNextEntryImpl(&iter);
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!next)
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::OK;
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (next) {
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node = next;
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next = OpenNextEntryImpl(&iter);
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (node->GetLastUsed() >= initial_time &&
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        node->GetLastUsed() < end_time) {
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      node->DoomImpl();
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else if (node->GetLastUsed() < initial_time) {
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (next)
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        next->Release();
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next = NULL;
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SyncEndEnumeration(iter);
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node->Release();
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::OK;
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We use OpenNextEntryImpl to retrieve elements from the cache, until we get
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// entries that are too old.
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncDoomEntriesSince(const base::Time initial_time) {
6363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_NE(net::APP_CACHE, cache_type_);
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_FAILED;
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats_.OnEvent(Stats::DOOM_RECENT);
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (;;) {
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* iter = NULL;
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EntryImpl* entry = OpenNextEntryImpl(&iter);
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!entry)
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return net::OK;
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (initial_time > entry->GetLastUsed()) {
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      entry->Release();
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SyncEndEnumeration(iter);
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return net::OK;
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    entry->DoomImpl();
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    entry->Release();
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SyncEndEnumeration(iter);  // Dooming the entry invalidates the iterator.
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncOpenNextEntry(void** iter, Entry** next_entry) {
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *next_entry = OpenNextEntryImpl(iter);
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (*next_entry) ? net::OK : net::ERR_FAILED;
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::SyncOpenPrevEntry(void** iter, Entry** prev_entry) {
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *prev_entry = OpenPrevEntryImpl(iter);
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (*prev_entry) ? net::OK : net::ERR_FAILED;
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackendImpl::SyncEndEnumeration(void* iter) {
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<Rankings::Iterator> iterator(
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      reinterpret_cast<Rankings::Iterator*>(iter));
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::OpenEntryImpl(const std::string& key) {
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (disabled_)
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint32 hash = Hash(key);
6803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("Open hash 0x%x", hash);
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool error;
68372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EntryImpl* cache_entry = MatchEntry(key, hash, false, Addr(), &error);
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry) {
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::OPEN_MISS);
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ENTRY_NORMAL != cache_entry->entry()->Data()->state) {
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The entry was already evicted.
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cache_entry->Release();
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::OPEN_MISS);
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnOpenEntry(cache_entry);
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_++;
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(AGE_MS, "OpenTime", GetSizeGroup(), start);
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::OPEN_HIT);
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return cache_entry;
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::CreateEntryImpl(const std::string& key) {
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_ || key.empty())
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint32 hash = Hash(key);
7103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("Create hash 0x%x", hash);
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<EntryImpl> parent;
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr entry_address(data_->table[hash & mask_]);
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (entry_address.is_initialized()) {
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We have an entry already. It could be the one we are looking for, or just
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // a hash conflict.
71772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    bool error;
71872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EntryImpl* old_entry = MatchEntry(key, hash, false, Addr(), &error);
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (old_entry)
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ResurrectEntry(old_entry);
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    EntryImpl* parent_entry = MatchEntry(key, hash, true, Addr(), &error);
72372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(!error);
7243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (parent_entry) {
7253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      parent.swap(&parent_entry);
7263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (data_->table[hash & mask_]) {
7273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // We should have corrected the problem.
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NOTREACHED();
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return NULL;
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_blocks;
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t key1_len = sizeof(EntryStore) - offsetof(EntryStore, key);
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (key.size() < key1_len ||
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      key.size() > static_cast<size_t>(kMaxInternalKeyLength))
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    num_blocks = 1;
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    num_blocks = static_cast<int>((key.size() - key1_len) / 256 + 2);
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!block_files_.CreateBlock(BLOCK_256, num_blocks, &entry_address)) {
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Create entry failed " << key.c_str();
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::CREATE_ERROR);
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr node_address(0);
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!block_files_.CreateBlock(RANKINGS, 1, &node_address)) {
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    block_files_.DeleteBlock(entry_address, false);
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Create entry failed " << key.c_str();
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::CREATE_ERROR);
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<EntryImpl> cache_entry(
7563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new EntryImpl(this, entry_address, false));
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IncreaseNumRefs();
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry->CreateEntry(node_address, key, hash)) {
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    block_files_.DeleteBlock(entry_address, false);
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    block_files_.DeleteBlock(node_address, false);
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Create entry failed " << key.c_str();
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::CREATE_ERROR);
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  cache_entry->BeginLogging(net_log_, true);
7683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We are not failing the operation; let's add this to the map.
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  open_entries_[entry_address.value()] = cache_entry;
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (parent.get())
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent->SetNextAddress(entry_address);
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  block_files_.GetFile(entry_address)->Store(cache_entry->entry());
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  block_files_.GetFile(node_address)->Store(cache_entry->rankings());
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IncreaseNumEntries();
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnCreateEntry(cache_entry);
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_++;
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!parent.get())
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->table[hash & mask_] = entry_address.value();
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(AGE_MS, "CreateTime", GetSizeGroup(), start);
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::CREATE_HIT);
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("create entry hit ");
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return cache_entry.release();
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::OpenNextEntryImpl(void** iter) {
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OpenFollowingEntry(true, iter);
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
794c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::OpenPrevEntryImpl(void** iter) {
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OpenFollowingEntry(false, iter);
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::SetMaxSize(int max_bytes) {
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  COMPILE_ASSERT(sizeof(max_bytes) == sizeof(max_size_), unsupported_int_model);
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_bytes < 0)
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Zero size means use the default.
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!max_bytes)
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Avoid a DCHECK later on.
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_bytes >= kint32max - kint32max / 10)
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_bytes = kint32max - kint32max / 10 - 1;
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= kMaxSize;
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  max_size_ = max_bytes;
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetType(net::CacheType type) {
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(type != net::MEMORY_CACHE);
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cache_type_ = type;
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFilePath BackendImpl::GetFileName(Addr address) const {
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!address.is_separate_file() || !address.is_initialized()) {
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return FilePath();
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string tmp = base::StringPrintf("f_%06x", address.FileNumber());
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return path_.AppendASCII(tmp);
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMappedFile* BackendImpl::File(Addr address) {
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return block_files_.GetFile(address);
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CreateExternalFile(Addr* address) {
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int file_number = data_->header.last_file + 1;
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr file_address(0);
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool success = false;
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < 0x0fffffff; i++, file_number++) {
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!file_address.SetFileNumber(file_number)) {
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      file_number = 1;
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    FilePath name = GetFileName(file_address);
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int flags = base::PLATFORM_FILE_READ |
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                base::PLATFORM_FILE_WRITE |
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                base::PLATFORM_FILE_CREATE |
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                base::PLATFORM_FILE_EXCLUSIVE_WRITE;
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    scoped_refptr<disk_cache::File> file(new disk_cache::File(
8523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        base::CreatePlatformFile(name, flags, NULL, NULL)));
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!file->IsValid())
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    success = true;
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    break;
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(success);
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!success)
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.last_file = file_number;
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  address->set_value(file_address.value());
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CreateBlock(FileType block_type, int block_count,
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             Addr* block_address) {
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return block_files_.CreateBlock(block_type, block_count, block_address);
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DeleteBlock(Addr block_address, bool deep) {
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  block_files_.DeleteBlock(block_address, deep);
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottLruData* BackendImpl::GetLruData() {
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return &data_->header.lru;
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::UpdateRank(EntryImpl* entry, bool modified) {
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!read_only_) {
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    eviction_.UpdateRank(entry, modified);
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::RecoveredEntry(CacheRankingsBlock* rankings) {
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(rankings->Data()->contents);
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntryImpl* cache_entry = NULL;
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool dirty;
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NewEntry(address, &cache_entry, &dirty))
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint32 hash = cache_entry->GetHash();
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cache_entry->Release();
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Anything on the table means that this entry is there.
899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data_->table[hash & mask_])
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->table[hash & mask_] = address.value();
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::InternalDoomEntry(EntryImpl* entry) {
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uint32 hash = entry->GetHash();
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string key = entry->GetKey();
90872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Addr entry_addr = entry->entry()->address();
90972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool error;
91072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EntryImpl* parent_entry = MatchEntry(key, hash, true, entry_addr, &error);
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheAddr child(entry->GetNextAddress());
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Doom entry 0x%p", entry);
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnDoomEntry(entry);
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->InternalDoom();
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (parent_entry) {
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent_entry->SetNextAddress(Addr(child));
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent_entry->Release();
92172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (!error) {
922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->table[hash & mask_] = child;
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!new_eviction_) {
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DecreaseNumEntries();
927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::DOOM_ENTRY);
930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// An entry may be linked on the DELETED list for a while after being doomed.
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This function is called when we want to remove it.
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::RemoveEntry(EntryImpl* entry) {
935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!new_eviction_)
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ENTRY_NORMAL != entry->entry()->Data()->state);
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Remove entry 0x%p", entry);
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnDestroyEntry(entry);
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DecreaseNumEntries();
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackendImpl::OnEntryDestroyBegin(Addr address) {
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntriesMap::iterator it = open_entries_.find(address.value());
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != open_entries_.end())
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    open_entries_.erase(it);
9493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
9503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
9513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackendImpl::OnEntryDestroyEnd() {
952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DecreaseNumRefs();
9533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (data_->header.num_bytes > max_size_ && !read_only_)
9543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    eviction_.TrimCache(false);
955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEntryImpl* BackendImpl::GetOpenEntry(CacheRankingsBlock* rankings) const {
958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(rankings->HasData());
959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntriesMap::const_iterator it =
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      open_entries_.find(rankings->Data()->contents);
961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != open_entries_.end()) {
962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We have this entry in memory.
963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return it->second;
964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return NULL;
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint32 BackendImpl::GetCurrentEntryId() const {
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return data_->header.this_id;
971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::MaxFileSize() const {
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return max_size_ / 8;
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::ModifyStorageSize(int32 old_size, int32 new_size) {
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_ || old_size == new_size)
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (old_size > new_size)
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SubstractStorageSize(old_size - new_size);
982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AddStorageSize(new_size - old_size);
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Update the usage statistics.
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.ModifyStorageStats(old_size, new_size);
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::TooMuchStorageRequested(int32 size) {
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.ModifyStorageStats(0, size);
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool BackendImpl::IsAllocAllowed(int current_size, int new_size) {
9943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GT(new_size, current_size);
9953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (user_flags_ & kNoBuffering)
9963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
9973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
9983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int to_add = new_size - current_size;
9993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (buffer_bytes_ + to_add > MaxBuffersSize())
10003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
10013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  buffer_bytes_ += to_add;
10033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(COUNTS_50000, "BufferBytes", 0, buffer_bytes_ / 1024);
10043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
10053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
10063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackendImpl::BufferDeleted(int size) {
10083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  buffer_bytes_ -= size;
10093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(size, 0);
10103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
10113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::IsLoaded() const {
1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "PendingIO", GetSizeGroup(), num_pending_io_);
1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (user_flags_ & kNoLoadProtection)
1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return num_pending_io_ > 5;
1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string BackendImpl::HistogramName(const char* name, int experiment) const {
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!experiment)
10223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return base::StringPrintf("DiskCache.%d.%s", cache_type_, name);
10233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return base::StringPrintf("DiskCache.%d.%s_%d", cache_type_,
10243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            name, experiment);
10253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
10263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbase::WeakPtr<BackendImpl> BackendImpl::GetWeakPtr() {
10283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ptr_factory_.GetWeakPtr();
1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::GetSizeGroup() const {
1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We want to report times grouped by the current cache size (50 MB groups).
1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int group = data_->header.num_bytes / (50 * 1024 * 1024);
1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (group > 6)
1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    group = 6;  // Limit the number of groups, just in case.
1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return group;
1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We want to remove biases from some histograms so we only send data once per
1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// week.
1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::ShouldReportAgain() {
1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (uma_report_)
1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return uma_report_ == 2;
1047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  uma_report_++;
1049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 last_report = stats_.GetCounter(Stats::LAST_REPORT);
1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Time last_time = Time::FromInternalValue(last_report);
1051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!last_report || (Time::Now() - last_time).InDays() >= 7) {
1052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.SetCounter(Stats::LAST_REPORT, Time::Now().ToInternalValue());
1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    uma_report_++;
1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return false;
1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::FirstEviction() {
1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(data_->header.create_time);
1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Time create_time = Time::FromInternalValue(data_->header.create_time);
1063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(AGE, "FillupAge", 0, create_time);
1064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 use_time = stats_.GetCounter(Stats::TIMER);
1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(HOURS, "FillupTime", 0, static_cast<int>(use_time / 120));
1067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(PERCENTAGE, "FirstHitRatio", 0, stats_.GetHitRatio());
1068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!use_time)
1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    use_time = 1;
1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS_10000, "FirstEntryAccessRate", 0,
1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            static_cast<int>(data_->header.num_entries / use_time));
1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS, "FirstByteIORate", 0,
1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            static_cast<int>((data_->header.num_bytes / 1024) / use_time));
1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int avg_size = data_->header.num_bytes / GetEntryCount();
1077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "FirstEntrySize", 0, avg_size);
1078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int large_entries_bytes = stats_.GetLargeEntriesSize();
1080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int large_ratio = large_entries_bytes * 100 / data_->header.num_bytes;
1081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(PERCENTAGE, "FirstLargeEntriesRatio", 0, large_ratio);
1082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (new_eviction_) {
1084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "FirstResurrectRatio", 0, stats_.GetResurrectRatio());
1085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "FirstNoUseRatio", 0,
1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[0] * 100 / data_->header.num_entries);
1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "FirstLowUseRatio", 0,
1088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[1] * 100 / data_->header.num_entries);
1089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "FirstHighUseRatio", 0,
1090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[2] * 100 / data_->header.num_entries);
1091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.ResetRatios();
1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::CriticalError(int error) {
1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(ERROR) << "Critical error found " << error;
1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats_.OnEvent(Stats::FATAL_ERROR);
1102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LogStats();
1103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ReportError(error);
1104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Setting the index table length to an invalid value will force re-creation
1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of the cache files.
1107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.table_len = 1;
1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disabled_ = true;
1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!num_refs_)
1111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    MessageLoop::current()->PostTask(FROM_HERE,
11123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        factory_.NewRunnableMethod(&BackendImpl::RestartCache, true));
1113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::ReportError(int error) {
1116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We transmit positive numbers, instead of direct error codes.
1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_LE(error, 0);
1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(CACHE_ERROR, "Error", 0, error * -1);
1119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::OnEvent(Stats::Counters an_event) {
1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(an_event);
1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackendImpl::OnRead(int32 bytes) {
1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(bytes, 0);
1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  byte_count_ += bytes;
1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (byte_count_ < 0)
1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    byte_count_ = kint32max;
1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackendImpl::OnWrite(int32 bytes) {
1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We use the same implementation as OnRead... just log the number of bytes.
1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OnRead(bytes);
1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BackendImpl::OnOperationCompleted(base::TimeDelta elapsed_time) {
11383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(TIMES, "TotalIOTime", 0, elapsed_time);
11393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (cache_type() != net::DISK_CACHE)
11413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
11423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
114321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UMA_HISTOGRAM_TIMES(base::FieldTrial::MakeName("DiskCache.TotalIOTime",
114421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                                 "CacheThrottle").data(),
114521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                      elapsed_time);
114621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!throttle_requests_)
11483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
11493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
115072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const int kMaxNormalDelayMS = 460;
11513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool throttling = io_delay_ > kMaxNormalDelayMS;
11533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We keep a simple exponential average of elapsed_time.
11553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  io_delay_ = (io_delay_ + static_cast<int>(elapsed_time.InMilliseconds())) / 2;
11563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (io_delay_ > kMaxNormalDelayMS && !throttling)
11573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    background_queue_.StartQueingOperations();
11583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  else if (io_delay_ <= kMaxNormalDelayMS && throttling)
11593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    background_queue_.StopQueingOperations();
11603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::OnStatsTimer() {
1163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::TIMER);
1164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 time = stats_.GetCounter(Stats::TIMER);
1165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 current = stats_.GetCounter(Stats::OPEN_ENTRIES);
1166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // OPEN_ENTRIES is a sampled average of the number of open entries, avoiding
1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the bias towards 0.
1169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (num_refs_ && (current != num_refs_)) {
1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int64 diff = (num_refs_ - current) / 50;
1171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!diff)
1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      diff = num_refs_ > current ? 1 : -1;
1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    current = current + diff;
1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.SetCounter(Stats::OPEN_ENTRIES, current);
1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.SetCounter(Stats::MAX_ENTRIES, max_refs_);
1176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "NumberOfReferences", 0, num_refs_);
1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS_10000, "EntryAccessRate", 0, entry_count_);
1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS, "ByteIORate", 0, byte_count_ / 1024);
1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_ = 0;
1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  byte_count_ = 0;
1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!data_)
1186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    first_timer_ = false;
1187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (first_timer_) {
1188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    first_timer_ = false;
1189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (ShouldReportAgain())
1190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ReportStats();
1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Save stats to disk at 5 min intervals.
1194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (time % 10 == 0)
1195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.Store();
1196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::IncrementIoCount() {
1199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_pending_io_++;
1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DecrementIoCount() {
1203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_pending_io_--;
1204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetUnitTestMode() {
1207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= kUnitTestMode;
1208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  unit_test_ = true;
1209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetUpgradeMode() {
1212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= kUpgradeMode;
1213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_only_ = true;
1214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetNewEviction() {
1217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= kNewEviction;
1218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  new_eviction_ = true;
1219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SetFlags(uint32 flags) {
1222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  user_flags_ |= flags;
1223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::ClearRefCountForTest() {
1226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_refs_ = 0;
1227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BackendImpl::FlushQueueForTest(CompletionCallback* callback) {
1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  background_queue_.FlushQueue(callback);
1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint BackendImpl::RunTaskForTest(Task* task, CompletionCallback* callback) {
12353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  background_queue_.RunTask(task, callback);
12363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return net::ERR_IO_PENDING;
12373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
12383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1239513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackendImpl::ThrottleRequestsForTest(bool throttle) {
1240513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (throttle)
1241513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    background_queue_.StartQueingOperations();
1242513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  else
1243513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    background_queue_.StopQueingOperations();
1244513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
1245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
124672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BackendImpl::TrimForTest(bool empty) {
124772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  eviction_.SetTestMode();
124872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  eviction_.TrimCache(empty);
124972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
125072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
125172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BackendImpl::TrimDeletedListForTest(bool empty) {
125272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  eviction_.SetTestMode();
125372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  eviction_.TrimDeletedList(empty);
125472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
125572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::SelfCheck() {
1257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!init_) {
1258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Init failed";
1259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INIT_FAILED;
1260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_entries = rankings_.SelfCheck();
1263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (num_entries < 0) {
1264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Invalid rankings list, error " << num_entries;
1265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return num_entries;
1266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (num_entries != data_->header.num_entries) {
1269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Number of entries mismatch";
1270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_NUM_ENTRIES_MISMATCH;
1271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return CheckAllEntries();
1274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
1277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint32 BackendImpl::GetEntryCount() const {
12793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (!index_ || disabled_)
12803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return 0;
12813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // num_entries includes entries already evicted.
12823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  int32 not_deleted = data_->header.num_entries -
12833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                      data_->header.lru.sizes[Rankings::DELETED];
12843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (not_deleted < 0) {
12863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    NOTREACHED();
12873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    not_deleted = 0;
12883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
12893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return not_deleted;
12913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
12923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
12933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::OpenEntry(const std::string& key, Entry** entry,
12943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                           CompletionCallback* callback) {
12953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
12963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.OpenEntry(key, entry, callback);
12973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
12983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
12993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::CreateEntry(const std::string& key, Entry** entry,
13013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                             CompletionCallback* callback) {
13023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.CreateEntry(key, entry, callback);
13043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::DoomEntry(const std::string& key,
13083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                           CompletionCallback* callback) {
13093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.DoomEntry(key, callback);
13113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::DoomAllEntries(CompletionCallback* callback) {
13153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.DoomAllEntries(callback);
13173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::DoomEntriesBetween(const base::Time initial_time,
13213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                    const base::Time end_time,
13223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                    CompletionCallback* callback) {
13233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.DoomEntriesBetween(initial_time, end_time, callback);
13253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::DoomEntriesSince(const base::Time initial_time,
13293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                                  CompletionCallback* callback) {
13303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.DoomEntriesSince(initial_time, callback);
13323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint BackendImpl::OpenNextEntry(void** iter, Entry** next_entry,
13363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                               CompletionCallback* callback) {
13373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  DCHECK(callback);
13383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.OpenNextEntry(iter, next_entry, callback);
13393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  return net::ERR_IO_PENDING;
13403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BackendImpl::EndEnumeration(void** iter) {
13433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  background_queue_.EndEnumeration(*iter);
13443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  *iter = NULL;
13453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BackendImpl::GetStats(StatsItems* stats) {
13483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (disabled_)
13493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    return;
13503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  std::pair<std::string, std::string> item;
13523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.first = "Entries";
13543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.second = base::StringPrintf("%d", data_->header.num_entries);
13553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats->push_back(item);
13563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.first = "Pending IO";
13583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.second = base::StringPrintf("%d", num_pending_io_);
13593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats->push_back(item);
13603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.first = "Max size";
13623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.second = base::StringPrintf("%d", max_size_);
13633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats->push_back(item);
13643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.first = "Current size";
13663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  item.second = base::StringPrintf("%d", data_->header.num_bytes);
13673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats->push_back(item);
13683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  stats_.GetItems(stats);
13703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen}
13713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
13723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// ------------------------------------------------------------------------
13733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
1374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We just created a new file so we're going to write the header and set the
1375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// file length to include the hash table (zero filled).
1376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CreateBackingStore(disk_cache::File* file) {
1377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AdjustMaxCacheSize(0);
1378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IndexHeader header;
1380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  header.table_len = DesiredIndexTableLen(max_size_);
1381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We need file version 2.1 for the new eviction algorithm.
1383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (new_eviction_)
1384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    header.version = 0x20001;
1385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  header.create_time = Time::Now().ToInternalValue();
1387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file->Write(&header, sizeof(header), 0))
1389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return file->SetLength(GetIndexSize(header.table_len));
1392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::InitBackingStore(bool* file_created) {
1395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file_util::CreateDirectory(path_);
1396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FilePath index_name = path_.AppendASCII(kIndexName);
1398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int flags = base::PLATFORM_FILE_READ |
1400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              base::PLATFORM_FILE_WRITE |
1401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              base::PLATFORM_FILE_OPEN_ALWAYS |
1402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              base::PLATFORM_FILE_EXCLUSIVE_WRITE;
1403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<disk_cache::File> file(new disk_cache::File(
14043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::CreatePlatformFile(index_name, flags, file_created, NULL)));
1405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file->IsValid())
1407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool ret = true;
1410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (*file_created)
1411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ret = CreateBackingStore(file);
1412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file = NULL;
1414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ret)
1415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  index_ = new MappedFile();
1418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_ = reinterpret_cast<Index*>(index_->Init(index_name, 0));
1419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!data_) {
1420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Unable to map Index file";
1421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index_->GetLength() < sizeof(Index)) {
1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We verify this again on CheckIndex() but it's easier to make sure now
1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // that the header is there.
1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Corrupt Index file";
1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
1432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The maximum cache size will be either set explicitly by the caller, or
1435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// calculated by this code.
1436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::AdjustMaxCacheSize(int table_len) {
1437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_size_)
1438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If table_len is provided, the index file exists.
1441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!table_len || data_->header.magic);
1442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The user is not setting the size, let's figure it out.
144400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#ifdef ANDROID
144500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int64 available = 10 * 1024 * 1024; // 10 MB
144600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#else
1447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 available = base::SysInfo::AmountOfFreeDiskSpace(path_);
144800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#endif
1449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (available < 0) {
1450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_size_ = kDefaultCacheSize;
1451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (table_len)
1455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    available += data_->header.num_bytes;
1456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  max_size_ = PreferedCacheSize(available);
1458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Let's not use more than the default size while we tune-up the performance
1460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of bigger caches. TODO(rvargas): remove this limit.
1461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_size_ > kDefaultCacheSize * 4)
1462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_size_ = kDefaultCacheSize * 4;
1463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!table_len)
1465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If we already have a table, adjust the size to it.
1468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int current_max_size = MaxStorageSizeForTable(table_len);
1469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_size_ > current_max_size)
1470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_size_= current_max_size;
1471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid BackendImpl::RestartCache(bool failure) {
1474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 errors = stats_.GetCounter(Stats::FATAL_ERROR);
14753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  int64 full_dooms = stats_.GetCounter(Stats::DOOM_CACHE);
14763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  int64 partial_dooms = stats_.GetCounter(Stats::DOOM_RECENT);
147772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int64 last_report = stats_.GetCounter(Stats::LAST_REPORT);
14783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
14793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  PrepareForRestart();
14803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  if (failure) {
14813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DCHECK(!num_refs_);
14823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DCHECK(!open_entries_.size());
14833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DelayedCacheCleanup(path_);
14843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  } else {
14853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    DeleteCache(path_, false);
14863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
1487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Don't call Init() if directed by the unit test: we are simulating a failure
1489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // trying to re-enable the cache.
1490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (unit_test_)
1491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    init_ = true;  // Let the destructor do proper cleanup.
14923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  else if (SyncInit() == net::OK) {
14933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    stats_.SetCounter(Stats::FATAL_ERROR, errors);
14943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    stats_.SetCounter(Stats::DOOM_CACHE, full_dooms);
14953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    stats_.SetCounter(Stats::DOOM_RECENT, partial_dooms);
149672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    stats_.SetCounter(Stats::LAST_REPORT, last_report);
14973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  }
1498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::PrepareForRestart() {
1501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Reset the mask_ if it was not given by the user.
1502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!(user_flags_ & kMask))
1503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    mask_ = 0;
1504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!(user_flags_ & kNewEviction))
1506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    new_eviction_ = false;
1507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  disabled_ = true;
1509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.crash = 0;
1510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  index_ = NULL;
1511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_ = NULL;
1512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  block_files_.CloseFiles();
1513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rankings_.Reset();
1514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  init_ = false;
1515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  restarted_ = true;
1516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::NewEntry(Addr address, EntryImpl** entry, bool* dirty) {
1519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntriesMap::iterator it = open_entries_.find(address.value());
1520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != open_entries_.end()) {
1521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Easy job. This entry is already in memory.
1522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EntryImpl* this_entry = it->second;
1523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    this_entry->AddRef();
1524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *entry = this_entry;
1525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *dirty = false;
1526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
1527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_refptr<EntryImpl> cache_entry(
15303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new EntryImpl(this, address, read_only_));
1531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  IncreaseNumRefs();
1532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *entry = NULL;
1533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!address.is_initialized() || address.is_separate_file() ||
1535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      address.file_type() != BLOCK_256) {
1536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(WARNING) << "Wrong entry address.";
1537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INVALID_ADDRESS;
1538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
1541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry->entry()->Load())
1542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_READ_FAILURE;
1543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsLoaded()) {
1545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CACHE_UMA(AGE_MS, "LoadTime", GetSizeGroup(), start);
1546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry->SanityCheck()) {
1549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(WARNING) << "Messed up entry found.";
1550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INVALID_ENTRY;
1551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!cache_entry->LoadNodeAddress())
1554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_READ_FAILURE;
1555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *dirty = cache_entry->IsDirty(GetCurrentEntryId());
1557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Prevent overwriting the dirty flag on the destructor.
1559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cache_entry->ClearDirtyFlag();
1560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!rankings_.SanityCheck(cache_entry->rankings(), false))
1562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_INVALID_LINKS;
1563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (*dirty) {
15653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    Trace("Dirty entry 0x%p 0x%x", reinterpret_cast<void*>(cache_entry.get()),
15663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          address.value());
15673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
15683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // We only add clean entries to the map.
1569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    open_entries_[address.value()] = cache_entry;
15703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  cache_entry->BeginLogging(net_log_, false);
1573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cache_entry.swap(entry);
1574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return 0;
1575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEntryImpl* BackendImpl::MatchEntry(const std::string& key, uint32 hash,
157872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   bool find_parent, Addr entry_addr,
157972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   bool* match_error) {
1580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(data_->table[hash & mask_]);
1581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<EntryImpl> cache_entry, parent_entry;
1582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntryImpl* tmp = NULL;
1583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool found = false;
158472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::set<CacheAddr> visited;
158572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  *match_error = false;
1586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (;;) {
1588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (disabled_)
1589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
159172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (visited.find(address.value()) != visited.end()) {
159272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // It's possible for a buggy version of the code to write a loop. Just
159372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // break it.
159472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      Trace("Hash collision loop 0x%x", address.value());
159572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      address.set_value(0);
159672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      parent_entry->SetNextAddress(address);
159772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
159872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    visited.insert(address.value());
159972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!address.is_initialized()) {
1601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (find_parent)
1602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        found = true;
1603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool dirty;
1607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int error = NewEntry(address, &tmp, &dirty);
1608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cache_entry.swap(&tmp);
1609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (error || dirty) {
1611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // This entry is dirty on disk (it was not properly closed): we cannot
1612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // trust it.
1613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Addr child(0);
1614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!error)
1615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        child.set_value(cache_entry->GetNextAddress());
1616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (parent_entry) {
1618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        parent_entry->SetNextAddress(child);
1619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        parent_entry = NULL;
1620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
1621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        data_->table[hash & mask_] = child.value();
1622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
1623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!error) {
1625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // It is important to call DestroyInvalidEntry after removing this
1626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // entry from the table.
1627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        DestroyInvalidEntry(cache_entry);
1628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cache_entry = NULL;
1629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
1630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        Trace("NewEntry failed on MatchEntry 0x%x", address.value());
1631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
1632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Restart the search.
1634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      address.set_value(data_->table[hash & mask_]);
163572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      visited.clear();
1636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
1637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
16393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK_EQ(hash & mask_, cache_entry->entry()->Data()->hash & mask_);
1640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (cache_entry->IsSameEntry(key, hash)) {
1641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!cache_entry->Update())
1642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cache_entry = NULL;
1643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      found = true;
164472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (find_parent && entry_addr.value() != address.value()) {
164572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        Trace("Entry not on the index 0x%x", address.value());
164672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        *match_error = true;
164772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        parent_entry = NULL;
164872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
1649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!cache_entry->Update())
1652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cache_entry = NULL;
1653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent_entry = cache_entry;
1654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cache_entry = NULL;
1655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!parent_entry)
1656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    address.set_value(parent_entry->GetNextAddress());
1659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (parent_entry && (!find_parent || !found))
1662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    parent_entry = NULL;
1663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cache_entry && (find_parent || !found))
1665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cache_entry = NULL;
1666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  find_parent ? parent_entry.swap(&tmp) : cache_entry.swap(&tmp);
1668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return tmp;
1669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is the actual implementation for OpenNextEntry and OpenPrevEntry.
1672c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::OpenFollowingEntry(bool forward, void** iter) {
1673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
1674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
1675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(iter);
1677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int kListsToSearch = 3;
1679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<EntryImpl> entries[kListsToSearch];
1680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<Rankings::Iterator> iterator(
1681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      reinterpret_cast<Rankings::Iterator*>(*iter));
1682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *iter = NULL;
1683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!iterator.get()) {
1685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    iterator.reset(new Rankings::Iterator(&rankings_));
1686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool ret = false;
1687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Get an entry from each list.
1689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int i = 0; i < kListsToSearch; i++) {
1690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EntryImpl* temp = NULL;
1691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ret |= OpenFollowingEntryFromList(forward, static_cast<Rankings::List>(i),
1692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                        &iterator->nodes[i], &temp);
1693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      entries[i].swap(&temp);  // The entry was already addref'd.
1694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!ret)
1696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return NULL;
1697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
1698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Get the next entry from the last list, and the actual entries for the
1699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // elements on the other lists.
1700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int i = 0; i < kListsToSearch; i++) {
1701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EntryImpl* temp = NULL;
1702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (iterator->list == i) {
1703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          OpenFollowingEntryFromList(forward, iterator->list,
1704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     &iterator->nodes[i], &temp);
1705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
170672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        temp = GetEnumeratedEntry(iterator->nodes[i]);
1707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
1708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      entries[i].swap(&temp);  // The entry was already addref'd.
1710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int newest = -1;
1714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int oldest = -1;
1715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Time access_times[kListsToSearch];
1716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kListsToSearch; i++) {
1717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (entries[i].get()) {
1718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      access_times[i] = entries[i]->GetLastUsed();
1719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (newest < 0) {
1720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK_LT(oldest, 0);
1721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        newest = oldest = i;
1722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        continue;
1723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
1724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (access_times[i] > access_times[newest])
1725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        newest = i;
1726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (access_times[i] < access_times[oldest])
1727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        oldest = i;
1728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
1729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (newest < 0 || oldest < 0)
1732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
1733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EntryImpl* next_entry;
1735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (forward) {
1736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_entry = entries[newest].release();
1737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    iterator->list = static_cast<Rankings::List>(newest);
1738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
1739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_entry = entries[oldest].release();
1740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    iterator->list = static_cast<Rankings::List>(oldest);
1741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *iter = iterator.release();
1744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return next_entry;
1745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::OpenFollowingEntryFromList(bool forward, Rankings::List list,
1748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                             CacheRankingsBlock** from_entry,
1749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                             EntryImpl** next_entry) {
1750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (disabled_)
1751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!new_eviction_ && Rankings::NO_USE != list)
1754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Rankings::ScopedRankingsBlock rankings(&rankings_, *from_entry);
1757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheRankingsBlock* next_block = forward ?
1758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rankings_.GetNext(rankings.get(), list) :
1759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rankings_.GetPrev(rankings.get(), list);
1760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Rankings::ScopedRankingsBlock next(&rankings_, next_block);
1761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *from_entry = NULL;
1762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
176372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  *next_entry = GetEnumeratedEntry(next.get());
1764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!*next_entry)
1765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *from_entry = next.release();
1768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
1769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenEntryImpl* BackendImpl::GetEnumeratedEntry(CacheRankingsBlock* next) {
1772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!next || disabled_)
1773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
1774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntryImpl* entry;
1776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool dirty;
1777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NewEntry(Addr(next->Data()->contents), &entry, &dirty))
1778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
1779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (dirty) {
1781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We cannot trust this entry. This code also releases the reference.
1782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DestroyInvalidEntryFromEnumeration(entry);
1783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
1784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
178672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!entry->Update()) {
1787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry->Release();
1788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
1789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
179172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Note that it is unfortunate (but possible) for this entry to be clean, but
179272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // not actually the real entry. In other words, we could have lost this entry
179372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // from the index, and it could have been replaced with a newer one. It's not
179472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // worth checking that this entry is "the real one", so we just return it and
179572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // let the enumeration continue; this entry will be evicted at some point, and
179672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // the regular path will work with the real entry. With time, this problem
179772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // will disasappear because this scenario is just a bug.
179872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
1799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure that we save the key for later.
1800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->GetKey();
1801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return entry;
1803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1805c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochEntryImpl* BackendImpl::ResurrectEntry(EntryImpl* deleted_entry) {
1806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ENTRY_NORMAL == deleted_entry->entry()->Data()->state) {
1807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    deleted_entry->Release();
1808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    stats_.OnEvent(Stats::CREATE_MISS);
1809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Trace("create entry miss ");
1810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
1811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We are attempting to create an entry and found out that the entry was
1814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // previously deleted.
1815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnCreateEntry(deleted_entry);
1817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry_count_++;
1818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  stats_.OnEvent(Stats::RESURRECT_HIT);
1820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Resurrect entry hit ");
1821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return deleted_entry;
1822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DestroyInvalidEntry(EntryImpl* entry) {
1825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(WARNING) << "Destroying invalid entry.";
1826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Destroying invalid entry 0x%p", entry);
1827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->SetPointerForInvalidEntry(GetCurrentEntryId());
1829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eviction_.OnDoomEntry(entry);
1831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->InternalDoom();
1832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!new_eviction_)
1834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DecreaseNumEntries();
1835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.OnEvent(Stats::INVALID_ENTRY);
1836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is kind of ugly. The entry may or may not be part of the cache index
1839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// table, and it may even have corrupt fields. If we just doom it, we may end up
1840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// deleting it twice (if all fields are right, and when looking up the parent of
1841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// chained entries wee see this one... and we delete it because it is dirty). If
1842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// we ignore it, we may leave it here forever. So we're going to attempt to
1843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// delete it through the provided object, without touching the index table
1844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (because we cannot jus call MatchEntry()), and also attempt to delete it from
1845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the table through the key: this may find a new entry (too bad), or an entry
1846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// that was just deleted and consider it a very corrupt entry.
1847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DestroyInvalidEntryFromEnumeration(EntryImpl* entry) {
1848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string key = entry->GetKey();
1849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->SetPointerForInvalidEntry(GetCurrentEntryId());
185072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CacheAddr next_entry = entry->GetNextAddress();
1851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!next_entry) {
1852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DestroyInvalidEntry(entry);
1853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry->Release();
1854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SyncDoomEntry(key);
1856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!next_entry)
1858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We have a chained entry so instead of destroying first this entry and then
1861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // anything with this key, we just called DoomEntry() first. If that call
1862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // deleted everything, |entry| has invalid data. Let's see if there is
1863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // something else to do. We started with just a rankings node (we come from
1864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // an enumeration), so that one may still be there.
1865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheRankingsBlock* rankings = entry->rankings();
1866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rankings->Load();
1867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rankings->Data()->contents) {
1868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We still have something. Clean this up.
1869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DestroyInvalidEntry(entry);
1870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry->Release();
1872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::AddStorageSize(int32 bytes) {
1875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.num_bytes += bytes;
1876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(data_->header.num_bytes, 0);
1877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::SubstractStorageSize(int32 bytes) {
1880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.num_bytes -= bytes;
1881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(data_->header.num_bytes, 0);
1882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::IncreaseNumRefs() {
1885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_refs_++;
1886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (max_refs_ < num_refs_)
1887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    max_refs_ = num_refs_;
1888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DecreaseNumRefs() {
1891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(num_refs_);
1892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  num_refs_--;
1893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!num_refs_ && disabled_)
1895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    MessageLoop::current()->PostTask(FROM_HERE,
18963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        factory_.NewRunnableMethod(&BackendImpl::RestartCache, true));
1897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::IncreaseNumEntries() {
1900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.num_entries++;
1901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GT(data_->header.num_entries, 0);
1902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::DecreaseNumEntries() {
1905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.num_entries--;
1906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data_->header.num_entries < 0) {
1907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
1908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data_->header.num_entries = 0;
1909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::LogStats() {
1913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  StatsItems stats;
1914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GetStats(&stats);
1915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1916731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  for (size_t index = 0; index < stats.size(); index++)
1917731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    VLOG(1) << stats[index].first << ": " << stats[index].second;
1918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::ReportStats() {
1921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "Entries", 0, data_->header.num_entries);
19223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
19233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int current_size = data_->header.num_bytes / (1024 * 1024);
19243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int max_size = max_size_ / (1024 * 1024);
19253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(COUNTS_10000, "Size2", 0, current_size);
19263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(COUNTS_10000, "MaxSize2", 0, max_size);
19273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!max_size)
19283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    max_size++;
19293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(PERCENTAGE, "UsedSpace", 0, current_size * 100 / max_size);
1930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS_10000, "AverageOpenEntries2", 0,
1932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            static_cast<int>(stats_.GetCounter(Stats::OPEN_ENTRIES)));
1933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS_10000, "MaxOpenEntries2", 0,
1934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            static_cast<int>(stats_.GetCounter(Stats::MAX_ENTRIES)));
1935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.SetCounter(Stats::MAX_ENTRIES, 0);
1936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  CACHE_UMA(COUNTS_10000, "TotalFatalErrors", 0,
19383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            static_cast<int>(stats_.GetCounter(Stats::FATAL_ERROR)));
19393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  CACHE_UMA(COUNTS_10000, "TotalDoomCache", 0,
19403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            static_cast<int>(stats_.GetCounter(Stats::DOOM_CACHE)));
19413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  CACHE_UMA(COUNTS_10000, "TotalDoomRecentEntries", 0,
19423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen            static_cast<int>(stats_.GetCounter(Stats::DOOM_RECENT)));
194372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  stats_.SetCounter(Stats::FATAL_ERROR, 0);
194472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  stats_.SetCounter(Stats::DOOM_CACHE, 0);
194572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  stats_.SetCounter(Stats::DOOM_RECENT, 0);
19463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
19473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  int64 total_hours = stats_.GetCounter(Stats::TIMER) / 120;
19483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!data_->header.create_time || !data_->header.lru.filled) {
19493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int cause = data_->header.create_time ? 0 : 1;
19503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!data_->header.lru.filled)
19513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      cause |= 2;
19523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CACHE_UMA(CACHE_ERROR, "ShortReport", 0, cause);
19533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    CACHE_UMA(HOURS, "TotalTimeNotFull", 0, static_cast<int>(total_hours));
1954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
19553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This is an up to date client that will report FirstEviction() data. After
1958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // that event, start reporting this:
1959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(HOURS, "TotalTime", 0, static_cast<int>(total_hours));
1961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 use_hours = stats_.GetCounter(Stats::LAST_REPORT_TIMER) / 120;
1963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.SetCounter(Stats::LAST_REPORT_TIMER, stats_.GetCounter(Stats::TIMER));
1964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We may see users with no use_hours at this point if this is the first time
1966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we are running this code.
1967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (use_hours)
1968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    use_hours = total_hours - use_hours;
1969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!use_hours || !GetEntryCount() || !data_->header.num_bytes)
1971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(HOURS, "UseTime", 0, static_cast<int>(use_hours));
19743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CACHE_UMA(PERCENTAGE, "HitRatio", data_->header.experiment,
19753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            stats_.GetHitRatio());
1976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 trim_rate = stats_.GetCounter(Stats::TRIM_ENTRY) / use_hours;
1978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "TrimRate", 0, static_cast<int>(trim_rate));
1979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int avg_size = data_->header.num_bytes / GetEntryCount();
1981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(COUNTS, "EntrySize", 0, avg_size);
1982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS, "EntriesFull", 0, data_->header.num_entries);
1983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(PERCENTAGE, "IndexLoad", 0,
1985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            data_->header.num_entries * 100 / (mask_ + 1));
1986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int large_entries_bytes = stats_.GetLargeEntriesSize();
1988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int large_ratio = large_entries_bytes * 100 / data_->header.num_bytes;
1989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CACHE_UMA(PERCENTAGE, "LargeEntriesRatio", 0, large_ratio);
1990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (new_eviction_) {
19923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CACHE_UMA(PERCENTAGE, "ResurrectRatio", data_->header.experiment,
19933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick              stats_.GetResurrectRatio());
1994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "NoUseRatio", 0,
1995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[0] * 100 / data_->header.num_entries);
1996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "LowUseRatio", 0,
1997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[1] * 100 / data_->header.num_entries);
1998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(PERCENTAGE, "HighUseRatio", 0,
1999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[2] * 100 / data_->header.num_entries);
20003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CACHE_UMA(PERCENTAGE, "DeletedRatio", data_->header.experiment,
2001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              data_->header.lru.sizes[4] * 100 / data_->header.num_entries);
2002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.ResetRatios();
2005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  stats_.SetCounter(Stats::TRIM_ENTRY, 0);
2006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cache_type_ == net::DISK_CACHE)
2008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    block_files_.ReportStats();
2009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BackendImpl::UpgradeTo2_1() {
2012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // 2.1 is basically the same as 2.0, except that new fields are actually
2013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // updated by the new eviction algorithm.
2014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(0x20000 == data_->header.version);
2015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.version = 0x20001;
2016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data_->header.lru.sizes[Rankings::NO_USE] = data_->header.num_entries;
2017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CheckIndex() {
2020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(data_);
2021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t current_size = index_->GetLength();
2023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (current_size < sizeof(Index)) {
2024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Corrupt Index file";
2025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (new_eviction_) {
2029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We support versions 2.0 and 2.1, upgrading 2.0 to 2.1.
2030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (kIndexMagic != data_->header.magic ||
2031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        kCurrentVersion >> 16 != data_->header.version >> 16) {
2032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(ERROR) << "Invalid file version or magic";
2033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
2034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (kCurrentVersion == data_->header.version) {
2036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // We need file version 2.1 for the new eviction algorithm.
2037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      UpgradeTo2_1();
2038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
2040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (kIndexMagic != data_->header.magic ||
2041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        kCurrentVersion != data_->header.version) {
2042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(ERROR) << "Invalid file version or magic";
2043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
2044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!data_->header.table_len) {
2048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Invalid table size";
2049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (current_size < GetIndexSize(data_->header.table_len) ||
2053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      data_->header.table_len & (kBaseTableLen - 1)) {
2054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Corrupt Index file";
2055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AdjustMaxCacheSize(data_->header.table_len);
2059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data_->header.num_bytes < 0 ||
2061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (max_size_ < kint32max - kDefaultCacheSize &&
2062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       data_->header.num_bytes > max_size_ + kDefaultCacheSize)) {
2063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Invalid cache (current) size";
2064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data_->header.num_entries < 0) {
2068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Invalid number of entries";
2069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
2070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!mask_)
2073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    mask_ = data_->header.table_len - 1;
2074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Load the table into memory with a single read.
2076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_array<char> buf(new char[current_size]);
2077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return index_->Read(buf.get(), current_size, 0);
2078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint BackendImpl::CheckAllEntries() {
2081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_dirty = 0;
2082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_entries = 0;
2083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(mask_ < kuint32max);
2084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i <= static_cast<int>(mask_); i++) {
2085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Addr address(data_->table[i]);
2086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!address.is_initialized())
2087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
2088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (;;) {
2089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      bool dirty;
2090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EntryImpl* tmp;
2091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int ret = NewEntry(address, &tmp, &dirty);
2092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (ret)
2093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ret;
2094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      scoped_refptr<EntryImpl> cache_entry;
2095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cache_entry.swap(&tmp);
2096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (dirty)
2098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        num_dirty++;
2099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else if (CheckEntry(cache_entry.get()))
2100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        num_entries++;
2101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else
2102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return ERR_INVALID_ENTRY;
2103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      address.set_value(cache_entry->GetNextAddress());
2105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!address.is_initialized())
2106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
2107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
2108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
21103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("CheckAllEntries End");
2111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (num_entries + num_dirty != data_->header.num_entries) {
2112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Number of entries mismatch";
2113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ERR_NUM_ENTRIES_MISMATCH;
2114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
2115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return num_dirty;
2117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BackendImpl::CheckEntry(EntryImpl* cache_entry) {
21203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool ok = block_files_.IsValid(cache_entry->entry()->address());
21213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ok = ok && block_files_.IsValid(cache_entry->rankings()->address());
21223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EntryStore* data = cache_entry->entry()->Data();
21233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (size_t i = 0; i < arraysize(data->data_addr); i++) {
21243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (data->data_addr[i]) {
21253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      Addr address(data->data_addr[i]);
21263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (address.is_block_file())
21273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ok = ok && block_files_.IsValid(address);
21283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
21293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
21303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RankingsNode* rankings = cache_entry->rankings()->Data();
21323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ok && !rankings->dummy;
21333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
21343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint BackendImpl::MaxBuffersSize() {
21363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static int64 total_memory = base::SysInfo::AmountOfPhysicalMemory();
21373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static bool done = false;
21383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!done) {
21403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const int kMaxBuffersSize = 30 * 1024 * 1024;
21413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // We want to use up to 2% of the computer's memory.
21433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    total_memory = total_memory * 2 / 100;
21443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (total_memory > kMaxBuffersSize || total_memory <= 0)
21453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      total_memory = kMaxBuffersSize;
21463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    done = true;
21483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
21493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
21503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return static_cast<int>(total_memory);
2151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
2152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace disk_cache
2154