• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ENTRY_IMPL_H_
6 #define NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_
7 
8 #include <queue>
9 #include <string>
10 
11 #include "base/files/file_path.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/threading/thread_checker.h"
15 #include "net/base/cache_type.h"
16 #include "net/base/net_export.h"
17 #include "net/base/net_log.h"
18 #include "net/disk_cache/disk_cache.h"
19 #include "net/disk_cache/simple/simple_entry_format.h"
20 #include "net/disk_cache/simple/simple_entry_operation.h"
21 
22 namespace base {
23 class TaskRunner;
24 }
25 
26 namespace net {
27 class GrowableIOBuffer;
28 class IOBuffer;
29 }
30 
31 namespace disk_cache {
32 
33 class SimpleBackendImpl;
34 class SimpleSynchronousEntry;
35 class SimpleEntryStat;
36 struct SimpleEntryCreationResults;
37 
38 // SimpleEntryImpl is the IO thread interface to an entry in the very simple
39 // disk cache. It proxies for the SimpleSynchronousEntry, which performs IO
40 // on the worker thread.
41 class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
42     public base::RefCounted<SimpleEntryImpl> {
43   friend class base::RefCounted<SimpleEntryImpl>;
44  public:
45   enum OperationsMode {
46     NON_OPTIMISTIC_OPERATIONS,
47     OPTIMISTIC_OPERATIONS,
48   };
49 
50   // The Backend provides an |ActiveEntryProxy| instance to this entry when it
51   // is active, meaning it's the canonical entry for this |entry_hash_|. The
52   // entry can make itself inactive by deleting its proxy.
53   class ActiveEntryProxy {
54    public:
55     virtual ~ActiveEntryProxy() = 0;
56   };
57 
58   SimpleEntryImpl(net::CacheType cache_type,
59                   const base::FilePath& path,
60                   uint64 entry_hash,
61                   OperationsMode operations_mode,
62                   SimpleBackendImpl* backend,
63                   net::NetLog* net_log);
64 
65   void SetActiveEntryProxy(
66       scoped_ptr<ActiveEntryProxy> active_entry_proxy);
67 
68   // Adds another reader/writer to this entry, if possible, returning |this| to
69   // |entry|.
70   int OpenEntry(Entry** entry, const CompletionCallback& callback);
71 
72   // Creates this entry, if possible. Returns |this| to |entry|.
73   int CreateEntry(Entry** entry, const CompletionCallback& callback);
74 
75   // Identical to Backend::Doom() except that it accepts a CompletionCallback.
76   int DoomEntry(const CompletionCallback& callback);
77 
key()78   const std::string& key() const { return key_; }
entry_hash()79   uint64 entry_hash() const { return entry_hash_; }
80   void SetKey(const std::string& key);
81 
82   // From Entry:
83   virtual void Doom() OVERRIDE;
84   virtual void Close() OVERRIDE;
85   virtual std::string GetKey() const OVERRIDE;
86   virtual base::Time GetLastUsed() const OVERRIDE;
87   virtual base::Time GetLastModified() const OVERRIDE;
88   virtual int32 GetDataSize(int index) const OVERRIDE;
89   virtual int ReadData(int stream_index,
90                        int offset,
91                        net::IOBuffer* buf,
92                        int buf_len,
93                        const CompletionCallback& callback) OVERRIDE;
94   virtual int WriteData(int stream_index,
95                         int offset,
96                         net::IOBuffer* buf,
97                         int buf_len,
98                         const CompletionCallback& callback,
99                         bool truncate) OVERRIDE;
100   virtual int ReadSparseData(int64 offset,
101                              net::IOBuffer* buf,
102                              int buf_len,
103                              const CompletionCallback& callback) OVERRIDE;
104   virtual int WriteSparseData(int64 offset,
105                               net::IOBuffer* buf,
106                               int buf_len,
107                               const CompletionCallback& callback) OVERRIDE;
108   virtual int GetAvailableRange(int64 offset,
109                                 int len,
110                                 int64* start,
111                                 const CompletionCallback& callback) OVERRIDE;
112   virtual bool CouldBeSparse() const OVERRIDE;
113   virtual void CancelSparseIO() OVERRIDE;
114   virtual int ReadyForSparseIO(const CompletionCallback& callback) OVERRIDE;
115 
116  private:
117   class ScopedOperationRunner;
118   friend class ScopedOperationRunner;
119 
120   enum State {
121     // The state immediately after construction, but before |synchronous_entry_|
122     // has been assigned. This is the state at construction, and is the only
123     // legal state to destruct an entry in.
124     STATE_UNINITIALIZED,
125 
126     // This entry is available for regular IO.
127     STATE_READY,
128 
129     // IO is currently in flight, operations must wait for completion before
130     // launching.
131     STATE_IO_PENDING,
132 
133     // A failure occurred in the current or previous operation. All operations
134     // after that must fail, until we receive a Close().
135     STATE_FAILURE,
136   };
137 
138   // Used in histograms, please only add entries at the end.
139   enum CheckCrcResult {
140     CRC_CHECK_NEVER_READ_TO_END = 0,
141     CRC_CHECK_NOT_DONE = 1,
142     CRC_CHECK_DONE = 2,
143     CRC_CHECK_NEVER_READ_AT_ALL = 3,
144     CRC_CHECK_MAX = 4,
145   };
146 
147   virtual ~SimpleEntryImpl();
148 
149   // Must be used to invoke a client-provided completion callback for an
150   // operation initiated through the backend (e.g. create, open) so that clients
151   // don't get notified after they deleted the backend (which they would not
152   // expect).
153   void PostClientCallback(const CompletionCallback& callback, int result);
154 
155   // Sets entry to STATE_UNINITIALIZED.
156   void MakeUninitialized();
157 
158   // Return this entry to a user of the API in |out_entry|. Increments the user
159   // count.
160   void ReturnEntryToCaller(Entry** out_entry);
161 
162   // An error occured, and the SimpleSynchronousEntry should have Doomed
163   // us at this point. We need to remove |this| from the Backend and the
164   // index.
165   void MarkAsDoomed();
166 
167   // Runs the next operation in the queue, if any and if there is no other
168   // operation running at the moment.
169   // WARNING: May delete |this|, as an operation in the queue can contain
170   // the last reference.
171   void RunNextOperationIfNeeded();
172 
173   void OpenEntryInternal(bool have_index,
174                          const CompletionCallback& callback,
175                          Entry** out_entry);
176 
177   void CreateEntryInternal(bool have_index,
178                            const CompletionCallback& callback,
179                            Entry** out_entry);
180 
181   void CloseInternal();
182 
183   void ReadDataInternal(int index,
184                         int offset,
185                         net::IOBuffer* buf,
186                         int buf_len,
187                         const CompletionCallback& callback);
188 
189   void WriteDataInternal(int index,
190                          int offset,
191                          net::IOBuffer* buf,
192                          int buf_len,
193                          const CompletionCallback& callback,
194                          bool truncate);
195 
196   void ReadSparseDataInternal(int64 sparse_offset,
197                               net::IOBuffer* buf,
198                               int buf_len,
199                               const CompletionCallback& callback);
200 
201   void WriteSparseDataInternal(int64 sparse_offset,
202                                net::IOBuffer* buf,
203                                int buf_len,
204                                const CompletionCallback& callback);
205 
206   void GetAvailableRangeInternal(int64 sparse_offset,
207                                  int len,
208                                  int64* out_start,
209                                  const CompletionCallback& callback);
210 
211   void DoomEntryInternal(const CompletionCallback& callback);
212 
213   // Called after a SimpleSynchronousEntry has completed CreateEntry() or
214   // OpenEntry(). If |in_sync_entry| is non-NULL, creation is successful and we
215   // can return |this| SimpleEntryImpl to |*out_entry|. Runs
216   // |completion_callback|.
217   void CreationOperationComplete(
218       const CompletionCallback& completion_callback,
219       const base::TimeTicks& start_time,
220       scoped_ptr<SimpleEntryCreationResults> in_results,
221       Entry** out_entry,
222       net::NetLog::EventType end_event_type);
223 
224   // Called after we've closed and written the EOF record to our entry. Until
225   // this point it hasn't been safe to OpenEntry() the same entry, but from this
226   // point it is.
227   void CloseOperationComplete();
228 
229   // Internal utility method used by other completion methods. Calls
230   // |completion_callback| after updating state and dooming on errors.
231   void EntryOperationComplete(const CompletionCallback& completion_callback,
232                               const SimpleEntryStat& entry_stat,
233                               scoped_ptr<int> result);
234 
235   // Called after an asynchronous read. Updates |crc32s_| if possible.
236   void ReadOperationComplete(int stream_index,
237                              int offset,
238                              const CompletionCallback& completion_callback,
239                              scoped_ptr<uint32> read_crc32,
240                              scoped_ptr<SimpleEntryStat> entry_stat,
241                              scoped_ptr<int> result);
242 
243   // Called after an asynchronous write completes.
244   void WriteOperationComplete(int stream_index,
245                               const CompletionCallback& completion_callback,
246                               scoped_ptr<SimpleEntryStat> entry_stat,
247                               scoped_ptr<int> result);
248 
249   void ReadSparseOperationComplete(
250       const CompletionCallback& completion_callback,
251       scoped_ptr<base::Time> last_used,
252       scoped_ptr<int> result);
253 
254   void WriteSparseOperationComplete(
255       const CompletionCallback& completion_callback,
256       scoped_ptr<SimpleEntryStat> entry_stat,
257       scoped_ptr<int> result);
258 
259   void GetAvailableRangeOperationComplete(
260       const CompletionCallback& completion_callback,
261       scoped_ptr<int> result);
262 
263   // Called after an asynchronous doom completes.
264   void DoomOperationComplete(const CompletionCallback& callback,
265                              State state_to_restore,
266                              int result);
267 
268   // Called after validating the checksums on an entry. Passes through the
269   // original result if successful, propogates the error if the checksum does
270   // not validate.
271   void ChecksumOperationComplete(
272       int stream_index,
273       int orig_result,
274       const CompletionCallback& completion_callback,
275       scoped_ptr<int> result);
276 
277   // Called after completion of asynchronous IO and receiving file metadata for
278   // the entry in |entry_stat|. Updates the metadata in the entry and in the
279   // index to make them available on next IO operations.
280   void UpdateDataFromEntryStat(const SimpleEntryStat& entry_stat);
281 
282   int64 GetDiskUsage() const;
283 
284   // Used to report histograms.
285   void RecordReadIsParallelizable(const SimpleEntryOperation& operation) const;
286   void RecordWriteDependencyType(const SimpleEntryOperation& operation) const;
287 
288   // Reads from the stream 0 data kept in memory.
289   int ReadStream0Data(net::IOBuffer* buf, int offset, int buf_len);
290 
291   // Copies data from |buf| to the internal in-memory buffer for stream 0. If
292   // |truncate| is set to true, the target buffer will be truncated at |offset|
293   // + |buf_len| before being written.
294   int SetStream0Data(net::IOBuffer* buf,
295                      int offset, int buf_len,
296                      bool truncate);
297 
298   // Updates |crc32s_| and |crc32s_end_offset_| for a write of the data in
299   // |buffer| on |stream_index|, starting at |offset| and of length |length|.
300   void AdvanceCrc(net::IOBuffer* buffer,
301                   int offset,
302                   int length,
303                   int stream_index);
304 
305   scoped_ptr<ActiveEntryProxy> active_entry_proxy_;
306 
307   // All nonstatic SimpleEntryImpl methods should always be called on the IO
308   // thread, in all cases. |io_thread_checker_| documents and enforces this.
309   base::ThreadChecker io_thread_checker_;
310 
311   const base::WeakPtr<SimpleBackendImpl> backend_;
312   const net::CacheType cache_type_;
313   const scoped_refptr<base::TaskRunner> worker_pool_;
314   const base::FilePath path_;
315   const uint64 entry_hash_;
316   const bool use_optimistic_operations_;
317   std::string key_;
318 
319   // |last_used_|, |last_modified_| and |data_size_| are copied from the
320   // synchronous entry at the completion of each item of asynchronous IO.
321   // TODO(clamy): Unify last_used_ with data in the index.
322   base::Time last_used_;
323   base::Time last_modified_;
324   int32 data_size_[kSimpleEntryStreamCount];
325   int32 sparse_data_size_;
326 
327   // Number of times this object has been returned from Backend::OpenEntry() and
328   // Backend::CreateEntry() without subsequent Entry::Close() calls. Used to
329   // notify the backend when this entry not used by any callers.
330   int open_count_;
331 
332   bool doomed_;
333 
334   State state_;
335 
336   // When possible, we compute a crc32, for the data in each entry as we read or
337   // write. For each stream, |crc32s_[index]| is the crc32 of that stream from
338   // [0 .. |crc32s_end_offset_|). If |crc32s_end_offset_[index] == 0| then the
339   // value of |crc32s_[index]| is undefined.
340   int32 crc32s_end_offset_[kSimpleEntryStreamCount];
341   uint32 crc32s_[kSimpleEntryStreamCount];
342 
343   // If |have_written_[index]| is true, we have written to the file that
344   // contains stream |index|.
345   bool have_written_[kSimpleEntryStreamCount];
346 
347   // Reflects how much CRC checking has been done with the entry. This state is
348   // reported on closing each entry stream.
349   CheckCrcResult crc_check_state_[kSimpleEntryStreamCount];
350 
351   // The |synchronous_entry_| is the worker thread object that performs IO on
352   // entries. It's owned by this SimpleEntryImpl whenever |executing_operation_|
353   // is false (i.e. when an operation is not pending on the worker pool). When
354   // an operation is being executed no one owns the synchronous entry. Therefore
355   // SimpleEntryImpl should not be deleted while an operation is running as that
356   // would leak the SimpleSynchronousEntry.
357   SimpleSynchronousEntry* synchronous_entry_;
358 
359   std::queue<SimpleEntryOperation> pending_operations_;
360 
361   net::BoundNetLog net_log_;
362 
363   scoped_ptr<SimpleEntryOperation> executing_operation_;
364 
365   // Unlike other streams, stream 0 data is read from the disk when the entry is
366   // opened, and then kept in memory. All read/write operations on stream 0
367   // affect the |stream_0_data_| buffer. When the entry is closed,
368   // |stream_0_data_| is written to the disk.
369   // Stream 0 is kept in memory because it is stored in the same file as stream
370   // 1 on disk, to reduce the number of file descriptors and save disk space.
371   // This strategy allows stream 1 to change size easily. Since stream 0 is only
372   // used to write HTTP headers, the memory consumption of keeping it in memory
373   // is acceptable.
374   scoped_refptr<net::GrowableIOBuffer> stream_0_data_;
375 };
376 
377 }  // namespace disk_cache
378 
379 #endif  // NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_
380