| Index: net/http/http_cache.cc
|
| ===================================================================
|
| --- net/http/http_cache.cc (revision 17313)
|
| +++ net/http/http_cache.cc (working copy)
|
| @@ -67,6 +67,8 @@
|
|
|
| //-----------------------------------------------------------------------------
|
|
|
| +static int kTransactionTimeoutInMillisecond = 5000;
|
| +
|
| struct HeaderNameAndValue {
|
| const char* name;
|
| const char* value;
|
| @@ -154,7 +156,9 @@
|
| network_read_callback_(this, &Transaction::OnNetworkReadCompleted)),
|
| ALLOW_THIS_IN_INITIALIZER_LIST(
|
| cache_read_callback_(new CancelableCompletionCallback<Transaction>(
|
| - this, &Transaction::OnCacheReadCompleted))) {
|
| + this, &Transaction::OnCacheReadCompleted))),
|
| + ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
|
| + is_waiting_for_entry_(false) {
|
| }
|
|
|
| // Clean up the transaction.
|
| @@ -206,6 +210,10 @@
|
| // to the transaction. Returns network error code.
|
| int EntryAvailable(ActiveEntry* entry);
|
|
|
| + // Called by the HttpCache when the given disk cache entry is busy. Sets up
|
| + // a timeout alarm to MessageLoop.
|
| + void PendOnEntry(ActiveEntry* entry);
|
| +
|
| private:
|
| // This is a helper function used to trigger a completion callback. It may
|
| // only be called if callback_ is non-null.
|
| @@ -278,6 +286,9 @@
|
| // Called to signal completion of the cache's ReadData method:
|
| void OnCacheReadCompleted(int result);
|
|
|
| + // Called to bypass cache when it took too much time to get access to cache.
|
| + void OnAddToEntryTimeout(ActiveEntry* entry);
|
| +
|
| const HttpRequestInfo* request_;
|
| scoped_ptr<HttpRequestInfo> custom_request_;
|
| HttpCache* cache_;
|
| @@ -296,6 +307,9 @@
|
| CompletionCallbackImpl<Transaction> network_read_callback_;
|
| scoped_refptr<CancelableCompletionCallback<Transaction> >
|
| cache_read_callback_;
|
| +
|
| + ScopedRunnableMethodFactory<Transaction> task_factory_;
|
| + bool is_waiting_for_entry_;
|
| };
|
|
|
| HttpCache::Transaction::~Transaction() {
|
| @@ -538,6 +552,7 @@
|
| //
|
| int rv;
|
| entry_ = entry;
|
| + is_waiting_for_entry_ = false;
|
| switch (mode_) {
|
| case READ:
|
| rv = BeginCacheRead();
|
| @@ -950,6 +965,43 @@
|
| HandleResult(result);
|
| }
|
|
|
| +void HttpCache::Transaction::PendOnEntry(ActiveEntry* entry) {
|
| + if (is_waiting_for_entry_) {
|
| + // Don't add timeout alarm more than once.
|
| + return;
|
| + }
|
| +
|
| + is_waiting_for_entry_ = true;
|
| +
|
| + MessageLoop::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + task_factory_.NewRunnableMethod(&Transaction::OnAddToEntryTimeout, entry),
|
| + kTransactionTimeoutInMillisecond);
|
| +}
|
| +
|
| +void HttpCache::Transaction::OnAddToEntryTimeout(ActiveEntry* entry) {
|
| + if (!is_waiting_for_entry_) {
|
| + // Already added to entry.
|
| + return;
|
| + }
|
| +
|
| + if (mode_ == READ) {
|
| + // We cannot bypass the cache.
|
| + return;
|
| + }
|
| +
|
| + // Check that the writer is still busy, and then give up accessing cache.
|
| + if (entry->writer &&
|
| + entry->writer->GetLoadState() == LOAD_STATE_WAITING_FOR_USER_ACTION) {
|
| + // There is a writer transaction suspended due to some error. Bypass
|
| + // cache if we can.
|
| + entry->pending_queue.remove(this);
|
| + mode_ = NONE;
|
| + is_waiting_for_entry_ = false;
|
| + BeginNetworkRequest();
|
| + }
|
| +}
|
| +
|
| //-----------------------------------------------------------------------------
|
|
|
| HttpCache::HttpCache(ProxyService* proxy_service,
|
| @@ -1317,6 +1369,8 @@
|
|
|
| if (entry->writer || entry->will_process_pending_queue) {
|
| entry->pending_queue.push_back(trans);
|
| + trans->PendOnEntry(entry);
|
| +
|
| return ERR_IO_PENDING;
|
| }
|
|
|
|
|