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/callback_forward.h"
13#include "base/compiler_specific.h"
14#include "base/containers/hash_tables.h"
15#include "base/files/file_path.h"
16#include "base/memory/ref_counted.h"
17#include "base/memory/scoped_ptr.h"
18#include "base/memory/weak_ptr.h"
19#include "base/task_runner.h"
20#include "base/time/time.h"
21#include "net/base/cache_type.h"
22#include "net/disk_cache/disk_cache.h"
23#include "net/disk_cache/simple/simple_entry_impl.h"
24#include "net/disk_cache/simple/simple_index_delegate.h"
25
26namespace base {
27class SingleThreadTaskRunner;
28class TaskRunner;
29}
30
31namespace disk_cache {
32
33// SimpleBackendImpl is a new cache backend that stores entries in individual
34// files.
35// See http://www.chromium.org/developers/design-documents/network-stack/disk-cache/very-simple-backend
36//
37// The non-static functions below must be called on the IO thread unless
38// otherwise stated.
39
40class SimpleEntryImpl;
41class SimpleIndex;
42
43class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend,
44    public SimpleIndexDelegate,
45    public base::SupportsWeakPtr<SimpleBackendImpl> {
46 public:
47  SimpleBackendImpl(const base::FilePath& path, int max_bytes,
48                    net::CacheType cache_type,
49                    base::SingleThreadTaskRunner* cache_thread,
50                    net::NetLog* net_log);
51
52  virtual ~SimpleBackendImpl();
53
54  net::CacheType cache_type() const { return cache_type_; }
55  SimpleIndex* index() { return index_.get(); }
56
57  base::TaskRunner* worker_pool() { return worker_pool_.get(); }
58
59  int Init(const CompletionCallback& completion_callback);
60
61  // Sets the maximum size for the total amount of data stored by this instance.
62  bool SetMaxSize(int max_bytes);
63
64  // Returns the maximum file size permitted in this backend.
65  int GetMaxFileSize() const;
66
67  // Removes |entry| from the |active_entries_| set, forcing future Open/Create
68  // operations to construct a new object.
69  void OnDeactivated(const SimpleEntryImpl* entry);
70
71  // Flush our SequencedWorkerPool.
72  static void FlushWorkerPoolForTesting();
73
74  // The entry for |entry_hash| is being doomed; the backend will not attempt
75  // run new operations for this |entry_hash| until the Doom is completed.
76  void OnDoomStart(uint64 entry_hash);
77
78  // The entry for |entry_hash| has been successfully doomed, we can now allow
79  // operations on this entry, and we can run any operations enqueued while the
80  // doom completed.
81  void OnDoomComplete(uint64 entry_hash);
82
83  // SimpleIndexDelegate:
84  virtual void DoomEntries(std::vector<uint64>* entry_hashes,
85                           const CompletionCallback& callback) OVERRIDE;
86
87  // Backend:
88  virtual net::CacheType GetCacheType() const OVERRIDE;
89  virtual int32 GetEntryCount() const OVERRIDE;
90  virtual int OpenEntry(const std::string& key, Entry** entry,
91                        const CompletionCallback& callback) OVERRIDE;
92  virtual int CreateEntry(const std::string& key, Entry** entry,
93                          const CompletionCallback& callback) OVERRIDE;
94  virtual int DoomEntry(const std::string& key,
95                        const CompletionCallback& callback) OVERRIDE;
96  virtual int DoomAllEntries(const CompletionCallback& callback) OVERRIDE;
97  virtual int DoomEntriesBetween(base::Time initial_time,
98                                 base::Time end_time,
99                                 const CompletionCallback& callback) OVERRIDE;
100  virtual int DoomEntriesSince(base::Time initial_time,
101                               const CompletionCallback& callback) OVERRIDE;
102  virtual int OpenNextEntry(void** iter, Entry** next_entry,
103                            const CompletionCallback& callback) OVERRIDE;
104  virtual void EndEnumeration(void** iter) OVERRIDE;
105  virtual void GetStats(
106      std::vector<std::pair<std::string, std::string> >* stats) OVERRIDE;
107  virtual void OnExternalCacheHit(const std::string& key) OVERRIDE;
108
109 private:
110  typedef base::hash_map<uint64, base::WeakPtr<SimpleEntryImpl> > EntryMap;
111
112  typedef base::Callback<void(base::Time mtime, uint64 max_size, int result)>
113      InitializeIndexCallback;
114
115  // Return value of InitCacheStructureOnDisk().
116  struct DiskStatResult {
117    base::Time cache_dir_mtime;
118    uint64 max_size;
119    bool detected_magic_number_mismatch;
120    int net_error;
121  };
122
123  void InitializeIndex(const CompletionCallback& callback,
124                       const DiskStatResult& result);
125
126  // Dooms all entries previously accessed between |initial_time| and
127  // |end_time|. Invoked when the index is ready.
128  void IndexReadyForDoom(base::Time initial_time,
129                         base::Time end_time,
130                         const CompletionCallback& callback,
131                         int result);
132
133  // Try to create the directory if it doesn't exist. This must run on the IO
134  // thread.
135  static DiskStatResult InitCacheStructureOnDisk(const base::FilePath& path,
136                                                 uint64 suggested_max_size);
137
138  // Searches |active_entries_| for the entry corresponding to |key|. If found,
139  // returns the found entry. Otherwise, creates a new entry and returns that.
140  scoped_refptr<SimpleEntryImpl> CreateOrFindActiveEntry(
141      uint64 entry_hash,
142      const std::string& key);
143
144  // Given a hash, will try to open the corresponding Entry. If we have an Entry
145  // corresponding to |hash| in the map of active entries, opens it. Otherwise,
146  // a new empty Entry will be created, opened and filled with information from
147  // the disk.
148  int OpenEntryFromHash(uint64 entry_hash,
149                        Entry** entry,
150                        const CompletionCallback& callback);
151
152  // Doom the entry corresponding to |entry_hash|, if it's active or currently
153  // pending doom. This function does not block if there is an active entry,
154  // which is very important to prevent races in DoomEntries() above.
155  int DoomEntryFromHash(uint64 entry_hash, const CompletionCallback & callback);
156
157  // Called when the index is initilized to find the next entry in the iterator
158  // |iter|. If there are no more hashes in the iterator list, net::ERR_FAILED
159  // is returned. Otherwise, calls OpenEntryFromHash.
160  void GetNextEntryInIterator(void** iter,
161                              Entry** next_entry,
162                              const CompletionCallback& callback,
163                              int error_code);
164
165  // Called when we tried to open an entry with hash alone. When a blank entry
166  // has been created and filled in with information from the disk - based on a
167  // hash alone - this checks that a duplicate active entry was not created
168  // using a key in the meantime.
169  void OnEntryOpenedFromHash(uint64 hash,
170                             Entry** entry,
171                             scoped_refptr<SimpleEntryImpl> simple_entry,
172                             const CompletionCallback& callback,
173                             int error_code);
174
175  // Called when we tried to open an entry from key. When the entry has been
176  // opened, a check for key mismatch is performed.
177  void OnEntryOpenedFromKey(const std::string key,
178                            Entry** entry,
179                            scoped_refptr<SimpleEntryImpl> simple_entry,
180                            const CompletionCallback& callback,
181                            int error_code);
182
183  // Called at the end of the asynchronous operation triggered by
184  // OpenEntryFromHash. Makes sure to continue iterating if the open entry was
185  // not a success.
186  void CheckIterationReturnValue(void** iter,
187                                 Entry** entry,
188                                 const CompletionCallback& callback,
189                                 int error_code);
190
191  // A callback thunk used by DoomEntries to clear the |entries_pending_doom_|
192  // after a mass doom.
193  void DoomEntriesComplete(scoped_ptr<std::vector<uint64> > entry_hashes,
194                           const CompletionCallback& callback,
195                           int result);
196
197  const base::FilePath path_;
198  const net::CacheType cache_type_;
199  scoped_ptr<SimpleIndex> index_;
200  const scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
201  scoped_refptr<base::TaskRunner> worker_pool_;
202
203  int orig_max_size_;
204  const SimpleEntryImpl::OperationsMode entry_operations_mode_;
205
206  EntryMap active_entries_;
207
208  // The set of all entries which are currently being doomed. To avoid races,
209  // these entries cannot have Doom/Create/Open operations run until the doom
210  // is complete. The base::Closure map target is used to store deferred
211  // operations to be run at the completion of the Doom.
212  base::hash_map<uint64, std::vector<base::Closure> > entries_pending_doom_;
213
214  net::NetLog* const net_log_;
215};
216
217}  // namespace disk_cache
218
219#endif  // NET_DISK_CACHE_SIMPLE_SIMPLE_BACKEND_IMPL_H_
220