123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- // Copyright (c) 2017 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_HTTP_HTTP_CACHE_WRITERS_H_
- #define NET_HTTP_HTTP_CACHE_WRITERS_H_
- #include <map>
- #include <memory>
- #include "base/memory/raw_ptr.h"
- #include "base/memory/weak_ptr.h"
- #include "net/base/completion_once_callback.h"
- #include "net/http/http_cache.h"
- #include "net/http/http_response_info.h"
- namespace crypto {
- class SecureHash;
- }
- namespace net {
- class HttpResponseInfo;
- class IOBuffer;
- class PartialData;
- // If multiple HttpCache::Transactions are accessing the same cache entry
- // simultaneously, their access to the data read from network is synchronized
- // by HttpCache::Writers. This enables each of those transactions to drive
- // reading the response body from the network ensuring a slow consumer does not
- // starve other consumers of the same resource.
- //
- // Writers represents the set of all HttpCache::Transactions that are reading
- // from the network using the same network transaction and writing to the same
- // cache entry. It is owned by the ActiveEntry. The writers object must be
- // deleted when HttpCache::WritersDoneWritingToEntry is called as it doesn't
- // expect any of its ongoing IO transactions (e.g., network reads or cache
- // writers) to complete after that point and won't know what to do with them.
- class NET_EXPORT_PRIVATE HttpCache::Writers {
- public:
- // This is the information maintained by Writers in the context of each
- // transaction.
- // |partial| is owned by the transaction and to be sure there are no
- // dangling pointers, it must be ensured that transaction's reference and
- // this information will be removed from writers once the transaction is
- // deleted.
- struct NET_EXPORT_PRIVATE TransactionInfo {
- TransactionInfo(PartialData* partial,
- bool truncated,
- HttpResponseInfo info);
- ~TransactionInfo();
- TransactionInfo& operator=(const TransactionInfo&);
- TransactionInfo(const TransactionInfo&);
- raw_ptr<PartialData> partial;
- bool truncated;
- HttpResponseInfo response_info;
- };
- // |cache| and |entry| must outlive this object.
- Writers(HttpCache* cache, HttpCache::ActiveEntry* entry);
- Writers(const Writers&) = delete;
- Writers& operator=(const Writers&) = delete;
- ~Writers();
- // Retrieves data from the network transaction associated with the Writers
- // object. This may be done directly (via a network read into |*buf->data()|)
- // or indirectly (by copying from another transactions buffer into
- // |*buf->data()| on network read completion) depending on whether or not a
- // read is currently in progress. May return the result synchronously or
- // return ERR_IO_PENDING: if ERR_IO_PENDING is returned, |callback| will be
- // run to inform the consumer of the result of the Read().
- // |transaction| may be removed while Read() is ongoing. In that case Writers
- // will still complete the Read() processing but will not invoke the
- // |callback|.
- int Read(scoped_refptr<IOBuffer> buf,
- int buf_len,
- CompletionOnceCallback callback,
- Transaction* transaction);
- // Invoked when StopCaching is called on a member transaction.
- // It stops caching only if there are no other transactions. Returns true if
- // caching can be stopped.
- // |keep_entry| should be true if the entry needs to be preserved after
- // truncation.
- bool StopCaching(bool keep_entry);
- // Membership functions like AddTransaction and RemoveTransaction are invoked
- // by HttpCache on behalf of the HttpCache::Transaction.
- // Adds an HttpCache::Transaction to Writers.
- // Should only be invoked if CanAddWriters() returns true.
- // |parallel_writing_pattern| governs whether writing is an exclusive
- // operation implying that Writers can contain at most one transaction till
- // the completion of the response body. It is illegal to invoke with
- // |parallel_writing_pattern| as PARALLEL_WRITING_NOT_JOIN* if there is
- // already a transaction present.
- // |transaction| can be destroyed at any point and it should invoke
- // HttpCache::DoneWithEntry() during its destruction. This will also ensure
- // any pointers in |info| are not accessed after the transaction is destroyed.
- void AddTransaction(Transaction* transaction,
- ParallelWritingPattern initial_writing_pattern,
- RequestPriority priority,
- const TransactionInfo& info);
- // Invoked when the transaction is done working with the entry.
- void RemoveTransaction(Transaction* transaction, bool success);
- // Invoked when there is a change in a member transaction's priority or a
- // member transaction is removed.
- void UpdatePriority();
- // Returns true if this object is empty.
- bool IsEmpty() const { return all_writers_.empty(); }
- // Invoked during HttpCache's destruction.
- void Clear() { all_writers_.clear(); }
- // Returns true if |transaction| is part of writers.
- bool HasTransaction(const Transaction* transaction) const {
- return all_writers_.count(const_cast<Transaction*>(transaction)) > 0;
- }
- // Returns true if more writers can be added for shared writing. Also fills in
- // the |reason| for why a transaction cannot be added.
- bool CanAddWriters(ParallelWritingPattern* reason);
- // Returns if only one transaction can be a member of writers.
- bool IsExclusive() const { return is_exclusive_; }
- // Returns the network transaction which may be nullptr for range requests.
- const HttpTransaction* network_transaction() const {
- return network_transaction_.get();
- }
- void CloseConnectionOnDestruction();
- // Returns the load state of the |network_transaction_| if present else
- // returns LOAD_STATE_IDLE.
- LoadState GetLoadState() const;
- // Sets the network transaction argument to |network_transaction_|. Must be
- // invoked before Read can be invoked. If |checksum| is set it will be
- // validated and the cache entry will be marked unusable if it doesn't match.
- void SetNetworkTransaction(
- Transaction* transaction,
- std::unique_ptr<HttpTransaction> network_transaction,
- std::unique_ptr<crypto::SecureHash> checksum);
- // Resets the network transaction to nullptr. Required for range requests as
- // they might use the current network transaction only for part of the
- // request. Must only be invoked for range requests.
- void ResetNetworkTransaction();
- // Returns if response is only being read from the network.
- bool network_read_only() const { return network_read_only_; }
- int GetTransactionsCount() const { return all_writers_.size(); }
- private:
- friend class WritersTest;
- enum class State {
- UNSET,
- NONE,
- NETWORK_READ,
- NETWORK_READ_COMPLETE,
- CACHE_WRITE_DATA,
- CACHE_WRITE_DATA_COMPLETE,
- MARK_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE,
- MARK_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE_COMPLETE,
- };
- // These transactions are waiting on Read. After the active transaction
- // completes writing the data to the cache, their buffer would be filled with
- // the data and their callback will be invoked.
- struct WaitingForRead {
- scoped_refptr<IOBuffer> read_buf;
- int read_buf_len;
- int write_len = 0;
- CompletionOnceCallback callback;
- WaitingForRead(scoped_refptr<IOBuffer> read_buf,
- int len,
- CompletionOnceCallback consumer_callback);
- ~WaitingForRead();
- WaitingForRead(WaitingForRead&&);
- };
- using WaitingForReadMap = std::map<Transaction*, WaitingForRead>;
- using TransactionMap = std::map<Transaction*, TransactionInfo>;
- // Runs the state transition loop. Resets and calls |callback_| on exit,
- // unless the return value is ERR_IO_PENDING.
- int DoLoop(int result);
- // State machine functions.
- int DoNetworkRead();
- int DoNetworkReadComplete(int result);
- int DoCacheWriteData(int num_bytes);
- int DoCacheWriteDataComplete(int result);
- int DoMarkSingleKeyedCacheEntryUnusable();
- int DoMarkSingleKeyedCacheEntryUnusableComplete(int result);
- // Helper functions for callback.
- void OnNetworkReadFailure(int result);
- void OnCacheWriteFailure();
- void OnDataReceived(int result);
- // Completes any pending IO_PENDING read operations by copying any received
- // bytes from read_buf_ to the given buffer and posts a task to run the
- // callback with |result|.
- void CompleteWaitingForReadTransactions(int result);
- // Removes idle writers, passing |result| which is to be used for any
- // subsequent read transaction.
- void RemoveIdleWriters(int result);
- // Invoked when |active_transaction_| fails to read from network or write to
- // cache. |error| indicates network read error code or cache write error.
- void ProcessFailure(int error);
- // Returns true if |this| only contains idle writers. Idle writers are those
- // that are waiting for Read to be invoked by the consumer.
- bool ContainsOnlyIdleWriters() const;
- // Returns true if its worth marking the entry as truncated.
- // TODO(shivanisha): Refactor this so that it could be const.
- bool ShouldTruncate();
- // Enqueues a truncation operation to the entry. Ignores the response.
- void TruncateEntry();
- // Remove the transaction.
- void EraseTransaction(Transaction* transaction, int result);
- TransactionMap::iterator EraseTransaction(TransactionMap::iterator it,
- int result);
- void SetCacheCallback(bool success, const TransactionSet& make_readers);
- // IO Completion callback function.
- void OnIOComplete(int result);
- State next_state_ = State::NONE;
- // True if only reading from network and not writing to cache.
- bool network_read_only_ = false;
- raw_ptr<HttpCache> const cache_ = nullptr;
- // Owner of |this|.
- raw_ptr<ActiveEntry> const entry_ = nullptr;
- std::unique_ptr<HttpTransaction> network_transaction_;
- scoped_refptr<IOBuffer> read_buf_;
- int io_buf_len_ = 0;
- int write_len_ = 0;
- // The cache transaction that is the current consumer of network_transaction_
- // ::Read or writing to the entry and is waiting for the operation to be
- // completed. This is used to ensure there is at most one consumer of
- // network_transaction_ at a time.
- raw_ptr<Transaction> active_transaction_ = nullptr;
- // Transactions whose consumers have invoked Read, but another transaction is
- // currently the |active_transaction_|. After the network read and cache write
- // is complete, the waiting transactions will be notified.
- WaitingForReadMap waiting_for_read_;
- // Includes all transactions. ResetStateForEmptyWriters should be invoked
- // whenever all_writers_ becomes empty.
- TransactionMap all_writers_;
- // True if multiple transactions are not allowed e.g. for partial requests.
- bool is_exclusive_ = false;
- ParallelWritingPattern parallel_writing_pattern_ = PARALLEL_WRITING_NONE;
- // Current priority of the request. It is always the maximum of all the writer
- // transactions.
- RequestPriority priority_ = MINIMUM_PRIORITY;
- // Response info of the most recent transaction added to Writers will be used
- // to write back the headers along with the truncated bit set. This is done so
- // that we don't overwrite headers written by a more recent transaction with
- // older headers while truncating.
- HttpResponseInfo response_info_truncation_;
- // Do not mark a partial request as truncated if it is not already a truncated
- // entry to start with.
- bool partial_do_not_truncate_ = false;
- // True if the entry should be kept, even if the response was not completely
- // written.
- bool should_keep_entry_ = true;
- // Set if we are currently calculating a checksum of the resource to validate
- // it against the expected checksum for the single-keyed cache. Initialised
- // with selected headers and accumulates the body of the response.
- std::unique_ptr<crypto::SecureHash> checksum_;
- CompletionOnceCallback callback_; // Callback for active_transaction_.
- // Since cache_ can destroy |this|, |cache_callback_| is only invoked at the
- // end of DoLoop().
- base::OnceClosure cache_callback_; // Callback for cache_.
- base::WeakPtrFactory<Writers> weak_factory_{this};
- };
- } // namespace net
- #endif // NET_HTTP_HTTP_CACHE_WRITERS_H_
|