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