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