http_cache.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/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"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_number_conversions.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/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"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_cache_transaction.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_layer.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_info.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Adaptor to delete a file on a worker thread.
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeletePath(base::FilePath path) {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  file_util::Delete(path, false);
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::DefaultBackend::DefaultBackend(CacheType type,
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                          BackendType backend_type,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          const base::FilePath& path,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int max_bytes,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          base::MessageLoopProxy* thread)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : type_(type),
61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      backend_type_(backend_type),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path_(path),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_bytes_(max_bytes),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thread_(thread) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::DefaultBackend::~DefaultBackend() {}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::BackendFactory* HttpCache::DefaultBackend::InMemory(int max_bytes) {
71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return new DefaultBackend(MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT,
72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            base::FilePath(), max_bytes, NULL);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::DefaultBackend::CreateBackend(
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log, disk_cache::Backend** backend,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& callback) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(max_bytes_, 0);
79a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return disk_cache::CreateCacheBackend(type_, backend_type_, path_, max_bytes_,
80a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                        true, thread_, net_log, backend,
81a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                        callback);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::ActiveEntry::ActiveEntry(disk_cache::Entry* entry)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : disk_entry(entry),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      writer(NULL),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      will_process_pending_queue(false),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      doomed(false) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::ActiveEntry::~ActiveEntry() {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disk_entry) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    disk_entry->Close();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    disk_entry = NULL;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This structure keeps track of work items that are attempting to create or
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// open cache entries or the backend itself.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HttpCache::PendingOp {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp() : disk_entry(NULL), backend(NULL), writer(NULL) {}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PendingOp() {}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache::Entry* disk_entry;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache::Backend* backend;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* writer;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback callback;  // BackendCallback.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemList pending_queue;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The type of operation represented by a work item.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum WorkItemOperation {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WI_CREATE_BACKEND,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WI_OPEN_ENTRY,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WI_CREATE_ENTRY,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WI_DOOM_ENTRY
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A work item encapsulates a single request to the backend with all the
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// information needed to complete that request.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HttpCache::WorkItem {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem(WorkItemOperation operation, Transaction* trans, ActiveEntry** entry)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : operation_(operation),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        trans_(trans),
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entry_(entry),
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        backend_(NULL) {}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem(WorkItemOperation operation, Transaction* trans,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           const net::CompletionCallback& cb, disk_cache::Backend** backend)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : operation_(operation),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        trans_(trans),
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        entry_(NULL),
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_(cb),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        backend_(backend) {}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~WorkItem() {}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calls back the transaction with the result of the operation.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyTransaction(int result, ActiveEntry* entry) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!entry || entry->disk_entry);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry_)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *entry_ = entry;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (trans_)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      trans_->io_callback().Run(result);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the caller about the operation completion. Returns true if the
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback was invoked.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool DoCallback(int result, disk_cache::Backend* backend) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (backend_)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *backend_ = backend;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback_.is_null()) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_.Run(result);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemOperation operation() { return operation_; }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearTransaction() { trans_ = NULL; }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearEntry() { entry_ = NULL; }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearCallback() { callback_.Reset(); }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Matches(Transaction* trans) const { return trans == trans_; }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsValid() const { return trans_ || entry_ || !callback_.is_null(); }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemOperation operation_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Transaction* trans_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry** entry_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CompletionCallback callback_;  // User callback.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache::Backend** backend_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class encapsulates a transaction whose only purpose is to write metadata
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to a given entry.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HttpCache::MetadataWriter {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MetadataWriter(HttpCache::Transaction* trans)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : transaction_(trans),
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        verified_(false),
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buf_len_(0) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~MetadataWriter() {}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implements the bulk of HttpCache::WriteMetadata.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Write(const GURL& url, base::Time expected_response_time, IOBuffer* buf,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             int buf_len);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyResponse(int result);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SelfDestroy();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnIOComplete(int result);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpCache::Transaction> transaction_;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified_;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buf_;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int buf_len_;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time expected_response_time_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request_info_;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MetadataWriter);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::MetadataWriter::Write(const GURL& url,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      base::Time expected_response_time,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      IOBuffer* buf, int buf_len) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(buf_len, 0);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf->data());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info_.url = url;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info_.method = "GET";
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info_.load_flags = LOAD_ONLY_FROM_CACHE;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected_response_time_ = expected_response_time;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf_ = buf;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf_len_ = buf_len;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verified_ = false;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transaction_->Start(
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &request_info_,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MetadataWriter::OnIOComplete, base::Unretained(this)),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BoundNetLog());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyResponse(rv);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::MetadataWriter::VerifyResponse(int result) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verified_ = true;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SelfDestroy();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HttpResponseInfo* response_info = transaction_->GetResponseInfo();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(response_info->was_cached);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_info->response_time != expected_response_time_)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SelfDestroy();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = transaction_->WriteMetadata(
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buf_, buf_len_,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&MetadataWriter::OnIOComplete, base::Unretained(this)));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != ERR_IO_PENDING)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SelfDestroy();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::MetadataWriter::SelfDestroy() {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::MetadataWriter::OnIOComplete(int result) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!verified_)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return VerifyResponse(result);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelfDestroy();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::HttpCache(const net::HttpNetworkSession::Params& params,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     BackendFactory* backend_factory)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net_log_(params.net_log),
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_factory_(backend_factory),
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      building_backend_(false),
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_(NORMAL),
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_layer_(new HttpNetworkLayer(new HttpNetworkSession(params))) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::HttpCache(HttpNetworkSession* session,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     BackendFactory* backend_factory)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net_log_(session->net_log()),
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_factory_(backend_factory),
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      building_backend_(false),
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_(NORMAL),
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_layer_(new HttpNetworkLayer(session)) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::HttpCache(HttpTransactionFactory* network_layer,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     NetLog* net_log,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     BackendFactory* backend_factory)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : net_log_(net_log),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_factory_(backend_factory),
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      building_backend_(false),
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mode_(NORMAL),
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_layer_(network_layer) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::~HttpCache() {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have any active entries remaining, then we need to deactivate them.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may have some pending calls to OnProcessPendingQueue, but since those
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // won't run (due to our destruction), we can simply ignore the corresponding
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will_process_pending_queue flag.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!active_entries_.empty()) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ActiveEntry* entry = active_entries_.begin()->second;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->will_process_pending_queue = false;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->pending_queue.clear();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->readers.clear();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->writer = NULL;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeactivateEntry(entry);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&doomed_entries_);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Before deleting pending_ops_, we have to make sure that the disk cache is
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // done with said operations, or it will attempt to use deleted data.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache_.reset();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOpsMap::iterator pending_it = pending_ops_.begin();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; pending_it != pending_ops_.end(); ++pending_it) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We are not notifying the transactions about the cache going away, even
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // though they are waiting for a callback that will never fire.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOp* pending_op = pending_it->second;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete pending_op->writer;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool delete_pending_op = true;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (building_backend_) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we don't have a backend, when its construction finishes it will
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // deliver the callbacks.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!pending_op->callback.is_null()) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If not null, the callback will delete the pending operation later.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete_pending_op = false;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_op->callback.Reset();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLDeleteElements(&pending_op->pending_queue);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delete_pending_op)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete pending_op;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::GetBackend(disk_cache::Backend** backend,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const CompletionCallback& callback) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disk_cache_.get()) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *backend = disk_cache_.get();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateBackend(backend, callback);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)disk_cache::Backend* HttpCache::GetCurrentBackend() const {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return disk_cache_.get();
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::ParseResponseInfo(const char* data, int len,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  HttpResponseInfo* response_info,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool* response_truncated) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pickle pickle(data, len);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return response_info->InitFromPickle(pickle, response_truncated);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::WriteMetadata(const GURL& url,
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              RequestPriority priority,
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              base::Time expected_response_time,
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              IOBuffer* buf,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int buf_len) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buf_len)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do lazy initialization of disk cache if needed.
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!disk_cache_.get()) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't care about the result.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateBackend(NULL, net::CompletionCallback());
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpCache::Transaction* trans =
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new HttpCache::Transaction(priority, this, NULL);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MetadataWriter* writer = new MetadataWriter(trans);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The writer will self destruct when done.
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  writer->Write(url, expected_response_time, buf, buf_len);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::CloseAllConnections() {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpNetworkLayer* network =
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<net::HttpNetworkLayer*>(network_layer_.get());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkSession* session = network->GetSession();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (session)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session->CloseAllConnections();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::CloseIdleConnections() {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpNetworkLayer* network =
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<net::HttpNetworkLayer*>(network_layer_.get());
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpNetworkSession* session = network->GetSession();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (session)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session->CloseIdleConnections();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnExternalCacheHit(const GURL& url,
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const std::string& http_method) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!disk_cache_.get())
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpRequestInfo request_info;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info.url = url;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_info.method = http_method;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key = GenerateCacheKey(&request_info);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache_->OnExternalCacheHit(key);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpCache::InitializeInfiniteCache(const base::FilePath& path) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::FieldTrialList::FindFullName("InfiniteCache") != "Yes")
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WorkerPool::PostTask(FROM_HERE, base::Bind(&DeletePath, path), true);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int HttpCache::CreateTransaction(RequestPriority priority,
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<HttpTransaction>* trans,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 HttpTransactionDelegate* delegate) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do lazy initialization of disk cache if needed.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!disk_cache_.get()) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't care about the result.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateBackend(NULL, net::CompletionCallback());
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  trans->reset(new HttpCache::Transaction(priority, this, delegate));
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache* HttpCache::GetCache() {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpNetworkSession* HttpCache::GetSession() {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpNetworkLayer* network =
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<net::HttpNetworkLayer*>(network_layer_.get());
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network->GetSession();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::CreateBackend(disk_cache::Backend** backend,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const net::CompletionCallback& callback) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!backend_factory_.get())
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_FAILED;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  building_backend_ = true;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WorkItem> item(new WorkItem(WI_CREATE_BACKEND, NULL, callback,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         backend));
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the only operation that we can do that is not related to any given
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entry, so we use an empty key for it.
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PendingOp* pending_op = GetPendingOp(std::string());
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback.is_null())
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_op->pending_queue.push_back(item.release());
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->writer = item.release();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    AsWeakPtr(), pending_op);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = backend_factory_->CreateBackend(net_log_, &pending_op->backend,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           pending_op->callback);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->writer->ClearCallback();
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->callback.Run(rv);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::GetBackendForTransaction(Transaction* trans) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disk_cache_.get())
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!building_backend_)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_FAILED;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* item = new WorkItem(
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WI_CREATE_BACKEND, trans, net::CompletionCallback(), NULL);
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PendingOp* pending_op = GetPendingOp(std::string());
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->writer);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->pending_queue.push_back(item);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_IO_PENDING;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generate a key that can be used inside the cache.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string HttpCache::GenerateCacheKey(const HttpRequestInfo* request) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strip out the reference, username, and password sections of the URL.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url = HttpUtil::SpecForRequest(request->url);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode_ != DISABLE);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mode_ == NORMAL) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No valid URL can begin with numerals, so we should not have to worry
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // about collisions with normal URLs.
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (request->upload_data_stream &&
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request->upload_data_stream->identifier()) {
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url.insert(0, base::StringPrintf(
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "%" PRId64 "/", request->upload_data_stream->identifier()));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return url;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In playback and record mode, we cache everything.
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lazily initialize.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (playback_cache_map_ == NULL)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    playback_cache_map_.reset(new PlaybackCacheMap());
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each time we request an item from the cache, we tag it with a
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // generation number.  During playback, multiple fetches for the same
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // item will use the same generation number and pull the proper
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance of an URL from the cache.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int generation = 0;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(playback_cache_map_ != NULL);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (playback_cache_map_->find(url) != playback_cache_map_->end())
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    generation = (*playback_cache_map_)[url];
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*playback_cache_map_)[url] = generation + 1;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The key into the cache is GENERATION # + METHOD + URL.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result = base::IntToString(generation);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.append(request->method);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.append(url);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DoomActiveEntry(const std::string& key) {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::iterator it = active_entries_.find(key);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == active_entries_.end())
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is not a performance critical operation, this is handling an error
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // condition so it is OK to look up the entry again.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoomEntry(key, NULL);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(OK, rv);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::DoomEntry(const std::string& key, Transaction* trans) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Need to abandon the ActiveEntry, but any transaction attached to the entry
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should not be impacted.  Dooming an entry only means that it will no
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // longer be returned by FindActiveEntry (and it will also be destroyed once
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all consumers are finished with the entry).
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::iterator it = active_entries_.find(key);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it == active_entries_.end()) {
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(trans);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AsyncDoomEntry(key, trans);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry* entry = it->second;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_entries_.erase(it);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We keep track of doomed entries so that we can ensure that they are
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cleaned up properly when the cache is destroyed.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  doomed_entries_.insert(entry);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->disk_entry->Doom();
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->doomed = true;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->writer || !entry->readers.empty());
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::AsyncDoomEntry(const std::string& key, Transaction* trans) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* item = new WorkItem(WI_DOOM_ENTRY, trans, NULL);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp* pending_op = GetPendingOp(key);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->pending_queue.push_back(item);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->writer = item;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    AsWeakPtr(), pending_op);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = disk_cache_->DoomEntry(key, pending_op->callback);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->ClearTransaction();
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->callback.Run(rv);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpCache::DoomMainEntryForUrl(const GURL& url) {
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpRequestInfo temp_info;
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  temp_info.url = url;
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  temp_info.method = "GET";
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string key = GenerateCacheKey(&temp_info);
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Defer to DoomEntry if there is an active entry, otherwise call
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // AsyncDoomEntry without triggering a callback.
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (active_entries_.count(key))
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DoomEntry(key, NULL);
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AsyncDoomEntry(key, NULL);
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::FinalizeDoomedEntry(ActiveEntry* entry) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->doomed);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->writer);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->readers.empty());
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->pending_queue.empty());
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesSet::iterator it = doomed_entries_.find(entry);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != doomed_entries_.end());
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  doomed_entries_.erase(it);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete entry;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::ActiveEntry* HttpCache::FindActiveEntry(const std::string& key) {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::const_iterator it = active_entries_.find(key);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return it != active_entries_.end() ? it->second : NULL;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::ActiveEntry* HttpCache::ActivateEntry(
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    disk_cache::Entry* disk_entry) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!FindActiveEntry(disk_entry->GetKey()));
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry* entry = new ActiveEntry(disk_entry);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_entries_[disk_entry->GetKey()] = entry;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entry;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DeactivateEntry(ActiveEntry* entry) {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->will_process_pending_queue);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->doomed);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->writer);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->disk_entry);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->readers.empty());
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->pending_queue.empty());
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key = entry->disk_entry->GetKey();
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (key.empty())
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SlowDeactivateEntry(entry);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::iterator it = active_entries_.find(key);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != active_entries_.end());
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it->second == entry);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_entries_.erase(it);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete entry;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We don't know this entry's key so we have to find it without it.
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::SlowDeactivateEntry(ActiveEntry* entry) {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ActiveEntriesMap::iterator it = active_entries_.begin();
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != active_entries_.end(); ++it) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->second == entry) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_entries_.erase(it);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete entry;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpCache::PendingOp* HttpCache::GetPendingOp(const std::string& key) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!FindActiveEntry(key));
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOpsMap::const_iterator it = pending_ops_.find(key);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != pending_ops_.end())
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return it->second;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp* operation = new PendingOp();
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_ops_[key] = operation;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return operation;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DeletePendingOp(PendingOp* pending_op) {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->disk_entry)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key = pending_op->disk_entry->GetKey();
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!key.empty()) {
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingOpsMap::iterator it = pending_ops_.find(key);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(it != pending_ops_.end());
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_ops_.erase(it);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (PendingOpsMap::iterator it = pending_ops_.begin();
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != pending_ops_.end(); ++it) {
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (it->second == pending_op) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_ops_.erase(it);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete pending_op;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::OpenEntry(const std::string& key, ActiveEntry** entry,
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         Transaction* trans) {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry* active_entry = FindActiveEntry(key);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_entry) {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *entry = active_entry;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* item = new WorkItem(WI_OPEN_ENTRY, trans, entry);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp* pending_op = GetPendingOp(key);
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer) {
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->pending_queue.push_back(item);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->writer = item;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    AsWeakPtr(), pending_op);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = disk_cache_->OpenEntry(key, &(pending_op->disk_entry),
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  pending_op->callback);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->ClearTransaction();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->callback.Run(rv);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::CreateEntry(const std::string& key, ActiveEntry** entry,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Transaction* trans) {
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (FindActiveEntry(key)) {
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_CACHE_RACE;
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItem* item = new WorkItem(WI_CREATE_ENTRY, trans, entry);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOp* pending_op = GetPendingOp(key);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->pending_queue.push_back(item);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pending_op->pending_queue.empty());
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->writer = item;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback = base::Bind(&HttpCache::OnPendingOpComplete,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    AsWeakPtr(), pending_op);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = disk_cache_->CreateEntry(key, &(pending_op->disk_entry),
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    pending_op->callback);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->ClearTransaction();
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->callback.Run(rv);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DestroyEntry(ActiveEntry* entry) {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->doomed) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FinalizeDoomedEntry(entry);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeactivateEntry(entry);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpCache::AddTransactionToEntry(ActiveEntry* entry, Transaction* trans) {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry);
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->disk_entry);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We implement a basic reader/writer lock for the disk cache entry.  If
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there is already a writer, then everyone has to wait for the writer to
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // finish before they can access the cache entry.  There can be multiple
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // readers.
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: If the transaction can only write, then the entry should not be in
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use (since any existing entry should have already been doomed).
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->writer || entry->will_process_pending_queue) {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->pending_queue.push_back(trans);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (trans->mode() & Transaction::WRITE) {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // transaction needs exclusive access to the entry
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry->readers.empty()) {
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry->writer = trans;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry->pending_queue.push_back(trans);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // transaction needs read access to the entry
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->readers.push_back(trans);
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do this before calling EntryAvailable to force any further calls to
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AddTransactionToEntry to add their transaction to the pending queue, which
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ensures FIFO ordering.
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entry->writer && !entry->pending_queue.empty())
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessPendingQueue(entry);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DoneWithEntry(ActiveEntry* entry, Transaction* trans,
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool cancel) {
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we already posted a task to move on to the next transaction and this was
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the writer, there is nothing to cancel.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->will_process_pending_queue && entry->readers.empty())
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->writer) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(trans == entry->writer);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Assume there was a failure.
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = false;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cancel) {
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(entry->disk_entry);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is a successful operation in the sense that we want to keep the
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // entry.
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      success = trans->AddTruncatedFlag();
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The previous operation may have deleted the entry.
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!trans->entry())
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneWritingToEntry(entry, success);
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoneReadingFromEntry(entry, trans);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DoneWritingToEntry(ActiveEntry* entry, bool success) {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->readers.empty());
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->writer = NULL;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success) {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessPendingQueue(entry);
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!entry->will_process_pending_queue);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We failed to create this entry.
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransactionList pending_queue;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_queue.swap(entry->pending_queue);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry->disk_entry->Doom();
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DestroyEntry(entry);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to do something about these pending entries, which now need to
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // be added to a new entry.
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!pending_queue.empty()) {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ERR_CACHE_RACE causes the transaction to restart the whole process.
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_queue.front()->io_callback().Run(ERR_CACHE_RACE);
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_queue.pop_front();
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans) {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->writer);
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionList::iterator it =
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(entry->readers.begin(), entry->readers.end(), trans);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(it != entry->readers.end());
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->readers.erase(it);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessPendingQueue(entry);
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::ConvertWriterToReader(ActiveEntry* entry) {
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->writer);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->writer->mode() == Transaction::READ_WRITE);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(entry->readers.empty());
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Transaction* trans = entry->writer;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->writer = NULL;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->readers.push_back(trans);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessPendingQueue(entry);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState HttpCache::GetLoadStateForPendingTransaction(
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Transaction* trans) {
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::const_iterator i = active_entries_.find(trans->key());
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == active_entries_.end()) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If this is really a pending transaction, and it is not part of
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // active_entries_, we should be creating the backend or the entry.
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_WAITING_FOR_CACHE;
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Transaction* writer = i->second->writer;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return writer ? writer->GetWriterLoadState() : LOAD_STATE_WAITING_FOR_CACHE;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::RemovePendingTransaction(Transaction* trans) {
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesMap::const_iterator i = active_entries_.find(trans->key());
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found = false;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != active_entries_.end())
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = RemovePendingTransactionFromEntry(i->second, trans);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (building_backend_) {
906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PendingOpsMap::const_iterator j = pending_ops_.find(std::string());
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (j != pending_ops_.end())
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found = RemovePendingTransactionFromPendingOp(j->second, trans);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (found)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingOpsMap::const_iterator j = pending_ops_.find(trans->key());
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (j != pending_ops_.end())
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = RemovePendingTransactionFromPendingOp(j->second, trans);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntriesSet::iterator k = doomed_entries_.begin();
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; k != doomed_entries_.end() && !found; ++k)
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = RemovePendingTransactionFromEntry(*k, trans);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(found) << "Pending transaction not found";
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::RemovePendingTransactionFromEntry(ActiveEntry* entry,
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  Transaction* trans) {
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionList& pending_queue = entry->pending_queue;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransactionList::iterator j =
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      find(pending_queue.begin(), pending_queue.end(), trans);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (j == pending_queue.end())
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_queue.erase(j);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpCache::RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      Transaction* trans) {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_op->writer->Matches(trans)) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->writer->ClearTransaction();
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->writer->ClearEntry();
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemList& pending_queue = pending_op->pending_queue;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemList::iterator it = pending_queue.begin();
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; it != pending_queue.end(); ++it) {
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it)->Matches(trans)) {
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete *it;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_queue.erase(it);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::ProcessPendingQueue(ActiveEntry* entry) {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Multiple readers may finish with an entry at once, so we want to batch up
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // calls to OnProcessPendingQueue.  This flag also tells us that we should
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not delete the entry before OnProcessPendingQueue runs.
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->will_process_pending_queue)
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->will_process_pending_queue = true;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop::current()->PostTask(
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&HttpCache::OnProcessPendingQueue,
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 AsWeakPtr(),
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 entry));
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnProcessPendingQueue(ActiveEntry* entry) {
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->will_process_pending_queue = false;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!entry->writer);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If no one is interested in this entry, then we can deactivate it.
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry->pending_queue.empty()) {
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry->readers.empty())
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DestroyEntry(entry);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Promote next transaction from the pending queue.
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Transaction* next = entry->pending_queue.front();
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((next->mode() & Transaction::WRITE) && !entry->readers.empty())
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Have to wait.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry->pending_queue.erase(entry->pending_queue.begin());
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = AddTransactionToEntry(entry, next);
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next->io_callback().Run(rv);
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnIOComplete(int result, PendingOp* pending_op) {
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemOperation op = pending_op->writer->operation();
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Completing the creation of the backend is simpler than the other cases.
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (op == WI_CREATE_BACKEND)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OnBackendCreated(result, pending_op);
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WorkItem> item(pending_op->writer);
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool fail_requests = false;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ActiveEntry* entry = NULL;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string key;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (op == WI_DOOM_ENTRY) {
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Anything after a Doom has to be restarted.
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fail_requests = true;
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (item->IsValid()) {
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key = pending_op->disk_entry->GetKey();
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry = ActivateEntry(pending_op->disk_entry);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The writer transaction is gone.
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (op == WI_CREATE_ENTRY)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_op->disk_entry->Doom();
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_op->disk_entry->Close();
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_op->disk_entry = NULL;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fail_requests = true;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We are about to notify a bunch of transactions, and they may decide to
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // re-issue a request (or send a different one). If we don't delete
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pending_op, the new request will be appended to the end of the list, and
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we'll see it again from this point before it has a chance to complete (and
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we'll be messing out the request order). The down side is that if for some
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reason notifying request A ends up cancelling request B (for the same key),
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we won't find request B anywhere (because it would be in a local variable
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here) and that's bad. If there is a chance for that to happen, we'll have
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to move the callback used to be a CancelableCallback. By the way, for this
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to happen the action (to cancel B) has to be synchronous to the
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notification for request A.
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemList pending_items;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_items.swap(pending_op->pending_queue);
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeletePendingOp(pending_op);
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item->NotifyTransaction(result, entry);
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!pending_items.empty()) {
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item.reset(pending_items.front());
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_items.pop_front();
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->operation() == WI_DOOM_ENTRY) {
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A queued doom request is always a race.
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fail_requests = true;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (result == OK) {
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entry = FindActiveEntry(key);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!entry)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fail_requests = true;
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fail_requests) {
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      item->NotifyTransaction(ERR_CACHE_RACE, NULL);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (item->operation() == WI_CREATE_ENTRY) {
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result == OK) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A second Create request, but the first request succeeded.
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item->NotifyTransaction(ERR_CACHE_CREATE_FAILURE, NULL);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (op != WI_CREATE_ENTRY) {
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Failed Open followed by a Create.
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          item->NotifyTransaction(ERR_CACHE_RACE, NULL);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          fail_requests = true;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          item->NotifyTransaction(result, entry);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (op == WI_CREATE_ENTRY && result != OK) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Failed Create followed by an Open.
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item->NotifyTransaction(ERR_CACHE_RACE, NULL);
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fail_requests = true;
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        item->NotifyTransaction(result, entry);
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnPendingOpComplete(const base::WeakPtr<HttpCache>& cache,
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    PendingOp* pending_op,
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int rv) {
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cache.get()) {
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache->OnIOComplete(rv, pending_op);
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The callback was cancelled so we should delete the pending_op that
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // was used with this callback.
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete pending_op;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) {
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<WorkItem> item(pending_op->writer);
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WorkItemOperation op = item->operation();
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(WI_CREATE_BACKEND, op);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need the callback anymore.
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_op->callback.Reset();
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disk_cache::Backend* backend = pending_op->backend;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (backend_factory_.get()) {
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We may end up calling OnBackendCreated multiple times if we have pending
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // work items. The first call saves the backend and releases the factory,
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and the last call clears building_backend_.
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_factory_.reset();  // Reclaim memory.
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == OK)
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disk_cache_.reset(backend);
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pending_op->pending_queue.empty()) {
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WorkItem* pending_item = pending_op->pending_queue.front();
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->pending_queue.pop_front();
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(WI_CREATE_BACKEND, pending_item->operation());
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We want to process a single callback at a time, because the cache may
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // go away from the callback.
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_op->writer = pending_item;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoop::current()->PostTask(
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&HttpCache::OnBackendCreated, AsWeakPtr(),
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   result, pending_op));
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    building_backend_ = false;
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeletePendingOp(pending_op);
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The cache may be gone when we return from the callback.
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!item->DoCallback(result, backend))
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->NotifyTransaction(result, NULL);
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1144