http_cache_writers.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Copyright (c) 2017 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. #ifndef NET_HTTP_HTTP_CACHE_WRITERS_H_
  5. #define NET_HTTP_HTTP_CACHE_WRITERS_H_
  6. #include <map>
  7. #include <memory>
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/memory/weak_ptr.h"
  10. #include "net/base/completion_once_callback.h"
  11. #include "net/http/http_cache.h"
  12. #include "net/http/http_response_info.h"
  13. namespace crypto {
  14. class SecureHash;
  15. }
  16. namespace net {
  17. class HttpResponseInfo;
  18. class IOBuffer;
  19. class PartialData;
  20. // If multiple HttpCache::Transactions are accessing the same cache entry
  21. // simultaneously, their access to the data read from network is synchronized
  22. // by HttpCache::Writers. This enables each of those transactions to drive
  23. // reading the response body from the network ensuring a slow consumer does not
  24. // starve other consumers of the same resource.
  25. //
  26. // Writers represents the set of all HttpCache::Transactions that are reading
  27. // from the network using the same network transaction and writing to the same
  28. // cache entry. It is owned by the ActiveEntry. The writers object must be
  29. // deleted when HttpCache::WritersDoneWritingToEntry is called as it doesn't
  30. // expect any of its ongoing IO transactions (e.g., network reads or cache
  31. // writers) to complete after that point and won't know what to do with them.
  32. class NET_EXPORT_PRIVATE HttpCache::Writers {
  33. public:
  34. // This is the information maintained by Writers in the context of each
  35. // transaction.
  36. // |partial| is owned by the transaction and to be sure there are no
  37. // dangling pointers, it must be ensured that transaction's reference and
  38. // this information will be removed from writers once the transaction is
  39. // deleted.
  40. struct NET_EXPORT_PRIVATE TransactionInfo {
  41. TransactionInfo(PartialData* partial,
  42. bool truncated,
  43. HttpResponseInfo info);
  44. ~TransactionInfo();
  45. TransactionInfo& operator=(const TransactionInfo&);
  46. TransactionInfo(const TransactionInfo&);
  47. raw_ptr<PartialData> partial;
  48. bool truncated;
  49. HttpResponseInfo response_info;
  50. };
  51. // |cache| and |entry| must outlive this object.
  52. Writers(HttpCache* cache, HttpCache::ActiveEntry* entry);
  53. Writers(const Writers&) = delete;
  54. Writers& operator=(const Writers&) = delete;
  55. ~Writers();
  56. // Retrieves data from the network transaction associated with the Writers
  57. // object. This may be done directly (via a network read into |*buf->data()|)
  58. // or indirectly (by copying from another transactions buffer into
  59. // |*buf->data()| on network read completion) depending on whether or not a
  60. // read is currently in progress. May return the result synchronously or
  61. // return ERR_IO_PENDING: if ERR_IO_PENDING is returned, |callback| will be
  62. // run to inform the consumer of the result of the Read().
  63. // |transaction| may be removed while Read() is ongoing. In that case Writers
  64. // will still complete the Read() processing but will not invoke the
  65. // |callback|.
  66. int Read(scoped_refptr<IOBuffer> buf,
  67. int buf_len,
  68. CompletionOnceCallback callback,
  69. Transaction* transaction);
  70. // Invoked when StopCaching is called on a member transaction.
  71. // It stops caching only if there are no other transactions. Returns true if
  72. // caching can be stopped.
  73. // |keep_entry| should be true if the entry needs to be preserved after
  74. // truncation.
  75. bool StopCaching(bool keep_entry);
  76. // Membership functions like AddTransaction and RemoveTransaction are invoked
  77. // by HttpCache on behalf of the HttpCache::Transaction.
  78. // Adds an HttpCache::Transaction to Writers.
  79. // Should only be invoked if CanAddWriters() returns true.
  80. // |parallel_writing_pattern| governs whether writing is an exclusive
  81. // operation implying that Writers can contain at most one transaction till
  82. // the completion of the response body. It is illegal to invoke with
  83. // |parallel_writing_pattern| as PARALLEL_WRITING_NOT_JOIN* if there is
  84. // already a transaction present.
  85. // |transaction| can be destroyed at any point and it should invoke
  86. // HttpCache::DoneWithEntry() during its destruction. This will also ensure
  87. // any pointers in |info| are not accessed after the transaction is destroyed.
  88. void AddTransaction(Transaction* transaction,
  89. ParallelWritingPattern initial_writing_pattern,
  90. RequestPriority priority,
  91. const TransactionInfo& info);
  92. // Invoked when the transaction is done working with the entry.
  93. void RemoveTransaction(Transaction* transaction, bool success);
  94. // Invoked when there is a change in a member transaction's priority or a
  95. // member transaction is removed.
  96. void UpdatePriority();
  97. // Returns true if this object is empty.
  98. bool IsEmpty() const { return all_writers_.empty(); }
  99. // Invoked during HttpCache's destruction.
  100. void Clear() { all_writers_.clear(); }
  101. // Returns true if |transaction| is part of writers.
  102. bool HasTransaction(const Transaction* transaction) const {
  103. return all_writers_.count(const_cast<Transaction*>(transaction)) > 0;
  104. }
  105. // Returns true if more writers can be added for shared writing. Also fills in
  106. // the |reason| for why a transaction cannot be added.
  107. bool CanAddWriters(ParallelWritingPattern* reason);
  108. // Returns if only one transaction can be a member of writers.
  109. bool IsExclusive() const { return is_exclusive_; }
  110. // Returns the network transaction which may be nullptr for range requests.
  111. const HttpTransaction* network_transaction() const {
  112. return network_transaction_.get();
  113. }
  114. void CloseConnectionOnDestruction();
  115. // Returns the load state of the |network_transaction_| if present else
  116. // returns LOAD_STATE_IDLE.
  117. LoadState GetLoadState() const;
  118. // Sets the network transaction argument to |network_transaction_|. Must be
  119. // invoked before Read can be invoked. If |checksum| is set it will be
  120. // validated and the cache entry will be marked unusable if it doesn't match.
  121. void SetNetworkTransaction(
  122. Transaction* transaction,
  123. std::unique_ptr<HttpTransaction> network_transaction,
  124. std::unique_ptr<crypto::SecureHash> checksum);
  125. // Resets the network transaction to nullptr. Required for range requests as
  126. // they might use the current network transaction only for part of the
  127. // request. Must only be invoked for range requests.
  128. void ResetNetworkTransaction();
  129. // Returns if response is only being read from the network.
  130. bool network_read_only() const { return network_read_only_; }
  131. int GetTransactionsCount() const { return all_writers_.size(); }
  132. private:
  133. friend class WritersTest;
  134. enum class State {
  135. UNSET,
  136. NONE,
  137. NETWORK_READ,
  138. NETWORK_READ_COMPLETE,
  139. CACHE_WRITE_DATA,
  140. CACHE_WRITE_DATA_COMPLETE,
  141. MARK_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE,
  142. MARK_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE_COMPLETE,
  143. };
  144. // These transactions are waiting on Read. After the active transaction
  145. // completes writing the data to the cache, their buffer would be filled with
  146. // the data and their callback will be invoked.
  147. struct WaitingForRead {
  148. scoped_refptr<IOBuffer> read_buf;
  149. int read_buf_len;
  150. int write_len = 0;
  151. CompletionOnceCallback callback;
  152. WaitingForRead(scoped_refptr<IOBuffer> read_buf,
  153. int len,
  154. CompletionOnceCallback consumer_callback);
  155. ~WaitingForRead();
  156. WaitingForRead(WaitingForRead&&);
  157. };
  158. using WaitingForReadMap = std::map<Transaction*, WaitingForRead>;
  159. using TransactionMap = std::map<Transaction*, TransactionInfo>;
  160. // Runs the state transition loop. Resets and calls |callback_| on exit,
  161. // unless the return value is ERR_IO_PENDING.
  162. int DoLoop(int result);
  163. // State machine functions.
  164. int DoNetworkRead();
  165. int DoNetworkReadComplete(int result);
  166. int DoCacheWriteData(int num_bytes);
  167. int DoCacheWriteDataComplete(int result);
  168. int DoMarkSingleKeyedCacheEntryUnusable();
  169. int DoMarkSingleKeyedCacheEntryUnusableComplete(int result);
  170. // Helper functions for callback.
  171. void OnNetworkReadFailure(int result);
  172. void OnCacheWriteFailure();
  173. void OnDataReceived(int result);
  174. // Completes any pending IO_PENDING read operations by copying any received
  175. // bytes from read_buf_ to the given buffer and posts a task to run the
  176. // callback with |result|.
  177. void CompleteWaitingForReadTransactions(int result);
  178. // Removes idle writers, passing |result| which is to be used for any
  179. // subsequent read transaction.
  180. void RemoveIdleWriters(int result);
  181. // Invoked when |active_transaction_| fails to read from network or write to
  182. // cache. |error| indicates network read error code or cache write error.
  183. void ProcessFailure(int error);
  184. // Returns true if |this| only contains idle writers. Idle writers are those
  185. // that are waiting for Read to be invoked by the consumer.
  186. bool ContainsOnlyIdleWriters() const;
  187. // Returns true if its worth marking the entry as truncated.
  188. // TODO(shivanisha): Refactor this so that it could be const.
  189. bool ShouldTruncate();
  190. // Enqueues a truncation operation to the entry. Ignores the response.
  191. void TruncateEntry();
  192. // Remove the transaction.
  193. void EraseTransaction(Transaction* transaction, int result);
  194. TransactionMap::iterator EraseTransaction(TransactionMap::iterator it,
  195. int result);
  196. void SetCacheCallback(bool success, const TransactionSet& make_readers);
  197. // IO Completion callback function.
  198. void OnIOComplete(int result);
  199. State next_state_ = State::NONE;
  200. // True if only reading from network and not writing to cache.
  201. bool network_read_only_ = false;
  202. raw_ptr<HttpCache> const cache_ = nullptr;
  203. // Owner of |this|.
  204. raw_ptr<ActiveEntry> const entry_ = nullptr;
  205. std::unique_ptr<HttpTransaction> network_transaction_;
  206. scoped_refptr<IOBuffer> read_buf_;
  207. int io_buf_len_ = 0;
  208. int write_len_ = 0;
  209. // The cache transaction that is the current consumer of network_transaction_
  210. // ::Read or writing to the entry and is waiting for the operation to be
  211. // completed. This is used to ensure there is at most one consumer of
  212. // network_transaction_ at a time.
  213. raw_ptr<Transaction> active_transaction_ = nullptr;
  214. // Transactions whose consumers have invoked Read, but another transaction is
  215. // currently the |active_transaction_|. After the network read and cache write
  216. // is complete, the waiting transactions will be notified.
  217. WaitingForReadMap waiting_for_read_;
  218. // Includes all transactions. ResetStateForEmptyWriters should be invoked
  219. // whenever all_writers_ becomes empty.
  220. TransactionMap all_writers_;
  221. // True if multiple transactions are not allowed e.g. for partial requests.
  222. bool is_exclusive_ = false;
  223. ParallelWritingPattern parallel_writing_pattern_ = PARALLEL_WRITING_NONE;
  224. // Current priority of the request. It is always the maximum of all the writer
  225. // transactions.
  226. RequestPriority priority_ = MINIMUM_PRIORITY;
  227. // Response info of the most recent transaction added to Writers will be used
  228. // to write back the headers along with the truncated bit set. This is done so
  229. // that we don't overwrite headers written by a more recent transaction with
  230. // older headers while truncating.
  231. HttpResponseInfo response_info_truncation_;
  232. // Do not mark a partial request as truncated if it is not already a truncated
  233. // entry to start with.
  234. bool partial_do_not_truncate_ = false;
  235. // True if the entry should be kept, even if the response was not completely
  236. // written.
  237. bool should_keep_entry_ = true;
  238. // Set if we are currently calculating a checksum of the resource to validate
  239. // it against the expected checksum for the single-keyed cache. Initialised
  240. // with selected headers and accumulates the body of the response.
  241. std::unique_ptr<crypto::SecureHash> checksum_;
  242. CompletionOnceCallback callback_; // Callback for active_transaction_.
  243. // Since cache_ can destroy |this|, |cache_callback_| is only invoked at the
  244. // end of DoLoop().
  245. base::OnceClosure cache_callback_; // Callback for cache_.
  246. base::WeakPtrFactory<Writers> weak_factory_{this};
  247. };
  248. } // namespace net
  249. #endif // NET_HTTP_HTTP_CACHE_WRITERS_H_