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