| // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_ | 
 | #define NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_ | 
 |  | 
 | #include <queue> | 
 | #include <string> | 
 |  | 
 | #include "base/files/file_path.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/memory/scoped_ptr.h" | 
 | #include "base/threading/thread_checker.h" | 
 | #include "net/base/cache_type.h" | 
 | #include "net/base/net_export.h" | 
 | #include "net/disk_cache/disk_cache.h" | 
 | #include "net/disk_cache/simple/simple_entry_format.h" | 
 | #include "net/disk_cache/simple/simple_entry_operation.h" | 
 | #include "net/log/net_log.h" | 
 |  | 
 | namespace base { | 
 | class TaskRunner; | 
 | } | 
 |  | 
 | namespace net { | 
 | class GrowableIOBuffer; | 
 | class IOBuffer; | 
 | } | 
 |  | 
 | namespace disk_cache { | 
 |  | 
 | class SimpleBackendImpl; | 
 | class SimpleSynchronousEntry; | 
 | class SimpleEntryStat; | 
 | struct SimpleEntryCreationResults; | 
 |  | 
 | // SimpleEntryImpl is the IO thread interface to an entry in the very simple | 
 | // disk cache. It proxies for the SimpleSynchronousEntry, which performs IO | 
 | // on the worker thread. | 
 | class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, | 
 |     public base::RefCounted<SimpleEntryImpl> { | 
 |   friend class base::RefCounted<SimpleEntryImpl>; | 
 |  public: | 
 |   enum OperationsMode { | 
 |     NON_OPTIMISTIC_OPERATIONS, | 
 |     OPTIMISTIC_OPERATIONS, | 
 |   }; | 
 |  | 
 |   // The Backend provides an |ActiveEntryProxy| instance to this entry when it | 
 |   // is active, meaning it's the canonical entry for this |entry_hash_|. The | 
 |   // entry can make itself inactive by deleting its proxy. | 
 |   class ActiveEntryProxy { | 
 |    public: | 
 |     virtual ~ActiveEntryProxy() = 0; | 
 |   }; | 
 |  | 
 |   SimpleEntryImpl(net::CacheType cache_type, | 
 |                   const base::FilePath& path, | 
 |                   uint64 entry_hash, | 
 |                   OperationsMode operations_mode, | 
 |                   SimpleBackendImpl* backend, | 
 |                   net::NetLog* net_log); | 
 |  | 
 |   void SetActiveEntryProxy( | 
 |       scoped_ptr<ActiveEntryProxy> active_entry_proxy); | 
 |  | 
 |   // Adds another reader/writer to this entry, if possible, returning |this| to | 
 |   // |entry|. | 
 |   int OpenEntry(Entry** entry, const CompletionCallback& callback); | 
 |  | 
 |   // Creates this entry, if possible. Returns |this| to |entry|. | 
 |   int CreateEntry(Entry** entry, const CompletionCallback& callback); | 
 |  | 
 |   // Identical to Backend::Doom() except that it accepts a CompletionCallback. | 
 |   int DoomEntry(const CompletionCallback& callback); | 
 |  | 
 |   const std::string& key() const { return key_; } | 
 |   uint64 entry_hash() const { return entry_hash_; } | 
 |   void SetKey(const std::string& key); | 
 |  | 
 |   // From Entry: | 
 |   void Doom() override; | 
 |   void Close() override; | 
 |   std::string GetKey() const override; | 
 |   base::Time GetLastUsed() const override; | 
 |   base::Time GetLastModified() const override; | 
 |   int32 GetDataSize(int index) const override; | 
 |   int ReadData(int stream_index, | 
 |                int offset, | 
 |                net::IOBuffer* buf, | 
 |                int buf_len, | 
 |                const CompletionCallback& callback) override; | 
 |   int WriteData(int stream_index, | 
 |                 int offset, | 
 |                 net::IOBuffer* buf, | 
 |                 int buf_len, | 
 |                 const CompletionCallback& callback, | 
 |                 bool truncate) override; | 
 |   int ReadSparseData(int64 offset, | 
 |                      net::IOBuffer* buf, | 
 |                      int buf_len, | 
 |                      const CompletionCallback& callback) override; | 
 |   int WriteSparseData(int64 offset, | 
 |                       net::IOBuffer* buf, | 
 |                       int buf_len, | 
 |                       const CompletionCallback& callback) override; | 
 |   int GetAvailableRange(int64 offset, | 
 |                         int len, | 
 |                         int64* start, | 
 |                         const CompletionCallback& callback) override; | 
 |   bool CouldBeSparse() const override; | 
 |   void CancelSparseIO() override; | 
 |   int ReadyForSparseIO(const CompletionCallback& callback) override; | 
 |  | 
 |  private: | 
 |   class ScopedOperationRunner; | 
 |   friend class ScopedOperationRunner; | 
 |  | 
 |   enum State { | 
 |     // The state immediately after construction, but before |synchronous_entry_| | 
 |     // has been assigned. This is the state at construction, and is the only | 
 |     // legal state to destruct an entry in. | 
 |     STATE_UNINITIALIZED, | 
 |  | 
 |     // This entry is available for regular IO. | 
 |     STATE_READY, | 
 |  | 
 |     // IO is currently in flight, operations must wait for completion before | 
 |     // launching. | 
 |     STATE_IO_PENDING, | 
 |  | 
 |     // A failure occurred in the current or previous operation. All operations | 
 |     // after that must fail, until we receive a Close(). | 
 |     STATE_FAILURE, | 
 |   }; | 
 |  | 
 |   // Used in histograms, please only add entries at the end. | 
 |   enum CheckCrcResult { | 
 |     CRC_CHECK_NEVER_READ_TO_END = 0, | 
 |     CRC_CHECK_NOT_DONE = 1, | 
 |     CRC_CHECK_DONE = 2, | 
 |     CRC_CHECK_NEVER_READ_AT_ALL = 3, | 
 |     CRC_CHECK_MAX = 4, | 
 |   }; | 
 |  | 
 |   ~SimpleEntryImpl() override; | 
 |  | 
 |   // Must be used to invoke a client-provided completion callback for an | 
 |   // operation initiated through the backend (e.g. create, open) so that clients | 
 |   // don't get notified after they deleted the backend (which they would not | 
 |   // expect). | 
 |   void PostClientCallback(const CompletionCallback& callback, int result); | 
 |  | 
 |   // Sets entry to STATE_UNINITIALIZED. | 
 |   void MakeUninitialized(); | 
 |  | 
 |   // Return this entry to a user of the API in |out_entry|. Increments the user | 
 |   // count. | 
 |   void ReturnEntryToCaller(Entry** out_entry); | 
 |  | 
 |   // An error occured, and the SimpleSynchronousEntry should have Doomed | 
 |   // us at this point. We need to remove |this| from the Backend and the | 
 |   // index. | 
 |   void MarkAsDoomed(); | 
 |  | 
 |   // Runs the next operation in the queue, if any and if there is no other | 
 |   // operation running at the moment. | 
 |   // WARNING: May delete |this|, as an operation in the queue can contain | 
 |   // the last reference. | 
 |   void RunNextOperationIfNeeded(); | 
 |  | 
 |   void OpenEntryInternal(bool have_index, | 
 |                          const CompletionCallback& callback, | 
 |                          Entry** out_entry); | 
 |  | 
 |   void CreateEntryInternal(bool have_index, | 
 |                            const CompletionCallback& callback, | 
 |                            Entry** out_entry); | 
 |  | 
 |   void CloseInternal(); | 
 |  | 
 |   void ReadDataInternal(int index, | 
 |                         int offset, | 
 |                         net::IOBuffer* buf, | 
 |                         int buf_len, | 
 |                         const CompletionCallback& callback); | 
 |  | 
 |   void WriteDataInternal(int index, | 
 |                          int offset, | 
 |                          net::IOBuffer* buf, | 
 |                          int buf_len, | 
 |                          const CompletionCallback& callback, | 
 |                          bool truncate); | 
 |  | 
 |   void ReadSparseDataInternal(int64 sparse_offset, | 
 |                               net::IOBuffer* buf, | 
 |                               int buf_len, | 
 |                               const CompletionCallback& callback); | 
 |  | 
 |   void WriteSparseDataInternal(int64 sparse_offset, | 
 |                                net::IOBuffer* buf, | 
 |                                int buf_len, | 
 |                                const CompletionCallback& callback); | 
 |  | 
 |   void GetAvailableRangeInternal(int64 sparse_offset, | 
 |                                  int len, | 
 |                                  int64* out_start, | 
 |                                  const CompletionCallback& callback); | 
 |  | 
 |   void DoomEntryInternal(const CompletionCallback& callback); | 
 |  | 
 |   // Called after a SimpleSynchronousEntry has completed CreateEntry() or | 
 |   // OpenEntry(). If |in_sync_entry| is non-NULL, creation is successful and we | 
 |   // can return |this| SimpleEntryImpl to |*out_entry|. Runs | 
 |   // |completion_callback|. | 
 |   void CreationOperationComplete( | 
 |       const CompletionCallback& completion_callback, | 
 |       const base::TimeTicks& start_time, | 
 |       scoped_ptr<SimpleEntryCreationResults> in_results, | 
 |       Entry** out_entry, | 
 |       net::NetLog::EventType end_event_type); | 
 |  | 
 |   // Called after we've closed and written the EOF record to our entry. Until | 
 |   // this point it hasn't been safe to OpenEntry() the same entry, but from this | 
 |   // point it is. | 
 |   void CloseOperationComplete(); | 
 |  | 
 |   // Internal utility method used by other completion methods. Calls | 
 |   // |completion_callback| after updating state and dooming on errors. | 
 |   void EntryOperationComplete(const CompletionCallback& completion_callback, | 
 |                               const SimpleEntryStat& entry_stat, | 
 |                               scoped_ptr<int> result); | 
 |  | 
 |   // Called after an asynchronous read. Updates |crc32s_| if possible. | 
 |   void ReadOperationComplete(int stream_index, | 
 |                              int offset, | 
 |                              const CompletionCallback& completion_callback, | 
 |                              scoped_ptr<uint32> read_crc32, | 
 |                              scoped_ptr<SimpleEntryStat> entry_stat, | 
 |                              scoped_ptr<int> result); | 
 |  | 
 |   // Called after an asynchronous write completes. | 
 |   void WriteOperationComplete(int stream_index, | 
 |                               const CompletionCallback& completion_callback, | 
 |                               scoped_ptr<SimpleEntryStat> entry_stat, | 
 |                               scoped_ptr<int> result); | 
 |  | 
 |   void ReadSparseOperationComplete( | 
 |       const CompletionCallback& completion_callback, | 
 |       scoped_ptr<base::Time> last_used, | 
 |       scoped_ptr<int> result); | 
 |  | 
 |   void WriteSparseOperationComplete( | 
 |       const CompletionCallback& completion_callback, | 
 |       scoped_ptr<SimpleEntryStat> entry_stat, | 
 |       scoped_ptr<int> result); | 
 |  | 
 |   void GetAvailableRangeOperationComplete( | 
 |       const CompletionCallback& completion_callback, | 
 |       scoped_ptr<int> result); | 
 |  | 
 |   // Called after an asynchronous doom completes. | 
 |   void DoomOperationComplete(const CompletionCallback& callback, | 
 |                              State state_to_restore, | 
 |                              int result); | 
 |  | 
 |   // Called after validating the checksums on an entry. Passes through the | 
 |   // original result if successful, propogates the error if the checksum does | 
 |   // not validate. | 
 |   void ChecksumOperationComplete( | 
 |       int stream_index, | 
 |       int orig_result, | 
 |       const CompletionCallback& completion_callback, | 
 |       scoped_ptr<int> result); | 
 |  | 
 |   // Called after completion of asynchronous IO and receiving file metadata for | 
 |   // the entry in |entry_stat|. Updates the metadata in the entry and in the | 
 |   // index to make them available on next IO operations. | 
 |   void UpdateDataFromEntryStat(const SimpleEntryStat& entry_stat); | 
 |  | 
 |   int64 GetDiskUsage() const; | 
 |  | 
 |   // Used to report histograms. | 
 |   void RecordReadIsParallelizable(const SimpleEntryOperation& operation) const; | 
 |   void RecordWriteDependencyType(const SimpleEntryOperation& operation) const; | 
 |  | 
 |   // Reads from the stream 0 data kept in memory. | 
 |   int ReadStream0Data(net::IOBuffer* buf, int offset, int buf_len); | 
 |  | 
 |   // Copies data from |buf| to the internal in-memory buffer for stream 0. If | 
 |   // |truncate| is set to true, the target buffer will be truncated at |offset| | 
 |   // + |buf_len| before being written. | 
 |   int SetStream0Data(net::IOBuffer* buf, | 
 |                      int offset, int buf_len, | 
 |                      bool truncate); | 
 |  | 
 |   // Updates |crc32s_| and |crc32s_end_offset_| for a write of the data in | 
 |   // |buffer| on |stream_index|, starting at |offset| and of length |length|. | 
 |   void AdvanceCrc(net::IOBuffer* buffer, | 
 |                   int offset, | 
 |                   int length, | 
 |                   int stream_index); | 
 |  | 
 |   scoped_ptr<ActiveEntryProxy> active_entry_proxy_; | 
 |  | 
 |   // All nonstatic SimpleEntryImpl methods should always be called on the IO | 
 |   // thread, in all cases. |io_thread_checker_| documents and enforces this. | 
 |   base::ThreadChecker io_thread_checker_; | 
 |  | 
 |   const base::WeakPtr<SimpleBackendImpl> backend_; | 
 |   const net::CacheType cache_type_; | 
 |   const scoped_refptr<base::TaskRunner> worker_pool_; | 
 |   const base::FilePath path_; | 
 |   const uint64 entry_hash_; | 
 |   const bool use_optimistic_operations_; | 
 |   std::string key_; | 
 |  | 
 |   // |last_used_|, |last_modified_| and |data_size_| are copied from the | 
 |   // synchronous entry at the completion of each item of asynchronous IO. | 
 |   // TODO(clamy): Unify last_used_ with data in the index. | 
 |   base::Time last_used_; | 
 |   base::Time last_modified_; | 
 |   int32 data_size_[kSimpleEntryStreamCount]; | 
 |   int32 sparse_data_size_; | 
 |  | 
 |   // Number of times this object has been returned from Backend::OpenEntry() and | 
 |   // Backend::CreateEntry() without subsequent Entry::Close() calls. Used to | 
 |   // notify the backend when this entry not used by any callers. | 
 |   int open_count_; | 
 |  | 
 |   bool doomed_; | 
 |  | 
 |   State state_; | 
 |  | 
 |   // When possible, we compute a crc32, for the data in each entry as we read or | 
 |   // write. For each stream, |crc32s_[index]| is the crc32 of that stream from | 
 |   // [0 .. |crc32s_end_offset_|). If |crc32s_end_offset_[index] == 0| then the | 
 |   // value of |crc32s_[index]| is undefined. | 
 |   int32 crc32s_end_offset_[kSimpleEntryStreamCount]; | 
 |   uint32 crc32s_[kSimpleEntryStreamCount]; | 
 |  | 
 |   // If |have_written_[index]| is true, we have written to the file that | 
 |   // contains stream |index|. | 
 |   bool have_written_[kSimpleEntryStreamCount]; | 
 |  | 
 |   // Reflects how much CRC checking has been done with the entry. This state is | 
 |   // reported on closing each entry stream. | 
 |   CheckCrcResult crc_check_state_[kSimpleEntryStreamCount]; | 
 |  | 
 |   // The |synchronous_entry_| is the worker thread object that performs IO on | 
 |   // entries. It's owned by this SimpleEntryImpl whenever |executing_operation_| | 
 |   // is false (i.e. when an operation is not pending on the worker pool). When | 
 |   // an operation is being executed no one owns the synchronous entry. Therefore | 
 |   // SimpleEntryImpl should not be deleted while an operation is running as that | 
 |   // would leak the SimpleSynchronousEntry. | 
 |   SimpleSynchronousEntry* synchronous_entry_; | 
 |  | 
 |   std::queue<SimpleEntryOperation> pending_operations_; | 
 |  | 
 |   net::BoundNetLog net_log_; | 
 |  | 
 |   scoped_ptr<SimpleEntryOperation> executing_operation_; | 
 |  | 
 |   // Unlike other streams, stream 0 data is read from the disk when the entry is | 
 |   // opened, and then kept in memory. All read/write operations on stream 0 | 
 |   // affect the |stream_0_data_| buffer. When the entry is closed, | 
 |   // |stream_0_data_| is written to the disk. | 
 |   // Stream 0 is kept in memory because it is stored in the same file as stream | 
 |   // 1 on disk, to reduce the number of file descriptors and save disk space. | 
 |   // This strategy allows stream 1 to change size easily. Since stream 0 is only | 
 |   // used to write HTTP headers, the memory consumption of keeping it in memory | 
 |   // is acceptable. | 
 |   scoped_refptr<net::GrowableIOBuffer> stream_0_data_; | 
 | }; | 
 |  | 
 | }  // namespace disk_cache | 
 |  | 
 | #endif  // NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_IMPL_H_ |