• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors
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 <stdint.h>
9 
10 #include <memory>
11 #include <string>
12 
13 #include "base/containers/queue.h"
14 #include "base/files/file_path.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/sequence_checker.h"
18 #include "base/time/time.h"
19 #include "net/base/cache_type.h"
20 #include "net/base/net_export.h"
21 #include "net/base/request_priority.h"
22 #include "net/disk_cache/disk_cache.h"
23 #include "net/disk_cache/simple/post_doom_waiter.h"
24 #include "net/disk_cache/simple/simple_entry_format.h"
25 #include "net/disk_cache/simple/simple_entry_operation.h"
26 #include "net/disk_cache/simple/simple_synchronous_entry.h"
27 #include "net/log/net_log_event_type.h"
28 #include "net/log/net_log_with_source.h"
29 
30 namespace base {
31 class TaskRunner;
32 }
33 
34 namespace net {
35 class GrowableIOBuffer;
36 class IOBuffer;
37 class NetLog;
38 class PrioritizedTaskRunner;
39 }
40 
41 namespace disk_cache {
42 
43 class BackendCleanupTracker;
44 class SimpleBackendImpl;
45 class SimpleEntryStat;
46 class SimpleFileTracker;
47 class SimpleSynchronousEntry;
48 struct SimpleEntryCreationResults;
49 
50 // SimpleEntryImpl is the source task_runner interface to an entry in the very
51 // simple disk cache. It proxies for the SimpleSynchronousEntry, which performs
52 // IO on the worker thread.
53 class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
54     public base::RefCounted<SimpleEntryImpl> {
55   friend class base::RefCounted<SimpleEntryImpl>;
56  public:
57   enum OperationsMode {
58     NON_OPTIMISTIC_OPERATIONS,
59     OPTIMISTIC_OPERATIONS,
60   };
61 
62   // The Backend provides an |ActiveEntryProxy| instance to this entry when it
63   // is active, meaning it's the canonical entry for this |entry_hash_|. The
64   // entry can make itself inactive by deleting its proxy.
65   class ActiveEntryProxy {
66    public:
67     virtual ~ActiveEntryProxy() = 0;
68   };
69 
70   SimpleEntryImpl(
71       net::CacheType cache_type,
72       const base::FilePath& path,
73       scoped_refptr<BackendCleanupTracker> cleanup_tracker,
74       uint64_t entry_hash,
75       OperationsMode operations_mode,
76       SimpleBackendImpl* backend,
77       SimpleFileTracker* file_tracker,
78       scoped_refptr<BackendFileOperationsFactory> file_operations_factory,
79       net::NetLog* net_log,
80       uint32_t entry_priority);
81 
82   void SetActiveEntryProxy(
83       std::unique_ptr<ActiveEntryProxy> active_entry_proxy);
84 
85   // Adds another reader/writer to this entry, if possible.
86   EntryResult OpenEntry(EntryResultCallback callback);
87 
88   // Creates this entry, if possible.
89   EntryResult CreateEntry(EntryResultCallback callback);
90 
91   // Opens an existing entry or creates a new one.
92   EntryResult OpenOrCreateEntry(EntryResultCallback callback);
93 
94   // Identical to Backend::Doom() except that it accepts a
95   // CompletionOnceCallback.
96   net::Error DoomEntry(CompletionOnceCallback callback);
97 
key()98   const std::string& key() const { return key_; }
entry_hash()99   uint64_t entry_hash() const { return entry_hash_; }
100 
101   // The key is not a constructor parameter to the SimpleEntryImpl, because
102   // during cache iteration, it's necessary to open entries by their hash
103   // alone. In that case, the SimpleSynchronousEntry will read the key from disk
104   // and it will be set.
105   void SetKey(const std::string& key);
106 
107   // SetCreatePendingDoom() should be called before CreateEntry() if the
108   // creation should suceed optimistically but not do any I/O until
109   // NotifyDoomBeforeCreateComplete() is called.
110   void SetCreatePendingDoom();
111   void NotifyDoomBeforeCreateComplete();
112 
113   // From Entry:
114   void Doom() override;
115   void Close() override;
116   std::string GetKey() const override;
117   // GetLastUsed() should not be called in net::APP_CACHE mode since the times
118   // are not updated.
119   base::Time GetLastUsed() const override;
120   base::Time GetLastModified() const override;
121   int32_t GetDataSize(int index) const override;
122   int ReadData(int stream_index,
123                int offset,
124                net::IOBuffer* buf,
125                int buf_len,
126                CompletionOnceCallback callback) override;
127   int WriteData(int stream_index,
128                 int offset,
129                 net::IOBuffer* buf,
130                 int buf_len,
131                 CompletionOnceCallback callback,
132                 bool truncate) override;
133   int ReadSparseData(int64_t offset,
134                      net::IOBuffer* buf,
135                      int buf_len,
136                      CompletionOnceCallback callback) override;
137   int WriteSparseData(int64_t offset,
138                       net::IOBuffer* buf,
139                       int buf_len,
140                       CompletionOnceCallback callback) override;
141   RangeResult GetAvailableRange(int64_t offset,
142                                 int len,
143                                 RangeResultCallback callback) override;
144   bool CouldBeSparse() const override;
145   void CancelSparseIO() override;
146   net::Error ReadyForSparseIO(CompletionOnceCallback callback) override;
147   void SetLastUsedTimeForTest(base::Time time) override;
148 
149   // Changes the entry's priority in its TaskRunner.
150   void SetPriority(uint32_t entry_priority);
151 
152  private:
153   class ScopedOperationRunner;
154   friend class ScopedOperationRunner;
155 
156   enum State {
157     // The state immediately after construction, but before |synchronous_entry_|
158     // has been assigned. This is the state at construction, and is one of the
159     // two states (along with failure) one can destruct an entry in.
160     STATE_UNINITIALIZED,
161 
162     // This entry is available for regular IO.
163     STATE_READY,
164 
165     // IO is currently in flight, operations must wait for completion before
166     // launching.
167     STATE_IO_PENDING,
168 
169     // A failure occurred in the current or previous operation. All operations
170     // after that must fail, until we receive a Close().
171     STATE_FAILURE,
172   };
173 
174   enum DoomState {
175     // No attempt to doom the entry has been made.
176     DOOM_NONE,
177 
178     // We have moved ourselves to |entries_pending_doom_| and have queued an
179     // operation to actually update the disk, but haven't completed it yet.
180     DOOM_QUEUED,
181 
182     // The disk has been updated. This corresponds to the state where we
183     // are in neither |entries_pending_doom_| nor |active_entries_|.
184     DOOM_COMPLETED,
185   };
186 
187   ~SimpleEntryImpl() override;
188 
189   // Must be used to invoke a client-provided completion callback for an
190   // operation initiated through the backend (e.g. create, open, doom) so that
191   // clients don't get notified after they deleted the backend (which they would
192   // not expect).
193   void PostClientCallback(CompletionOnceCallback callback, int result);
194   void PostClientCallback(EntryResultCallback callback, EntryResult result);
195 
196   // Clears entry state enough to prepare it for re-use. This will generally
197   // put it back into STATE_UNINITIALIZED, except if the entry is doomed and
198   // therefore disconnected from ownership of corresponding filename, in which
199   // case it will be put into STATE_FAILURE.
200   void ResetEntry();
201 
202   // Adjust ownership before return of this entry to a user of the API.
203   // Increments the user count.
204   void ReturnEntryToCaller();
205 
206   // Like above, but for asynchronous return after the event loop runs again,
207   // also invoking the callback per the usual net convention.
208   // The return is cancelled if the backend is deleted in the interim.
209   void ReturnEntryToCallerAsync(bool is_open, EntryResultCallback callback);
210 
211   // Portion of the above that runs off the event loop.
212   void FinishReturnEntryToCallerAsync(bool is_open,
213                                       EntryResultCallback callback);
214 
215   // Remove |this| from the Backend and the index, either because
216   // SimpleSynchronousEntry has detected an error or because we are about to
217   // be dooming it ourselves and want it to be tracked in
218   // |entries_pending_doom_| instead.
219   void MarkAsDoomed(DoomState doom_state);
220 
221   // Runs the next operation in the queue, if any and if there is no other
222   // operation running at the moment.
223   // WARNING: May delete |this|, as an operation in the queue can contain
224   // the last reference.
225   void RunNextOperationIfNeeded();
226 
227   void OpenEntryInternal(SimpleEntryOperation::EntryResultState result_state,
228                          EntryResultCallback callback);
229 
230   void CreateEntryInternal(SimpleEntryOperation::EntryResultState result_state,
231                            EntryResultCallback callback);
232 
233   void OpenOrCreateEntryInternal(
234       OpenEntryIndexEnum index_state,
235       SimpleEntryOperation::EntryResultState result_state,
236       EntryResultCallback callback);
237 
238   void CloseInternal();
239 
240   int ReadDataInternal(bool sync_possible,
241                        int index,
242                        int offset,
243                        net::IOBuffer* buf,
244                        int buf_len,
245                        CompletionOnceCallback callback);
246 
247   void WriteDataInternal(int index,
248                          int offset,
249                          net::IOBuffer* buf,
250                          int buf_len,
251                          CompletionOnceCallback callback,
252                          bool truncate);
253 
254   void ReadSparseDataInternal(int64_t sparse_offset,
255                               net::IOBuffer* buf,
256                               int buf_len,
257                               CompletionOnceCallback callback);
258 
259   void WriteSparseDataInternal(int64_t sparse_offset,
260                                net::IOBuffer* buf,
261                                int buf_len,
262                                CompletionOnceCallback callback);
263 
264   void GetAvailableRangeInternal(int64_t sparse_offset,
265                                  int len,
266                                  RangeResultCallback callback);
267 
268   void DoomEntryInternal(CompletionOnceCallback callback);
269 
270   // Called after a SimpleSynchronousEntry has completed CreateEntry() or
271   // OpenEntry(). If |in_results| is used to denote whether that was successful,
272   // Posts either the produced entry or an error code to |completion_callback|.
273   void CreationOperationComplete(
274       SimpleEntryOperation::EntryResultState result_state,
275       EntryResultCallback completion_callback,
276       const base::TimeTicks& start_time,
277       const base::Time index_last_used_time,
278       std::unique_ptr<SimpleEntryCreationResults> in_results,
279       net::NetLogEventType end_event_type);
280 
281   // Called after we've closed and written the EOF record to our entry. Until
282   // this point it hasn't been safe to OpenEntry() the same entry, but from this
283   // point it is.
284   void CloseOperationComplete(
285       std::unique_ptr<SimpleEntryCloseResults> in_results);
286 
287   // Internal utility method used by other completion methods.
288   // Updaties state and dooms on errors.
289   void UpdateStateAfterOperationComplete(const SimpleEntryStat& entry_stat,
290                                          int result);
291 
292   // Internal utility method used by other completion methods. Calls
293   // |completion_callback| after updating state and dooming on errors.
294   void EntryOperationComplete(CompletionOnceCallback completion_callback,
295                               const SimpleEntryStat& entry_stat,
296                               int result);
297 
298   // Called after an asynchronous read. Updates |crc32s_| if possible.
299   void ReadOperationComplete(
300       int stream_index,
301       int offset,
302       CompletionOnceCallback completion_callback,
303       std::unique_ptr<SimpleEntryStat> entry_stat,
304       std::unique_ptr<SimpleSynchronousEntry::ReadResult> read_result);
305 
306   // Called after an asynchronous write completes.
307   // |buf| parameter brings back a reference to net::IOBuffer to the original
308   // sequence, so that we can reduce cross thread malloc/free pair.
309   // See http://crbug.com/708644 for details.
310   void WriteOperationComplete(
311       int stream_index,
312       CompletionOnceCallback completion_callback,
313       std::unique_ptr<SimpleEntryStat> entry_stat,
314       std::unique_ptr<SimpleSynchronousEntry::WriteResult> result,
315       net::IOBuffer* buf);
316 
317   void ReadSparseOperationComplete(CompletionOnceCallback completion_callback,
318                                    std::unique_ptr<base::Time> last_used,
319                                    std::unique_ptr<int> result);
320 
321   void WriteSparseOperationComplete(CompletionOnceCallback completion_callback,
322                                     std::unique_ptr<SimpleEntryStat> entry_stat,
323                                     std::unique_ptr<int> result);
324 
325   void GetAvailableRangeOperationComplete(
326       RangeResultCallback completion_callback,
327       std::unique_ptr<RangeResult> result);
328 
329   // Called after an asynchronous doom completes.
330   void DoomOperationComplete(CompletionOnceCallback callback,
331                              State state_to_restore,
332                              int result);
333 
334   // Called after completion of an operation, to either incoproprate file info
335   // received from I/O done on the worker pool, or to simply bump the
336   // timestamps. Updates the metadata both in |this| and in the index.
337   // Stream size information in particular may be important for following
338   // operations.
339   void UpdateDataFromEntryStat(const SimpleEntryStat& entry_stat);
340 
341   int64_t GetDiskUsage() const;
342 
343   // Completes a read from the stream data kept in memory, logging metrics
344   // and updating metadata. Returns the # of bytes read successfully.
345   // This asumes the caller has already range-checked offset and buf_len
346   // appropriately.
347   int ReadFromBuffer(net::GrowableIOBuffer* in_buf,
348                      int offset,
349                      int buf_len,
350                      net::IOBuffer* out_buf);
351 
352   // Copies data from |buf| to the internal in-memory buffer for stream 0. If
353   // |truncate| is set to true, the target buffer will be truncated at |offset|
354   // + |buf_len| before being written.
355   int SetStream0Data(net::IOBuffer* buf,
356                      int offset, int buf_len,
357                      bool truncate);
358 
359   // We want all async I/O on entries to complete before recycling the dir.
360   scoped_refptr<BackendCleanupTracker> cleanup_tracker_;
361 
362   std::unique_ptr<ActiveEntryProxy> active_entry_proxy_;
363 
364   // All nonstatic SimpleEntryImpl methods should always be called on the
365   // source creation sequence, in all cases. |sequence_checker_| documents and
366   // enforces this.
367   SEQUENCE_CHECKER(sequence_checker_);
368 
369   const base::WeakPtr<SimpleBackendImpl> backend_;
370   const raw_ptr<SimpleFileTracker> file_tracker_;
371   const scoped_refptr<BackendFileOperationsFactory> file_operations_factory_;
372   const net::CacheType cache_type_;
373   const base::FilePath path_;
374   const uint64_t entry_hash_;
375   const bool use_optimistic_operations_;
376   std::string key_;
377 
378   // |last_used_|, |last_modified_| and |data_size_| are copied from the
379   // synchronous entry at the completion of each item of asynchronous IO.
380   // TODO(clamy): Unify last_used_ with data in the index.
381   base::Time last_used_;
382   base::Time last_modified_;
383   int32_t data_size_[kSimpleEntryStreamCount];
384   int32_t sparse_data_size_ = 0;
385 
386   // Number of times this object has been returned from Backend::OpenEntry() and
387   // Backend::CreateEntry() without subsequent Entry::Close() calls. Used to
388   // notify the backend when this entry not used by any callers.
389   int open_count_ = 0;
390 
391   DoomState doom_state_ = DOOM_NONE;
392 
393   enum {
394     CREATE_NORMAL,
395     CREATE_OPTIMISTIC_PENDING_DOOM,
396     CREATE_OPTIMISTIC_PENDING_DOOM_FOLLOWED_BY_DOOM,
397   } optimistic_create_pending_doom_state_ = CREATE_NORMAL;
398 
399   State state_ = STATE_UNINITIALIZED;
400 
401   // When possible, we compute a crc32, for the data in each entry as we read or
402   // write. For each stream, |crc32s_[index]| is the crc32 of that stream from
403   // [0 .. |crc32s_end_offset_|). If |crc32s_end_offset_[index] == 0| then the
404   // value of |crc32s_[index]| is undefined.
405   // Note at this can only be done in the current implementation in the case of
406   // a single entry reader that reads serially through the entire file.
407   // Extending this to multiple readers is possible, but isn't currently worth
408   // it; see http://crbug.com/488076#c3 for details.
409   int32_t crc32s_end_offset_[kSimpleEntryStreamCount];
410   uint32_t crc32s_[kSimpleEntryStreamCount];
411 
412   // If |have_written_[index]| is true, we have written to the file that
413   // contains stream |index|.
414   bool have_written_[kSimpleEntryStreamCount];
415 
416   // The |synchronous_entry_| is the worker thread object that performs IO on
417   // entries. It's owned by this SimpleEntryImpl whenever |executing_operation_|
418   // is false (i.e. when an operation is not pending on the worker pool). When
419   // an operation is being executed no one owns the synchronous entry. Therefore
420   // SimpleEntryImpl should not be deleted while an operation is running as that
421   // would leak the SimpleSynchronousEntry.
422   raw_ptr<SimpleSynchronousEntry> synchronous_entry_ = nullptr;
423 
424   scoped_refptr<net::PrioritizedTaskRunner> prioritized_task_runner_;
425 
426   base::queue<SimpleEntryOperation> pending_operations_;
427 
428   net::NetLogWithSource net_log_;
429 
430   // Unlike other streams, stream 0 data is read from the disk when the entry is
431   // opened, and then kept in memory. All read/write operations on stream 0
432   // affect the |stream_0_data_| buffer. When the entry is closed,
433   // |stream_0_data_| is written to the disk.
434   // Stream 0 is kept in memory because it is stored in the same file as stream
435   // 1 on disk, to reduce the number of file descriptors and save disk space.
436   // This strategy allows stream 1 to change size easily. Since stream 0 is only
437   // used to write HTTP headers, the memory consumption of keeping it in memory
438   // is acceptable.
439   scoped_refptr<net::GrowableIOBuffer> stream_0_data_;
440 
441   // Sometimes stream 1 data is prefetched when stream 0 is first read.
442   // If a write to the stream occurs on the entry the prefetch buffer is
443   // discarded. It may also be null if it wasn't prefetched in the first place.
444   scoped_refptr<net::GrowableIOBuffer> stream_1_prefetch_data_;
445 
446   // This is used only while a doom is pending.
447   scoped_refptr<SimplePostDoomWaiterTable> post_doom_waiting_;
448 
449   // Choosing uint32_t over uint64_t for space savings. Pages have in the
450   // hundres to possibly thousands of resources. Wrapping every 4 billion
451   // shouldn't cause inverted priorities very often.
452   uint32_t entry_priority_ = 0;
453 };
454 
455 }  // namespace disk_cache
456 
457 #endif  // NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_
458