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.
5 #ifndef NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_
6 #define NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_
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/disk_cache/disk_cache.h"
18 #include "net/disk_cache/simple/simple_entry_format.h"
19 #include "net/disk_cache/simple/simple_entry_operation.h"
20 #include "net/log/net_log.h"
27 class GrowableIOBuffer
;
31 namespace disk_cache
{
33 class SimpleBackendImpl
;
34 class SimpleSynchronousEntry
;
35 class SimpleEntryStat
;
36 struct SimpleEntryCreationResults
;
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
>;
46 NON_OPTIMISTIC_OPERATIONS
,
47 OPTIMISTIC_OPERATIONS
,
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
{
55 virtual ~ActiveEntryProxy() = 0;
58 SimpleEntryImpl(net::CacheType cache_type
,
59 const base::FilePath
& path
,
61 OperationsMode operations_mode
,
62 SimpleBackendImpl
* backend
,
63 net::NetLog
* net_log
);
65 void SetActiveEntryProxy(
66 scoped_ptr
<ActiveEntryProxy
> active_entry_proxy
);
68 // Adds another reader/writer to this entry, if possible, returning |this| to
70 int OpenEntry(Entry
** entry
, const CompletionCallback
& callback
);
72 // Creates this entry, if possible. Returns |this| to |entry|.
73 int CreateEntry(Entry
** entry
, const CompletionCallback
& callback
);
75 // Identical to Backend::Doom() except that it accepts a CompletionCallback.
76 int DoomEntry(const CompletionCallback
& callback
);
78 const std::string
& key() const { return key_
; }
79 uint64
entry_hash() const { return entry_hash_
; }
80 void SetKey(const std::string
& key
);
84 void Close() override
;
85 std::string
GetKey() const override
;
86 base::Time
GetLastUsed() const override
;
87 base::Time
GetLastModified() const override
;
88 int32
GetDataSize(int index
) const override
;
89 int ReadData(int stream_index
,
93 const CompletionCallback
& callback
) override
;
94 int WriteData(int stream_index
,
98 const CompletionCallback
& callback
,
99 bool truncate
) override
;
100 int ReadSparseData(int64 offset
,
103 const CompletionCallback
& callback
) override
;
104 int WriteSparseData(int64 offset
,
107 const CompletionCallback
& callback
) override
;
108 int GetAvailableRange(int64 offset
,
111 const CompletionCallback
& callback
) override
;
112 bool CouldBeSparse() const override
;
113 void CancelSparseIO() override
;
114 int ReadyForSparseIO(const CompletionCallback
& callback
) override
;
117 class ScopedOperationRunner
;
118 friend class ScopedOperationRunner
;
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.
126 // This entry is available for regular IO.
129 // IO is currently in flight, operations must wait for completion before
133 // A failure occurred in the current or previous operation. All operations
134 // after that must fail, until we receive a Close().
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,
143 CRC_CHECK_NEVER_READ_AT_ALL
= 3,
147 ~SimpleEntryImpl() override
;
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
153 void PostClientCallback(const CompletionCallback
& callback
, int result
);
155 // Sets entry to STATE_UNINITIALIZED.
156 void MakeUninitialized();
158 // Return this entry to a user of the API in |out_entry|. Increments the user
160 void ReturnEntryToCaller(Entry
** out_entry
);
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
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();
173 void OpenEntryInternal(bool have_index
,
174 const CompletionCallback
& callback
,
177 void CreateEntryInternal(bool have_index
,
178 const CompletionCallback
& callback
,
181 void CloseInternal();
183 void ReadDataInternal(int index
,
187 const CompletionCallback
& callback
);
189 void WriteDataInternal(int index
,
193 const CompletionCallback
& callback
,
196 void ReadSparseDataInternal(int64 sparse_offset
,
199 const CompletionCallback
& callback
);
201 void WriteSparseDataInternal(int64 sparse_offset
,
204 const CompletionCallback
& callback
);
206 void GetAvailableRangeInternal(int64 sparse_offset
,
209 const CompletionCallback
& callback
);
211 void DoomEntryInternal(const CompletionCallback
& callback
);
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
,
222 net::NetLog::EventType end_event_type
);
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
227 void CloseOperationComplete();
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
);
235 // Called after an asynchronous read. Updates |crc32s_| if possible.
236 void ReadOperationComplete(int stream_index
,
238 const CompletionCallback
& completion_callback
,
239 scoped_ptr
<uint32
> read_crc32
,
240 scoped_ptr
<SimpleEntryStat
> entry_stat
,
241 scoped_ptr
<int> result
);
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
);
249 void ReadSparseOperationComplete(
250 const CompletionCallback
& completion_callback
,
251 scoped_ptr
<base::Time
> last_used
,
252 scoped_ptr
<int> result
);
254 void WriteSparseOperationComplete(
255 const CompletionCallback
& completion_callback
,
256 scoped_ptr
<SimpleEntryStat
> entry_stat
,
257 scoped_ptr
<int> result
);
259 void GetAvailableRangeOperationComplete(
260 const CompletionCallback
& completion_callback
,
261 scoped_ptr
<int> result
);
263 // Called after an asynchronous doom completes.
264 void DoomOperationComplete(const CompletionCallback
& callback
,
265 State state_to_restore
,
268 // Called after validating the checksums on an entry. Passes through the
269 // original result if successful, propogates the error if the checksum does
271 void ChecksumOperationComplete(
274 const CompletionCallback
& completion_callback
,
275 scoped_ptr
<int> result
);
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
);
282 int64
GetDiskUsage() const;
284 // Used to report histograms.
285 void RecordReadIsParallelizable(const SimpleEntryOperation
& operation
) const;
286 void RecordWriteDependencyType(const SimpleEntryOperation
& operation
) const;
288 // Reads from the stream 0 data kept in memory.
289 int ReadStream0Data(net::IOBuffer
* buf
, int offset
, int buf_len
);
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
,
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
,
305 scoped_ptr
<ActiveEntryProxy
> active_entry_proxy_
;
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_
;
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_
;
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_
;
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.
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 // Note at this can only be done in the current implementation in the case of
341 // a single entry reader that reads serially through the entire file.
342 // Extending this to multiple readers is possible, but isn't currently worth
343 // it; see http://crbug.com/488076#c3 for details.
344 int32 crc32s_end_offset_
[kSimpleEntryStreamCount
];
345 uint32 crc32s_
[kSimpleEntryStreamCount
];
347 // If |have_written_[index]| is true, we have written to the file that
348 // contains stream |index|.
349 bool have_written_
[kSimpleEntryStreamCount
];
351 // Reflects how much CRC checking has been done with the entry. This state is
352 // reported on closing each entry stream.
353 CheckCrcResult crc_check_state_
[kSimpleEntryStreamCount
];
355 // The |synchronous_entry_| is the worker thread object that performs IO on
356 // entries. It's owned by this SimpleEntryImpl whenever |executing_operation_|
357 // is false (i.e. when an operation is not pending on the worker pool). When
358 // an operation is being executed no one owns the synchronous entry. Therefore
359 // SimpleEntryImpl should not be deleted while an operation is running as that
360 // would leak the SimpleSynchronousEntry.
361 SimpleSynchronousEntry
* synchronous_entry_
;
363 std::queue
<SimpleEntryOperation
> pending_operations_
;
365 net::BoundNetLog net_log_
;
367 scoped_ptr
<SimpleEntryOperation
> executing_operation_
;
369 // Unlike other streams, stream 0 data is read from the disk when the entry is
370 // opened, and then kept in memory. All read/write operations on stream 0
371 // affect the |stream_0_data_| buffer. When the entry is closed,
372 // |stream_0_data_| is written to the disk.
373 // Stream 0 is kept in memory because it is stored in the same file as stream
374 // 1 on disk, to reduce the number of file descriptors and save disk space.
375 // This strategy allows stream 1 to change size easily. Since stream 0 is only
376 // used to write HTTP headers, the memory consumption of keeping it in memory
378 scoped_refptr
<net::GrowableIOBuffer
> stream_0_data_
;
381 } // namespace disk_cache
383 #endif // NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_