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