http_cache.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_cache.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/file_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/field_trial.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h"
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/worker_pool.h"
30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "net/base/cache_type.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_data_stream.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/disk_cache/disk_cache.h"
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/http/disk_based_cert_cache.h"
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/disk_cache_based_quic_server_info.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_cache_transaction.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_layer.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_info.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/crypto/quic_server_info.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool UseCertCache() {
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return base::FieldTrialList::FindFullName("CertCacheTrial") ==
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         "ExperimentGroup";
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Adaptor to delete a file on a worker thread.
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeletePath(base::FilePath path) {
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::DeleteFile(path, false);
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::DefaultBackend::DefaultBackend(CacheType type,
64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                          BackendType backend_type,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          const base::FilePath& path,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int max_bytes,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          base::MessageLoopProxy* thread)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(type),
69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      backend_type_(backend_type),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path_(path),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_bytes_(max_bytes),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thread_(thread) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::DefaultBackend::~DefaultBackend() {}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::BackendFactory* HttpCache::DefaultBackend::InMemory(int max_bytes) {
79a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return new DefaultBackend(MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT,
80a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            base::FilePath(), max_bytes, NULL);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::DefaultBackend::CreateBackend(
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    NetLog* net_log, scoped_ptr<disk_cache::Backend>* backend,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& callback) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(max_bytes_, 0);
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return disk_cache::CreateCacheBackend(type_,
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        backend_type_,
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        path_,
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        max_bytes_,
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        true,
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        thread_.get(),
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        net_log,
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                        backend,
95a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                        callback);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::ActiveEntry::ActiveEntry(disk_cache::Entry* entry)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : disk_entry(entry),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      writer(NULL),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      will_process_pending_queue(false),
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      doomed(false) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::ActiveEntry::~ActiveEntry() {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disk_entry) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    disk_entry->Close();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    disk_entry = NULL;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This structure keeps track of work items that are attempting to create or
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// open cache entries or the backend itself.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HttpCache::PendingOp {
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  PendingOp() : disk_entry(NULL), writer(NULL) {}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PendingOp() {}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache::Entry* disk_entry;
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<disk_cache::Backend> backend;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* writer;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback callback;  // BackendCallback.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemList pending_queue;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The type of operation represented by a work item.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum WorkItemOperation {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WI_CREATE_BACKEND,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WI_OPEN_ENTRY,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WI_CREATE_ENTRY,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WI_DOOM_ENTRY
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A work item encapsulates a single request to the backend with all the
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// information needed to complete that request.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HttpCache::WorkItem {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem(WorkItemOperation operation, Transaction* trans, ActiveEntry** entry)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : operation_(operation),
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        trans_(trans),
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entry_(entry),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        backend_(NULL) {}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem(WorkItemOperation operation, Transaction* trans,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           const net::CompletionCallback& cb, disk_cache::Backend** backend)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : operation_(operation),
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        trans_(trans),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entry_(NULL),
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_(cb),
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        backend_(backend) {}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~WorkItem() {}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calls back the transaction with the result of the operation.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyTransaction(int result, ActiveEntry* entry) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!entry || entry->disk_entry);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry_)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *entry_ = entry;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (trans_)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      trans_->io_callback().Run(result);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the caller about the operation completion. Returns true if the
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback was invoked.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool DoCallback(int result, disk_cache::Backend* backend) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (backend_)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *backend_ = backend;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback_.is_null()) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_.Run(result);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemOperation operation() { return operation_; }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearTransaction() { trans_ = NULL; }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearEntry() { entry_ = NULL; }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearCallback() { callback_.Reset(); }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Matches(Transaction* trans) const { return trans == trans_; }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsValid() const { return trans_ || entry_ || !callback_.is_null(); }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemOperation operation_;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Transaction* trans_;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry** entry_;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CompletionCallback callback_;  // User callback.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache::Backend** backend_;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class encapsulates a transaction whose only purpose is to write metadata
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to a given entry.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HttpCache::MetadataWriter {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MetadataWriter(HttpCache::Transaction* trans)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : transaction_(trans),
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        verified_(false),
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buf_len_(0) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~MetadataWriter() {}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implements the bulk of HttpCache::WriteMetadata.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Write(const GURL& url, base::Time expected_response_time, IOBuffer* buf,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             int buf_len);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyResponse(int result);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SelfDestroy();
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnIOComplete(int result);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpCache::Transaction> transaction_;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified_;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf_;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int buf_len_;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time expected_response_time_;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request_info_;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MetadataWriter);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::MetadataWriter::Write(const GURL& url,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Time expected_response_time,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      IOBuffer* buf, int buf_len) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(buf_len, 0);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf->data());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info_.url = url;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info_.method = "GET";
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info_.load_flags = LOAD_ONLY_FROM_CACHE;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_response_time_ = expected_response_time;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf_ = buf;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf_len_ = buf_len;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verified_ = false;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transaction_->Start(
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &request_info_,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MetadataWriter::OnIOComplete, base::Unretained(this)),
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BoundNetLog());
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyResponse(rv);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::MetadataWriter::VerifyResponse(int result) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verified_ = true;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SelfDestroy();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response_info = transaction_->GetResponseInfo();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(response_info->was_cached);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_info->response_time != expected_response_time_)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SelfDestroy();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = transaction_->WriteMetadata(
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buf_.get(),
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buf_len_,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MetadataWriter::OnIOComplete, base::Unretained(this)));
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != ERR_IO_PENDING)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelfDestroy();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::MetadataWriter::SelfDestroy() {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::MetadataWriter::OnIOComplete(int result) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!verified_)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return VerifyResponse(result);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelfDestroy();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class HttpCache::QuicServerInfoFactoryAdaptor : public QuicServerInfoFactory {
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicServerInfoFactoryAdaptor(HttpCache* http_cache)
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : http_cache_(http_cache) {
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual QuicServerInfo* GetForServer(
285e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const QuicServerId& server_id) OVERRIDE {
286e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return new DiskCacheBasedQuicServerInfo(server_id, http_cache_);
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  HttpCache* const http_cache_;
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//-----------------------------------------------------------------------------
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::HttpCache(const net::HttpNetworkSession::Params& params,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     BackendFactory* backend_factory)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net_log_(params.net_log),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_factory_(backend_factory),
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      building_backend_(false),
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      bypass_lock_for_test_(false),
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_(NORMAL),
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))),
302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_factory_(this) {
30346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SetupQuicServerInfoFactory(network_layer_->GetSession());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This call doesn't change the shared |session|'s QuicServerInfoFactory because
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |session| is shared.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::HttpCache(HttpNetworkSession* session,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     BackendFactory* backend_factory)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net_log_(session->net_log()),
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_factory_(backend_factory),
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      building_backend_(false),
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      bypass_lock_for_test_(false),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_(NORMAL),
316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      network_layer_(new HttpNetworkLayer(session)),
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_factory_(this) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::HttpCache(HttpTransactionFactory* network_layer,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     NetLog* net_log,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     BackendFactory* backend_factory)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net_log_(net_log),
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_factory_(backend_factory),
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      building_backend_(false),
326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      bypass_lock_for_test_(false),
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_(NORMAL),
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      network_layer_(network_layer),
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_factory_(this) {
33046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SetupQuicServerInfoFactory(network_layer_->GetSession());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::~HttpCache() {
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Transactions should see an invalid cache after this point; otherwise they
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // could see an inconsistent object (half destroyed).
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have any active entries remaining, then we need to deactivate them.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may have some pending calls to OnProcessPendingQueue, but since those
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // won't run (due to our destruction), we can simply ignore the corresponding
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will_process_pending_queue flag.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!active_entries_.empty()) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ActiveEntry* entry = active_entries_.begin()->second;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->will_process_pending_queue = false;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->pending_queue.clear();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->readers.clear();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->writer = NULL;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeactivateEntry(entry);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&doomed_entries_);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Before deleting pending_ops_, we have to make sure that the disk cache is
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // done with said operations, or it will attempt to use deleted data.
355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  cert_cache_.reset();
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache_.reset();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOpsMap::iterator pending_it = pending_ops_.begin();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; pending_it != pending_ops_.end(); ++pending_it) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are not notifying the transactions about the cache going away, even
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // though they are waiting for a callback that will never fire.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOp* pending_op = pending_it->second;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete pending_op->writer;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool delete_pending_op = true;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (building_backend_) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we don't have a backend, when its construction finishes it will
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // deliver the callbacks.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!pending_op->callback.is_null()) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If not null, the callback will delete the pending operation later.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete_pending_op = false;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_op->callback.Reset();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLDeleteElements(&pending_op->pending_queue);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delete_pending_op)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete pending_op;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::GetBackend(disk_cache::Backend** backend,
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const CompletionCallback& callback) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disk_cache_.get()) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *backend = disk_cache_.get();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateBackend(backend, callback);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)disk_cache::Backend* HttpCache::GetCurrentBackend() const {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return disk_cache_.get();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::ParseResponseInfo(const char* data, int len,
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  HttpResponseInfo* response_info,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool* response_truncated) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pickle pickle(data, len);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return response_info->InitFromPickle(pickle, response_truncated);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::WriteMetadata(const GURL& url,
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              RequestPriority priority,
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              base::Time expected_response_time,
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              IOBuffer* buf,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int buf_len) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buf_len)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do lazy initialization of disk cache if needed.
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!disk_cache_.get()) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't care about the result.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateBackend(NULL, net::CompletionCallback());
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpCache::Transaction* trans =
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new HttpCache::Transaction(priority, this);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MetadataWriter* writer = new MetadataWriter(trans);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The writer will self destruct when done.
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  writer->Write(url, expected_response_time, buf, buf_len);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::CloseAllConnections() {
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  HttpNetworkSession* session = GetSession();
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (session)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session->CloseAllConnections();
432d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::CloseIdleConnections() {
435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  HttpNetworkSession* session = GetSession();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (session)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session->CloseIdleConnections();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnExternalCacheHit(const GURL& url,
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& http_method) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!disk_cache_.get())
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request_info;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info.url = url;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info.method = http_method;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key = GenerateCacheKey(&request_info);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache_->OnExternalCacheHit(key);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpCache::InitializeInfiniteCache(const base::FilePath& path) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::FieldTrialList::FindFullName("InfiniteCache") != "Yes")
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WorkerPool::PostTask(FROM_HERE, base::Bind(&DeletePath, path), true);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int HttpCache::CreateTransaction(RequestPriority priority,
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 scoped_ptr<HttpTransaction>* trans) {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do lazy initialization of disk cache if needed.
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!disk_cache_.get()) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't care about the result.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateBackend(NULL, net::CompletionCallback());
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch   HttpCache::Transaction* transaction =
467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new HttpCache::Transaction(priority, this);
468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch   if (bypass_lock_for_test_)
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    transaction->BypassLockForTest();
470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  trans->reset(transaction);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache* HttpCache::GetCache() {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpNetworkSession* HttpCache::GetSession() {
480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return network_layer_->GetSession();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<HttpTransactionFactory>
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HttpCache::SetHttpNetworkTransactionFactoryForTesting(
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<HttpTransactionFactory> new_network_layer) {
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<HttpTransactionFactory> old_network_layer(network_layer_.Pass());
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  network_layer_ = new_network_layer.Pass();
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return old_network_layer.Pass();
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::CreateBackend(disk_cache::Backend** backend,
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const net::CompletionCallback& callback) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!backend_factory_.get())
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_FAILED;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  building_backend_ = true;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WorkItem> item(new WorkItem(WI_CREATE_BACKEND, NULL, callback,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         backend));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the only operation that we can do that is not related to any given
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entry, so we use an empty key for it.
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PendingOp* pending_op = GetPendingOp(std::string());
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback.is_null())
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_op->pending_queue.push_back(item.release());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->writer = item.release();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
516010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                    GetWeakPtr(), pending_op);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = backend_factory_->CreateBackend(net_log_, &pending_op->backend,
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           pending_op->callback);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->writer->ClearCallback();
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->callback.Run(rv);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::GetBackendForTransaction(Transaction* trans) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disk_cache_.get())
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!building_backend_)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_FAILED;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* item = new WorkItem(
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WI_CREATE_BACKEND, trans, net::CompletionCallback(), NULL);
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PendingOp* pending_op = GetPendingOp(std::string());
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->writer);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->pending_queue.push_back(item);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_IO_PENDING;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generate a key that can be used inside the cache.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string HttpCache::GenerateCacheKey(const HttpRequestInfo* request) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strip out the reference, username, and password sections of the URL.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url = HttpUtil::SpecForRequest(request->url);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ != DISABLE);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == NORMAL) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No valid URL can begin with numerals, so we should not have to worry
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // about collisions with normal URLs.
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (request->upload_data_stream &&
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request->upload_data_stream->identifier()) {
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url.insert(0, base::StringPrintf(
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "%" PRId64 "/", request->upload_data_stream->identifier()));
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return url;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In playback and record mode, we cache everything.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lazily initialize.
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (playback_cache_map_ == NULL)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    playback_cache_map_.reset(new PlaybackCacheMap());
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each time we request an item from the cache, we tag it with a
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // generation number.  During playback, multiple fetches for the same
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // item will use the same generation number and pull the proper
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance of an URL from the cache.
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int generation = 0;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(playback_cache_map_ != NULL);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (playback_cache_map_->find(url) != playback_cache_map_->end())
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    generation = (*playback_cache_map_)[url];
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*playback_cache_map_)[url] = generation + 1;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The key into the cache is GENERATION # + METHOD + URL.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result = base::IntToString(generation);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.append(request->method);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.append(url);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DoomActiveEntry(const std::string& key) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::iterator it = active_entries_.find(key);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == active_entries_.end())
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is not a performance critical operation, this is handling an error
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // condition so it is OK to look up the entry again.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoomEntry(key, NULL);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(OK, rv);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::DoomEntry(const std::string& key, Transaction* trans) {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Need to abandon the ActiveEntry, but any transaction attached to the entry
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should not be impacted.  Dooming an entry only means that it will no
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // longer be returned by FindActiveEntry (and it will also be destroyed once
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all consumers are finished with the entry).
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::iterator it = active_entries_.find(key);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == active_entries_.end()) {
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(trans);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AsyncDoomEntry(key, trans);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry* entry = it->second;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_entries_.erase(it);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We keep track of doomed entries so that we can ensure that they are
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cleaned up properly when the cache is destroyed.
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  doomed_entries_.insert(entry);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->disk_entry->Doom();
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->doomed = true;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->writer || !entry->readers.empty());
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::AsyncDoomEntry(const std::string& key, Transaction* trans) {
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* item = new WorkItem(WI_DOOM_ENTRY, trans, NULL);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp* pending_op = GetPendingOp(key);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer) {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->pending_queue.push_back(item);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->writer = item;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
631010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                    GetWeakPtr(), pending_op);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = disk_cache_->DoomEntry(key, pending_op->callback);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->ClearTransaction();
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->callback.Run(rv);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpCache::DoomMainEntryForUrl(const GURL& url) {
643d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!disk_cache_)
644d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
645d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpRequestInfo temp_info;
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  temp_info.url = url;
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  temp_info.method = "GET";
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string key = GenerateCacheKey(&temp_info);
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Defer to DoomEntry if there is an active entry, otherwise call
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // AsyncDoomEntry without triggering a callback.
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (active_entries_.count(key))
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DoomEntry(key, NULL);
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AsyncDoomEntry(key, NULL);
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::FinalizeDoomedEntry(ActiveEntry* entry) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->doomed);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->writer);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->readers.empty());
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->pending_queue.empty());
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesSet::iterator it = doomed_entries_.find(entry);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != doomed_entries_.end());
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  doomed_entries_.erase(it);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete entry;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::ActiveEntry* HttpCache::FindActiveEntry(const std::string& key) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::const_iterator it = active_entries_.find(key);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it != active_entries_.end() ? it->second : NULL;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::ActiveEntry* HttpCache::ActivateEntry(
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    disk_cache::Entry* disk_entry) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!FindActiveEntry(disk_entry->GetKey()));
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry* entry = new ActiveEntry(disk_entry);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_entries_[disk_entry->GetKey()] = entry;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entry;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DeactivateEntry(ActiveEntry* entry) {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->will_process_pending_queue);
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->doomed);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->writer);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->disk_entry);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->readers.empty());
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->pending_queue.empty());
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key = entry->disk_entry->GetKey();
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key.empty())
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SlowDeactivateEntry(entry);
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::iterator it = active_entries_.find(key);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != active_entries_.end());
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it->second == entry);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_entries_.erase(it);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete entry;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We don't know this entry's key so we have to find it without it.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::SlowDeactivateEntry(ActiveEntry* entry) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ActiveEntriesMap::iterator it = active_entries_.begin();
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != active_entries_.end(); ++it) {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->second == entry) {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_entries_.erase(it);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete entry;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::PendingOp* HttpCache::GetPendingOp(const std::string& key) {
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!FindActiveEntry(key));
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOpsMap::const_iterator it = pending_ops_.find(key);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != pending_ops_.end())
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp* operation = new PendingOp();
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_ops_[key] = operation;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return operation;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DeletePendingOp(PendingOp* pending_op) {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->disk_entry)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key = pending_op->disk_entry->GetKey();
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!key.empty()) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOpsMap::iterator it = pending_ops_.find(key);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(it != pending_ops_.end());
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_ops_.erase(it);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (PendingOpsMap::iterator it = pending_ops_.begin();
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != pending_ops_.end(); ++it) {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (it->second == pending_op) {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_ops_.erase(it);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete pending_op;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::OpenEntry(const std::string& key, ActiveEntry** entry,
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         Transaction* trans) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry* active_entry = FindActiveEntry(key);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_entry) {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *entry = active_entry;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* item = new WorkItem(WI_OPEN_ENTRY, trans, entry);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp* pending_op = GetPendingOp(key);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->pending_queue.push_back(item);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->writer = item;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
771010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                    GetWeakPtr(), pending_op);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = disk_cache_->OpenEntry(key, &(pending_op->disk_entry),
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  pending_op->callback);
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->ClearTransaction();
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->callback.Run(rv);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::CreateEntry(const std::string& key, ActiveEntry** entry,
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Transaction* trans) {
785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (FindActiveEntry(key)) {
786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_CACHE_RACE;
787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* item = new WorkItem(WI_CREATE_ENTRY, trans, entry);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp* pending_op = GetPendingOp(key);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->pending_queue.push_back(item);
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->writer = item;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
800010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                    GetWeakPtr(), pending_op);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = disk_cache_->CreateEntry(key, &(pending_op->disk_entry),
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    pending_op->callback);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->ClearTransaction();
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->callback.Run(rv);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DestroyEntry(ActiveEntry* entry) {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->doomed) {
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FinalizeDoomedEntry(entry);
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeactivateEntry(entry);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::AddTransactionToEntry(ActiveEntry* entry, Transaction* trans) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->disk_entry);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We implement a basic reader/writer lock for the disk cache entry.  If
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there is already a writer, then everyone has to wait for the writer to
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // finish before they can access the cache entry.  There can be multiple
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // readers.
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: If the transaction can only write, then the entry should not be in
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use (since any existing entry should have already been doomed).
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->writer || entry->will_process_pending_queue) {
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->pending_queue.push_back(trans);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (trans->mode() & Transaction::WRITE) {
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // transaction needs exclusive access to the entry
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry->readers.empty()) {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry->writer = trans;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry->pending_queue.push_back(trans);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // transaction needs read access to the entry
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->readers.push_back(trans);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do this before calling EntryAvailable to force any further calls to
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AddTransactionToEntry to add their transaction to the pending queue, which
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ensures FIFO ordering.
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry->writer && !entry->pending_queue.empty())
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessPendingQueue(entry);
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DoneWithEntry(ActiveEntry* entry, Transaction* trans,
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool cancel) {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we already posted a task to move on to the next transaction and this was
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the writer, there is nothing to cancel.
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->will_process_pending_queue && entry->readers.empty())
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->writer) {
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(trans == entry->writer);
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Assume there was a failure.
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = false;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cancel) {
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(entry->disk_entry);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is a successful operation in the sense that we want to keep the
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // entry.
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      success = trans->AddTruncatedFlag();
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The previous operation may have deleted the entry.
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!trans->entry())
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(entry, success);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneReadingFromEntry(entry, trans);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DoneWritingToEntry(ActiveEntry* entry, bool success) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->readers.empty());
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->writer = NULL;
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success) {
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessPendingQueue(entry);
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!entry->will_process_pending_queue);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We failed to create this entry.
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionList pending_queue;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_queue.swap(entry->pending_queue);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->disk_entry->Doom();
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestroyEntry(entry);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to do something about these pending entries, which now need to
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be added to a new entry.
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!pending_queue.empty()) {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ERR_CACHE_RACE causes the transaction to restart the whole process.
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_queue.front()->io_callback().Run(ERR_CACHE_RACE);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_queue.pop_front();
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans) {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->writer);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionList::iterator it =
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(entry->readers.begin(), entry->readers.end(), trans);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != entry->readers.end());
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->readers.erase(it);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessPendingQueue(entry);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::ConvertWriterToReader(ActiveEntry* entry) {
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->writer);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->writer->mode() == Transaction::READ_WRITE);
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->readers.empty());
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Transaction* trans = entry->writer;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->writer = NULL;
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->readers.push_back(trans);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessPendingQueue(entry);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState HttpCache::GetLoadStateForPendingTransaction(
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Transaction* trans) {
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::const_iterator i = active_entries_.find(trans->key());
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == active_entries_.end()) {
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If this is really a pending transaction, and it is not part of
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // active_entries_, we should be creating the backend or the entry.
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_WAITING_FOR_CACHE;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Transaction* writer = i->second->writer;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return writer ? writer->GetWriterLoadState() : LOAD_STATE_WAITING_FOR_CACHE;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::RemovePendingTransaction(Transaction* trans) {
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::const_iterator i = active_entries_.find(trans->key());
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found = false;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != active_entries_.end())
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = RemovePendingTransactionFromEntry(i->second, trans);
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found)
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (building_backend_) {
961c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PendingOpsMap::const_iterator j = pending_ops_.find(std::string());
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (j != pending_ops_.end())
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found = RemovePendingTransactionFromPendingOp(j->second, trans);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found)
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOpsMap::const_iterator j = pending_ops_.find(trans->key());
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (j != pending_ops_.end())
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = RemovePendingTransactionFromPendingOp(j->second, trans);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesSet::iterator k = doomed_entries_.begin();
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; k != doomed_entries_.end() && !found; ++k)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = RemovePendingTransactionFromEntry(*k, trans);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(found) << "Pending transaction not found";
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::RemovePendingTransactionFromEntry(ActiveEntry* entry,
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  Transaction* trans) {
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionList& pending_queue = entry->pending_queue;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionList::iterator j =
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      find(pending_queue.begin(), pending_queue.end(), trans);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (j == pending_queue.end())
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_queue.erase(j);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      Transaction* trans) {
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer->Matches(trans)) {
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->writer->ClearTransaction();
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->writer->ClearEntry();
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemList& pending_queue = pending_op->pending_queue;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemList::iterator it = pending_queue.begin();
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; it != pending_queue.end(); ++it) {
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->Matches(trans)) {
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete *it;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_queue.erase(it);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void HttpCache::SetupQuicServerInfoFactory(HttpNetworkSession* session) {
10175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (session &&
101846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      !session->quic_stream_factory()->has_quic_server_info_factory()) {
101946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK(!quic_server_info_factory_);
102046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    quic_server_info_factory_.reset(new QuicServerInfoFactoryAdaptor(this));
102146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    session->quic_stream_factory()->set_quic_server_info_factory(
102246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        quic_server_info_factory_.get());
102346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
102446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
102546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::ProcessPendingQueue(ActiveEntry* entry) {
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Multiple readers may finish with an entry at once, so we want to batch up
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // calls to OnProcessPendingQueue.  This flag also tells us that we should
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not delete the entry before OnProcessPendingQueue runs.
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->will_process_pending_queue)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->will_process_pending_queue = true;
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1036010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&HttpCache::OnProcessPendingQueue, GetWeakPtr(), entry));
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) {
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->will_process_pending_queue = false;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->writer);
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If no one is interested in this entry, then we can deactivate it.
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->pending_queue.empty()) {
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry->readers.empty())
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DestroyEntry(entry);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Promote next transaction from the pending queue.
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Transaction* next = entry->pending_queue.front();
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((next->mode() & Transaction::WRITE) && !entry->readers.empty())
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Have to wait.
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->pending_queue.erase(entry->pending_queue.begin());
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = AddTransactionToEntry(entry, next);
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next->io_callback().Run(rv);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnIOComplete(int result, PendingOp* pending_op) {
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemOperation op = pending_op->writer->operation();
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Completing the creation of the backend is simpler than the other cases.
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (op == WI_CREATE_BACKEND)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnBackendCreated(result, pending_op);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WorkItem> item(pending_op->writer);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool fail_requests = false;
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry* entry = NULL;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (op == WI_DOOM_ENTRY) {
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Anything after a Doom has to be restarted.
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fail_requests = true;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (item->IsValid()) {
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key = pending_op->disk_entry->GetKey();
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry = ActivateEntry(pending_op->disk_entry);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The writer transaction is gone.
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (op == WI_CREATE_ENTRY)
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_op->disk_entry->Doom();
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_op->disk_entry->Close();
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_op->disk_entry = NULL;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fail_requests = true;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We are about to notify a bunch of transactions, and they may decide to
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // re-issue a request (or send a different one). If we don't delete
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_op, the new request will be appended to the end of the list, and
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we'll see it again from this point before it has a chance to complete (and
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we'll be messing out the request order). The down side is that if for some
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reason notifying request A ends up cancelling request B (for the same key),
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we won't find request B anywhere (because it would be in a local variable
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here) and that's bad. If there is a chance for that to happen, we'll have
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to move the callback used to be a CancelableCallback. By the way, for this
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to happen the action (to cancel B) has to be synchronous to the
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notification for request A.
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemList pending_items;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_items.swap(pending_op->pending_queue);
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeletePendingOp(pending_op);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item->NotifyTransaction(result, entry);
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!pending_items.empty()) {
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item.reset(pending_items.front());
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_items.pop_front();
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->operation() == WI_DOOM_ENTRY) {
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A queued doom request is always a race.
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fail_requests = true;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (result == OK) {
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry = FindActiveEntry(key);
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!entry)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fail_requests = true;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fail_requests) {
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item->NotifyTransaction(ERR_CACHE_RACE, NULL);
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->operation() == WI_CREATE_ENTRY) {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result == OK) {
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A second Create request, but the first request succeeded.
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item->NotifyTransaction(ERR_CACHE_CREATE_FAILURE, NULL);
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (op != WI_CREATE_ENTRY) {
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Failed Open followed by a Create.
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          item->NotifyTransaction(ERR_CACHE_RACE, NULL);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          fail_requests = true;
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          item->NotifyTransaction(result, entry);
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (op == WI_CREATE_ENTRY && result != OK) {
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Failed Create followed by an Open.
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item->NotifyTransaction(ERR_CACHE_RACE, NULL);
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fail_requests = true;
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item->NotifyTransaction(result, entry);
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnPendingOpComplete(const base::WeakPtr<HttpCache>& cache,
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    PendingOp* pending_op,
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int rv) {
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cache.get()) {
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache->OnIOComplete(rv, pending_op);
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The callback was cancelled so we should delete the pending_op that
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // was used with this callback.
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete pending_op;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) {
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WorkItem> item(pending_op->writer);
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemOperation op = item->operation();
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(WI_CREATE_BACKEND, op);
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need the callback anymore.
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback.Reset();
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (backend_factory_.get()) {
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We may end up calling OnBackendCreated multiple times if we have pending
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // work items. The first call saves the backend and releases the factory,
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and the last call clears building_backend_.
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_factory_.reset();  // Reclaim memory.
1178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (result == OK) {
1179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      disk_cache_ = pending_op->backend.Pass();
1180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (UseCertCache())
1181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        cert_cache_.reset(new DiskBasedCertCache(disk_cache_.get()));
1182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pending_op->pending_queue.empty()) {
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WorkItem* pending_item = pending_op->pending_queue.front();
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->pending_queue.pop_front();
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(WI_CREATE_BACKEND, pending_item->operation());
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We want to process a single callback at a time, because the cache may
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // go away from the callback.
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->writer = pending_item;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
119490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
1196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&HttpCache::OnBackendCreated, GetWeakPtr(),
1197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   result, pending_op));
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    building_backend_ = false;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeletePendingOp(pending_op);
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The cache may be gone when we return from the callback.
1204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!item->DoCallback(result, disk_cache_.get()))
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->NotifyTransaction(result, NULL);
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1209