1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_DISK_CACHE_SIMPLE_SIMPLE_BACKEND_IMPL_H_
6#define NET_DISK_CACHE_SIMPLE_SIMPLE_BACKEND_IMPL_H_
7
8#include <string>
9#include <utility>
10#include <vector>
11
12#include "base/compiler_specific.h"
13#include "base/containers/hash_tables.h"
14#include "base/files/file_path.h"
15#include "base/memory/ref_counted.h"
16#include "base/memory/scoped_ptr.h"
17#include "base/memory/weak_ptr.h"
18#include "base/task_runner.h"
19#include "base/time/time.h"
20#include "net/base/cache_type.h"
21#include "net/disk_cache/disk_cache.h"
22#include "net/disk_cache/simple/simple_entry_impl.h"
23
24namespace base {
25class SingleThreadTaskRunner;
26class TaskRunner;
27}
28
29namespace disk_cache {
30
31// SimpleBackendImpl is a new cache backend that stores entries in individual
32// files.
33// See http://www.chromium.org/developers/design-documents/network-stack/disk-cache/very-simple-backend
34//
35// The non-static functions below must be called on the IO thread unless
36// otherwise stated.
37
38class SimpleEntryImpl;
39class SimpleIndex;
40
41class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend,
42    public base::SupportsWeakPtr<SimpleBackendImpl> {
43 public:
44  SimpleBackendImpl(const base::FilePath& path, int max_bytes,
45                    net::CacheType type,
46                    base::SingleThreadTaskRunner* cache_thread,
47                    net::NetLog* net_log);
48
49  virtual ~SimpleBackendImpl();
50
51  SimpleIndex* index() { return index_.get(); }
52
53  base::TaskRunner* worker_pool() { return worker_pool_.get(); }
54
55  int Init(const CompletionCallback& completion_callback);
56
57  // Sets the maximum size for the total amount of data stored by this instance.
58  bool SetMaxSize(int max_bytes);
59
60  // Returns the maximum file size permitted in this backend.
61  int GetMaxFileSize() const;
62
63  // Removes |entry| from the |active_entries_| set, forcing future Open/Create
64  // operations to construct a new object.
65  void OnDeactivated(const SimpleEntryImpl* entry);
66
67  // Backend:
68  virtual net::CacheType GetCacheType() const OVERRIDE;
69  virtual int32 GetEntryCount() const OVERRIDE;
70  virtual int OpenEntry(const std::string& key, Entry** entry,
71                        const CompletionCallback& callback) OVERRIDE;
72  virtual int CreateEntry(const std::string& key, Entry** entry,
73                          const CompletionCallback& callback) OVERRIDE;
74  virtual int DoomEntry(const std::string& key,
75                        const CompletionCallback& callback) OVERRIDE;
76  virtual int DoomAllEntries(const CompletionCallback& callback) OVERRIDE;
77  virtual int DoomEntriesBetween(base::Time initial_time,
78                                 base::Time end_time,
79                                 const CompletionCallback& callback) OVERRIDE;
80  virtual int DoomEntriesSince(base::Time initial_time,
81                               const CompletionCallback& callback) OVERRIDE;
82  virtual int OpenNextEntry(void** iter, Entry** next_entry,
83                            const CompletionCallback& callback) OVERRIDE;
84  virtual void EndEnumeration(void** iter) OVERRIDE;
85  virtual void GetStats(
86      std::vector<std::pair<std::string, std::string> >* stats) OVERRIDE;
87  virtual void OnExternalCacheHit(const std::string& key) OVERRIDE;
88
89 private:
90  typedef base::hash_map<uint64, base::WeakPtr<SimpleEntryImpl> > EntryMap;
91
92  typedef base::Callback<void(base::Time mtime, uint64 max_size, int result)>
93      InitializeIndexCallback;
94
95  // Return value of InitCacheStructureOnDisk().
96  struct DiskStatResult {
97    base::Time cache_dir_mtime;
98    uint64 max_size;
99    bool detected_magic_number_mismatch;
100    int net_error;
101  };
102
103  void InitializeIndex(const CompletionCallback& callback,
104                       const DiskStatResult& result);
105
106  // Dooms all entries previously accessed between |initial_time| and
107  // |end_time|. Invoked when the index is ready.
108  void IndexReadyForDoom(base::Time initial_time,
109                         base::Time end_time,
110                         const CompletionCallback& callback,
111                         int result);
112
113  // Try to create the directory if it doesn't exist. This must run on the IO
114  // thread.
115  static DiskStatResult InitCacheStructureOnDisk(const base::FilePath& path,
116                                                 uint64 suggested_max_size);
117
118  // Searches |active_entries_| for the entry corresponding to |key|. If found,
119  // returns the found entry. Otherwise, creates a new entry and returns that.
120  scoped_refptr<SimpleEntryImpl> CreateOrFindActiveEntry(
121      const std::string& key);
122
123  // Given a hash, will try to open the corresponding Entry. If we have an Entry
124  // corresponding to |hash| in the map of active entries, opens it. Otherwise,
125  // a new empty Entry will be created, opened and filled with information from
126  // the disk.
127  int OpenEntryFromHash(uint64 hash,
128                        Entry** entry,
129                        const CompletionCallback& callback);
130
131  // Called when the index is initilized to find the next entry in the iterator
132  // |iter|. If there are no more hashes in the iterator list, net::ERR_FAILED
133  // is returned. Otherwise, calls OpenEntryFromHash.
134  void GetNextEntryInIterator(void** iter,
135                              Entry** next_entry,
136                              const CompletionCallback& callback,
137                              int error_code);
138
139  // Called when we tried to open an entry with hash alone. When a blank entry
140  // has been created and filled in with information from the disk - based on a
141  // hash alone - this checks that a duplicate active entry was not created
142  // using a key in the meantime.
143  void OnEntryOpenedFromHash(uint64 hash,
144                             Entry** entry,
145                             scoped_refptr<SimpleEntryImpl> simple_entry,
146                             const CompletionCallback& callback,
147                             int error_code);
148
149  // Called when we tried to open an entry from key. When the entry has been
150  // opened, a check for key mismatch is performed.
151  void OnEntryOpenedFromKey(const std::string key,
152                            Entry** entry,
153                            scoped_refptr<SimpleEntryImpl> simple_entry,
154                            const CompletionCallback& callback,
155                            int error_code);
156
157  // Called at the end of the asynchronous operation triggered by
158  // OpenEntryFromHash. Makes sure to continue iterating if the open entry was
159  // not a success.
160  void CheckIterationReturnValue(void** iter,
161                                 Entry** entry,
162                                 const CompletionCallback& callback,
163                                 int error_code);
164
165  const base::FilePath path_;
166  scoped_ptr<SimpleIndex> index_;
167  const scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
168  scoped_refptr<base::TaskRunner> worker_pool_;
169
170  int orig_max_size_;
171  const SimpleEntryImpl::OperationsMode entry_operations_mode_;
172
173  // TODO(gavinp): Store the entry_hash in SimpleEntryImpl, and index this map
174  // by hash. This will save memory, and make IndexReadyForDoom easier.
175  EntryMap active_entries_;
176
177  net::NetLog* const net_log_;
178};
179
180}  // namespace disk_cache
181
182#endif  // NET_DISK_CACHE_SIMPLE_SIMPLE_BACKEND_IMPL_H_
183