Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(426)

Unified Diff: net/http/http_cache_shared_writers.h

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Feedback addressed Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_cache.cc ('k') | net/http/http_cache_shared_writers.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_cache_shared_writers.h
diff --git a/net/http/http_cache_shared_writers.h b/net/http/http_cache_shared_writers.h
new file mode 100644
index 0000000000000000000000000000000000000000..84652dde48d8ce2899bd1a6607ca3e6706ff61ee
--- /dev/null
+++ b/net/http/http_cache_shared_writers.h
@@ -0,0 +1,266 @@
+// Copyright (c) 2016 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_SHARED_WRITERS_H_
+#define NET_HTTP_HTTP_CACHE_SHARED_WRITERS_H_
+
+#include <list>
+#include <memory>
+#include "base/memory/weak_ptr.h"
+#include "net/base/completion_callback.h"
+#include "net/http/http_cache.h"
+
+// Shared reading from the network and writing to the cache enables multiple
+// HttpCache::Transactions to drive reading the response body from the network.
+// This ensures that a slow consumer does not starve other consumers of the
+// same resource. Shared reading/writing starts after the first transaction has
+// read the response headers. Subsequent transactions are then able to join
+// reading the response. A shared transaction will either read the already
+// written part of the response from the cache or invoke read on the network
+// and write to the cache, depending on its read offset.
+namespace net {
+
+// SharedWriters 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.
+class HttpCache::SharedWriters {
+ public:
+ // Creates a new SharedWriters object and transfers the ownership of network
+ // transaction to SharedWriters. Consumer must ensure that |*entry| and
+ // |*cache| outlives |this|. It is ok for cache_transaction to die before this
+ // object.
+ static void Create(Transaction* cacheTransaction,
+ std::unique_ptr<HttpTransaction> network_transaction,
+ base::WeakPtr<HttpCache> cache,
+ RequestPriority priority);
+ SharedWriters(base::WeakPtr<HttpCache> cache,
+ ActiveEntry* entry,
+ Transaction* cache_transaction,
+ RequestPriority priority,
+ std::unique_ptr<HttpTransaction> network_transaction);
+ ~SharedWriters();
+
+ // Adds a transaction to SharedWriters. Return value is OK if it is the
+ // current validating transaction and ERR_IO_PENDING if it is waiting.
+ int AddTransaction(Transaction* transaction);
+
+ // Invokes Read on network transaction if a read is not already in progress.
+ // In case a read is already in progress then this transaction is added to
+ // a waiting queue, read_in_progress is set to true and ERR_IO_PENDING is
+ // returned.
+ int Read(scoped_refptr<IOBuffer> buf,
+ int buf_len,
+ const CompletionCallback& callback,
+ Transaction* transaction,
+ bool* read_in_progress);
+
+ // Invokes WriteData on disk entry.
+ int CacheWrite(scoped_refptr<IOBuffer> buf,
+ int write_len,
+ const CompletionCallback& callback,
+ Transaction* transaction);
+
+ // Invoked when the validating transaction wants to continue with the entry
+ // as the validation successfully matched it.
+ void OnValidationMatch(Transaction* transaction, RequestPriority priority);
+
+ // Invoked when the validating transaction cannot continue with the entry as
+ // the validation did not return a 304. Its fine to continue writing to cache
+ // if this is the only transaction, so network transaction ownership is
+ // transferred to SharedWriters. But if there are other transactions, the
+ // entry is doomed and this transaction will continue reading from the
+ // network so the return value will pass the ownership of the network
+ // transaction back to the transaction.
+ std::unique_ptr<HttpTransaction> OnValidationNoMatch(
+ const std::string& key,
+ Transaction* transaction,
+ std::unique_ptr<HttpTransaction> network_transaction,
+ RequestPriority priority);
+
+ // Invoked when DoneReading is invoked on a shared transaction. The
+ // transaction will be removed from |this|. If another transaction is
+ // currently reading, then other transactions will not be impacted.
+ void DoneReading(Transaction* transaction);
+
+ // Invoked when StopCaching is called for a shared writer transaction.
+ // It stops caching only if there are no other transactions.
+ void StopCaching(Transaction* transaction);
+
+ // Removes a transaction which is waiting for Read to be invoked by the
+ // consumer.
+ void RemoveIdleTransaction(Transaction* transaction);
+
+ // Removes a transaction waiting on a Read call.
+ void RemoveWaitingForReadTransaction(Transaction* transaction);
+
+ // Removes the currently validating transaction.
+ void RemoveValidatingTransaction(Transaction* transaction);
+
+ // Removes a pending transaction.
+ bool RemoveWaitingForValidationTransaction(Transaction* transaction);
+
+ // Removes the currently active transaction.
+ void RemoveActiveTransaction(Transaction* transaction);
+
+ // Returns true if this object is empty.
+ bool empty();
+
+ HttpTransaction* network_transaction() { return network_transaction_.get(); }
+
+ // Do not add new transactions if in the process of marking the entry as
+ // truncated.
+ bool CanAddNewTransaction();
+
+ // Invoked when there is a change in a member transaction's priority or a
+ // member transaction is removed.
+ void PriorityChanged();
+
+ private:
+ enum class State {
+ NONE,
+ NETWORK_READ,
+ NETWORK_READ_COMPLETE,
+ CACHE_WRITE_DATA,
+ CACHE_WRITE_DATA_COMPLETE,
+ CACHE_WRITE_TRUNCATED_RESPONSE,
+ CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE,
+ DONE
+ };
+
+ // 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 {
+ Transaction* transaction;
+ scoped_refptr<IOBuffer> read_buf;
+ int read_buf_len;
+ int write_len;
+ const CompletionCallback callback;
+ WaitingForRead(Transaction* transaction,
+ scoped_refptr<IOBuffer> read_buf,
+ int len,
+ const CompletionCallback& consumer_callback);
+ ~WaitingForRead();
+ WaitingForRead(const WaitingForRead&);
+ };
+
+ using WaitingForReadList = std::list<WaitingForRead>;
+ // 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 DoCacheWriteTruncatedResponse();
+ int DoCacheWriteTruncatedResponseComplete(int result);
+
+ // Helper functions for callback.
+
+ void OnNetworkReadFailure(int result);
+
+ bool AttemptTruncation();
+
+ void OnCacheWriteSuccess(int result);
+
+ // Helper function invoked when response is successfully written to the cache.
+ void ResponseDataComplete();
+
+ void OnCacheWriteFailure();
+
+ void FailureCleanup(int error, bool continue_network_reading);
+
+ // All pending transactions will not be tracked by entry.
+ void MoveToPendingQueue();
+
+ // All transactions eligible for shared writing from entry's pending queue
+ // will be tracked from SharedWriters after this function.
+ void MoveFromPendingQueue();
+
+ // When response is completely written, any idle writers are moved to
+ // entry_->readers.
+ void MoveIdleWritersToReaders();
+
+ // Posts a task for invoking the io callback of the first transaction waiting
+ // for validation.
+ void ProcessFirstWaitingValidation();
+
+ void OnProcessFirstWaitingValidation();
+
+ // Notifies the transactions waiting on Read of the result, by posting a task
+ // for each of them.
+ void ProcessWaitingForReadTransactions(int result);
+
+ // Removes the active transaction from |this|.
+ void ResetActiveTransaction(bool continue_network_reading = false);
+
+ // Sets the state of idle writers so that they can fail any subsequent
+ // Read.
+ void SetIdleWritersFailState(int result);
+
+ // Helper function to let the validating transaction continue being a part of
+ // SharedWriters.
+ void ValidationDoneContinue(Transaction* transaction,
+ RequestPriority priority);
+
+ RequestPriority getCurrentHighestPriority();
+
+ // IO Completion callback function.
+ void OnIOComplete(int result);
+
+ State next_state_ = State::NONE;
+
+ // Http Cache.
+ base::WeakPtr<HttpCache> cache_;
+
+ // Owner of this object.
+ ActiveEntry* 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.
+ // After the network read and cache write is successful and data
+ // written to cache, other waiting transactions will be notified.
+ Transaction* active_transaction_ = nullptr;
+
+ // This will point to the currently validating transaction.
+ Transaction* validating_transaction_ = nullptr;
+
+ // These transactions are waiting for the validating transaction to complete
+ // and then the first of these will begin validation.
+ TransactionList waiting_for_validation_;
+
+ WaitingForReadList waiting_for_read_;
+
+ // Includes a transaction if it is past the validation stage.
+ TransactionSet all_writers_;
+
+ // Current priority of the request. If a higher priority transaction is
+ // added, the priority of network transaction will be increased.
+ RequestPriority priority_ = DEFAULT_PRIORITY;
+
+ CompletionCallback callback_; // Consumer's callback.
+ base::Callback<void(bool*)> cache_callback_; // Cache callback.
+ CompletionCallback io_callback_;
+
+ // Saved so it could be returned to the consumer after marking the entry as
+ // truncated, if needed.
+ int rv_post_truncation_ = 0;
+
+ base::WeakPtrFactory<SharedWriters> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedWriters);
+};
+
+} // namespace net
+
+#endif // NET_HTTP_HTTP_CACHE_SHARED_WRITERS_H_
« no previous file with comments | « net/http/http_cache.cc ('k') | net/http/http_cache_shared_writers.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698