1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2009-2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/sparse_control.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/format_macros.h" 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/backend_impl.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/entry_impl.h" 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/file.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/disk_cache/net_log_parameters.h" 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time; 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Stream of the sparse data index. 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kSparseIndex = 2; 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Stream of the sparse data. 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kSparseData = 1; 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We can have up to 64k children. 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kMaxMapSize = 8 * 1024; 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The maximum number of bytes that a child can store. 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kMaxEntrySize = 0x100000; 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The size of each data block (tracked by the child allocation bitmap). 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kBlockSize = 1024; 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Returns the name of a child entry given the base_name and signature of the 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// parent and the child_id. 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If the entry is called entry_name, child entries will be named something 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// like Range_entry_name:XXX:YYY where XXX is the entry signature and YYY is the 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// number of the particular child. 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string GenerateChildName(const std::string& base_name, int64 signature, 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 child_id) { 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return base::StringPrintf("Range_%s:%" PRIx64 ":%" PRIx64, base_name.c_str(), 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick signature, child_id); 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class deletes the children of a sparse entry. 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ChildrenDeleter 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : public base::RefCounted<ChildrenDeleter>, 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public disk_cache::FileIOCallback { 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ChildrenDeleter(disk_cache::BackendImpl* backend, const std::string& name) 5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : backend_(backend->GetWeakPtr()), name_(name), signature_(0) {} 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnFileIOComplete(int bytes_copied); 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Two ways of deleting the children: if we have the children map, use Start() 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // directly, otherwise pass the data address to ReadData(). 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Start(char* buffer, int len); 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void ReadData(disk_cache::Addr address, int len); 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott friend class base::RefCounted<ChildrenDeleter>; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~ChildrenDeleter() {} 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void DeleteChildren(); 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::WeakPtr<disk_cache::BackendImpl> backend_; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string name_; 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::Bitmap children_map_; 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 signature_; 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_array<char> buffer_; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ChildrenDeleter); 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This is the callback of the file operation. 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ChildrenDeleter::OnFileIOComplete(int bytes_copied) { 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* buffer = buffer_.release(); 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Start(buffer, bytes_copied); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ChildrenDeleter::Start(char* buffer, int len) { 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_.reset(buffer); 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (len < static_cast<int>(sizeof(disk_cache::SparseData))) 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Release(); 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Just copy the information from |buffer|, delete |buffer| and start deleting 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the child entries. 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::SparseData* data = 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<disk_cache::SparseData*>(buffer); 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott signature_ = data->header.signature; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int num_bits = (len - sizeof(disk_cache::SparseHeader)) * 8; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_map_.Resize(num_bits, false); 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_map_.SetMap(data->bitmap, num_bits / 32); 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_.reset(); 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DeleteChildren(); 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ChildrenDeleter::ReadData(disk_cache::Addr address, int len) { 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(address.is_block_file()); 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!backend_) 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return Release(); 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::File* file(backend_->File(address)); 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!file) 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Release(); 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t file_offset = address.start_block() * address.BlockSize() + 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::kBlockHeaderSize; 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_.reset(new char[len]); 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool completed; 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!file->Read(buffer_.get(), len, file_offset, this, &completed)) 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Release(); 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (completed) 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OnFileIOComplete(len); 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // And wait until OnFileIOComplete gets called. 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ChildrenDeleter::DeleteChildren() { 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int child_id = 0; 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!children_map_.FindNextSetBit(&child_id) || !backend_) { 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We are done. Just delete this object. 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Release(); 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string child_name = GenerateChildName(name_, signature_, child_id); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch backend_->SyncDoomEntry(child_name); 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_map_.Set(child_id, false); 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Post a task to delete the next child. 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott this, &ChildrenDeleter::DeleteChildren)); 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Returns the NetLog event type corresponding to a SparseOperation. 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennet::NetLog::EventType GetSparseEventType( 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen disk_cache::SparseControl::SparseOperation operation) { 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen switch (operation) { 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case disk_cache::SparseControl::kReadOperation: 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::NetLog::TYPE_SPARSE_READ; 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case disk_cache::SparseControl::kWriteOperation: 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::NetLog::TYPE_SPARSE_WRITE; 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case disk_cache::SparseControl::kGetRangeOperation: 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::NetLog::TYPE_SPARSE_GET_RANGE; 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen default: 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::NetLog::TYPE_CANCELLED; 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Logs the end event for |operation| on a child entry. Range operations log 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// no events for each child they search through. 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid LogChildOperationEnd(const net::BoundNetLog& net_log, 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen disk_cache::SparseControl::SparseOperation operation, 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result) { 1633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (net_log.IsLoggingAllEvents()) { 1643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net::NetLog::EventType event_type; 1653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen switch (operation) { 1663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case disk_cache::SparseControl::kReadOperation: 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event_type = net::NetLog::TYPE_SPARSE_READ_CHILD_DATA; 1683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen break; 1693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case disk_cache::SparseControl::kWriteOperation: 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen event_type = net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA; 1713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen break; 1723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case disk_cache::SparseControl::kGetRangeOperation: 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 1743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen default: 1753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen NOTREACHED(); 1763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return; 1773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 1783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net_log.EndEventWithNetErrorCode(event_type, result); 1793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 1803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 1813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace. 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache { 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 186731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSparseControl::SparseControl(EntryImpl* entry) 187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : entry_(entry), 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick child_(NULL), 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick operation_(kNoOperation), 190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick init_(false), 191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick child_map_(child_data_.bitmap, kNumSparseBits, kNumSparseBits / 32), 192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ALLOW_THIS_IN_INITIALIZER_LIST( 193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick child_callback_(this, &SparseControl::OnChildIOCompleted)), 194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick user_callback_(NULL) { 195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSparseControl::~SparseControl() { 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (child_) 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CloseChild(); 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (init_) 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WriteSparseData(); 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SparseControl::Init() { 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!init_); 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We should not have sparse data for the exposed entry. 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (entry_->GetDataSize(kSparseData)) 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Now see if there is something where we store our data. 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = net::OK; 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int data_len = entry_->GetDataSize(kSparseIndex); 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!data_len) { 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = CreateSparseEntry(); 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = OpenSparseEntry(data_len); 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == net::OK) 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott init_ = true; 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SparseControl::CouldBeSparse() const { 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!init_); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry_->GetDataSize(kSparseData)) 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't verify the data, just see if it could be there. 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (entry_->GetDataSize(kSparseIndex) != 0); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SparseControl::StartIO(SparseOperation op, int64 offset, net::IOBuffer* buf, 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int buf_len, net::CompletionCallback* callback) { 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(init_); 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We don't support simultaneous IO for sparse data. 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (operation_ != kNoOperation) 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset < 0 || buf_len < 0) 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_INVALID_ARGUMENT; 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We only support up to 64 GB. 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset + buf_len >= 0x1000000000LL || offset + buf_len < 0) 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_buf_); 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!buf && (op == kReadOperation || op == kWriteOperation)) 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Copy the operation parameters. 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott operation_ = op; 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset_ = offset; 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_buf_ = buf ? new net::DrainableIOBuffer(buf, buf_len) : NULL; 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf_len_ = buf_len; 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result_ = 0; 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_ = false; 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott finished_ = false; 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott abort_ = false; 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (entry_->net_log().IsLoggingAllEvents()) { 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry_->net_log().BeginEvent( 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetSparseEventType(operation_), 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new SparseOperationParameters(offset_, buf_len_))); 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoChildrenIO(); 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!pending_) { 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Everything was done synchronously. 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott operation_ = kNoOperation; 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_buf_ = NULL; 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = NULL; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result_; 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_IO_PENDING; 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SparseControl::GetAvailableRange(int64 offset, int len, int64* start) { 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(init_); 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We don't support simultaneous IO for sparse data. 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (operation_ != kNoOperation) 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(start); 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott range_found_ = false; 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = StartIO(kGetRangeOperation, offset, NULL, len, NULL); 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (range_found_) { 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *start = offset_; 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is a failure. We want to return a valid start value in any case. 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *start = offset; 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result < 0 ? result : 0; // Don't mask error codes to the caller. 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::CancelIO() { 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (operation_ == kNoOperation) 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott abort_ = true; 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SparseControl::ReadyToUse(net::CompletionCallback* completion_callback) { 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!abort_) 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::OK; 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We'll grab another reference to keep this object alive because we just have 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // one extra reference due to the pending IO operation itself, but we'll 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // release that one before invoking user_callback_. 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_->AddRef(); // Balanced in DoAbortCallbacks. 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott abort_callbacks_.push_back(completion_callback); 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_IO_PENDING; 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Static 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::DeleteChildren(EntryImpl* entry) { 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(entry->GetEntryFlags() & PARENT_ENTRY); 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int data_len = entry->GetDataSize(kSparseIndex); 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (data_len < static_cast<int>(sizeof(SparseData)) || 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry->GetDataSize(kSparseData)) 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int map_len = data_len - sizeof(SparseHeader); 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (map_len > kMaxMapSize || map_len % 4) 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* buffer; 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Addr address; 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry->GetData(kSparseIndex, &buffer, &address); 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!buffer && !address.is_initialized()) 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry->net_log().AddEvent(net::NetLog::TYPE_SPARSE_DELETE_CHILDREN, NULL); 342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ChildrenDeleter* deleter = new ChildrenDeleter(entry->backend_, 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry->GetKey()); 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The object will self destruct when finished. 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott deleter->AddRef(); 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (buffer) { 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott deleter, &ChildrenDeleter::Start, buffer, data_len)); 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott deleter, &ChildrenDeleter::ReadData, address, data_len)); 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We are going to start using this entry to store sparse data, so we have to 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// initialize our control info. 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SparseControl::CreateSparseEntry() { 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (CHILD_ENTRY & entry_->GetEntryFlags()) 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(&sparse_header_, 0, sizeof(sparse_header_)); 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sparse_header_.signature = Time::Now().ToInternalValue(); 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sparse_header_.magic = kIndexMagic; 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sparse_header_.parent_key_len = entry_->GetKey().size(); 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_map_.Resize(kNumSparseBits, true); 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Save the header. The bitmap is saved in the destructor. 370513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::IOBuffer> buf( 371513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_))); 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = entry_->WriteData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL, 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott false); 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != sizeof(sparse_header_)) { 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(ERROR) << "Unable to save sparse_header_"; 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_->SetEntryFlags(PARENT_ENTRY); 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::OK; 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We are opening an entry from disk. Make sure that our control data is there. 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SparseControl::OpenSparseEntry(int data_len) { 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (data_len < static_cast<int>(sizeof(SparseData))) 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (entry_->GetDataSize(kSparseData)) 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!(PARENT_ENTRY & entry_->GetEntryFlags())) 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Dont't go over board with the bitmap. 8 KB gives us offsets up to 64 GB. 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int map_len = data_len - sizeof(sparse_header_); 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (map_len > kMaxMapSize || map_len % 4) 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 400513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::IOBuffer> buf( 401513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_))); 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Read header. 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = entry_->ReadData(kSparseIndex, 0, buf, sizeof(sparse_header_), NULL); 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != static_cast<int>(sizeof(sparse_header_))) 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_READ_FAILURE; 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The real validation should be performed by the caller. This is just to 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // double check. 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (sparse_header_.magic != kIndexMagic || 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sparse_header_.parent_key_len != 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<int>(entry_->GetKey().size())) 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Read the actual bitmap. 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf = new net::IOBuffer(map_len); 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = entry_->ReadData(kSparseIndex, sizeof(sparse_header_), buf, map_len, 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL); 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != map_len) 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_READ_FAILURE; 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Grow the bitmap to the current size and copy the bits. 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_map_.Resize(map_len * 8, false); 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_map_.SetMap(reinterpret_cast<uint32*>(buf->data()), map_len); 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::OK; 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SparseControl::OpenChild() { 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(result_, 0); 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string key = GenerateChildKey(); 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (child_) { 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Keep using the same child or open another one?. 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (key == child_->GetKey()) 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CloseChild(); 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See if we are tracking this child. 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ChildPresent()) 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ContinueWithoutChild(key); 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_ = entry_->backend_->OpenEntryImpl(key); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!child_) 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ContinueWithoutChild(key); 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EntryImpl* child = static_cast<EntryImpl*>(child_); 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!(CHILD_ENTRY & child->GetEntryFlags()) || 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child->GetDataSize(kSparseIndex) < 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<int>(sizeof(child_data_))) 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return KillChildAndContinue(key, false); 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 453513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::WrappedIOBuffer> buf( 454513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_))); 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Read signature. 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = child_->ReadData(kSparseIndex, 0, buf, sizeof(child_data_), NULL); 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != sizeof(child_data_)) 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return KillChildAndContinue(key, true); // This is a fatal failure. 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (child_data_.header.signature != sparse_header_.signature || 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header.magic != kIndexMagic) 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return KillChildAndContinue(key, false); 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (child_data_.header.last_block_len < 0 || 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header.last_block_len > kBlockSize) { 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure these values are always within range. 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header.last_block_len = 0; 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header.last_block = -1; 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::CloseChild() { 476513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::WrappedIOBuffer> buf( 477513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_))); 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Save the allocation bitmap before closing the child entry. 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_), 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, false); 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != sizeof(child_data_)) 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(ERROR) << "Failed to save child data"; 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_->Release(); 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_ = NULL; 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string SparseControl::GenerateChildKey() { 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GenerateChildName(entry_->GetKey(), sparse_header_.signature, 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset_ >> 20); 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We are deleting the child because something went wrong. 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SparseControl::KillChildAndContinue(const std::string& key, bool fatal) { 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetChildBit(false); 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_->DoomImpl(); 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_->Release(); 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_ = NULL; 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fatal) { 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result_ = net::ERR_CACHE_READ_FAILURE; 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ContinueWithoutChild(key); 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We were not able to open this child; see what we can do. 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SparseControl::ContinueWithoutChild(const std::string& key) { 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (kReadOperation == operation_) 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (kGetRangeOperation == operation_) 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_ = entry_->backend_->CreateEntryImpl(key); 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!child_) { 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_ = NULL; 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result_ = net::ERR_CACHE_READ_FAILURE; 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Write signature. 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott InitChildData(); 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SparseControl::ChildPresent() { 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int child_bit = static_cast<int>(offset_ >> 20); 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (children_map_.Size() <= child_bit) 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return children_map_.Get(child_bit); 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::SetChildBit(bool value) { 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int child_bit = static_cast<int>(offset_ >> 20); 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We may have to increase the bitmap of child entries. 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (children_map_.Size() <= child_bit) 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_map_.Resize(Bitmap::RequiredArraySize(child_bit + 1) * 32, true); 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_map_.Set(child_bit, value); 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::WriteSparseData() { 543513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::IOBuffer> buf(new net::WrappedIOBuffer( 544513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch reinterpret_cast<const char*>(children_map_.GetMap()))); 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int len = children_map_.ArraySize() * 4; 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = entry_->WriteData(kSparseIndex, sizeof(sparse_header_), buf, len, 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, false); 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != len) { 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(ERROR) << "Unable to save sparse map"; 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SparseControl::VerifyRange() { 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(result_, 0); 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_offset_ = static_cast<int>(offset_) & (kMaxEntrySize - 1); 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_len_ = std::min(buf_len_, kMaxEntrySize - child_offset_); 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We can write to (or get info from) anywhere in this child. 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (operation_ != kReadOperation) 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check that there are no holes in this range. 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int last_bit = (child_offset_ + child_len_ + 1023) >> 10; 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int start = child_offset_ >> 10; 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (child_map_.FindNextBit(&start, last_bit, false)) { 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Something is not here. 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(child_data_.header.last_block_len, 0); 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize); 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int partial_block_len = PartialBlockLength(start); 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (start == child_offset_ >> 10) { 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // It looks like we don't have anything. 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (partial_block_len <= (child_offset_ & (kBlockSize - 1))) 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We have the first part. 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_len_ = (start << 10) - child_offset_; 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (partial_block_len) { 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We may have a few extra bytes. 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_len_ = std::min(child_len_ + partial_block_len, buf_len_); 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // There is no need to read more after this one. 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf_len_ = child_len_; 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::UpdateRange(int result) { 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result <= 0 || operation_ != kWriteOperation) 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(child_data_.header.last_block_len, 0); 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize); 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Write the bitmap. 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int first_bit = child_offset_ >> 10; 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int block_offset = child_offset_ & (kBlockSize - 1); 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (block_offset && (child_data_.header.last_block != first_bit || 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header.last_block_len < block_offset)) { 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The first block is not completely filled; ignore it. 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_bit++; 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int last_bit = (child_offset_ + result) >> 10; 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block_offset = (child_offset_ + result) & (kBlockSize - 1); 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This condition will hit with the following criteria: 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 1. The first byte doesn't follow the last write. 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 2. The first byte is in the middle of a block. 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 3. The first byte and the last byte are in the same block. 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (first_bit > last_bit) 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (block_offset && !child_map_.Get(last_bit)) { 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The last block is not completely filled; save it for later. 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header.last_block = last_bit; 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header.last_block_len = block_offset; 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header.last_block = -1; 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_map_.SetRange(first_bit, last_bit, true); 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SparseControl::PartialBlockLength(int block_index) const { 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (block_index == child_data_.header.last_block) 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return child_data_.header.last_block_len; 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This may be the last stored index. 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int entry_len = child_->GetDataSize(kSparseData); 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (block_index == entry_len >> 10) 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return entry_len & (kBlockSize - 1); 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is really empty. 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::InitChildData() { 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We know the real type of child_. 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EntryImpl* child = static_cast<EntryImpl*>(child_); 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child->SetEntryFlags(CHILD_ENTRY); 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(&child_data_, 0, sizeof(child_data_)); 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_data_.header = sparse_header_; 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 648513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::WrappedIOBuffer> buf( 649513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_))); 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_), 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, false); 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != sizeof(child_data_)) 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(ERROR) << "Failed to save child data"; 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetChildBit(true); 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::DoChildrenIO() { 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (DoChildIO()) continue; 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Range operations are finished synchronously, often without setting 662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // |finished_| to true. 663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (kGetRangeOperation == operation_ && 664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry_->net_log().IsLoggingAllEvents()) { 665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry_->net_log().EndEvent( 666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_GET_RANGE, 667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr( 668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new GetAvailableRangeResultParameters(offset_, result_))); 669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 6703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (finished_) { 671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (kGetRangeOperation != operation_ && 672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry_->net_log().IsLoggingAllEvents()) { 673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry_->net_log().EndEvent(GetSparseEventType(operation_), NULL); 674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 6753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (pending_) 6763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DoUserCallback(); 6773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SparseControl::DoChildIO() { 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott finished_ = true; 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!buf_len_ || result_ < 0) 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!OpenChild()) 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!VerifyRange()) 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We have more work to do. Let's not trigger a callback to the caller. 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott finished_ = false; 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::CompletionCallback* callback = user_callback_ ? &child_callback_ : NULL; 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = 0; 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (operation_) { 697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kReadOperation: 6983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (entry_->net_log().IsLoggingAllEvents()) { 6993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_->net_log().BeginEvent( 700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_READ_CHILD_DATA, 701ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new SparseReadWriteParameters( 702ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_->net_log().source(), 703ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_len_))); 7043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = child_->ReadDataImpl(kSparseData, child_offset_, user_buf_, 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_len_, callback); 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kWriteOperation: 7093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (entry_->net_log().IsLoggingAllEvents()) { 7103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_->net_log().BeginEvent( 711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA, 712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new SparseReadWriteParameters( 713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_->net_log().source(), 714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_len_))); 7153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = child_->WriteDataImpl(kSparseData, child_offset_, user_buf_, 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_len_, callback, false); 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kGetRangeOperation: 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoGetAvailableRange(); 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == net::ERR_IO_PENDING) { 727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!pending_) { 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_ = true; 729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The child will protect himself against closing the entry while IO is in 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // progress. However, this entry can still be closed, and that would not 731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // be a good thing for us, so we increase the refcount until we're 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // finished doing sparse stuff. 733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_->AddRef(); // Balanced in DoUserCallback. 734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!rv) 738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoChildIOCompleted(rv); 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SparseControl::DoGetAvailableRange() { 745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!child_) 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return child_len_; // Move on to the next child. 747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check that there are no holes in this range. 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int last_bit = (child_offset_ + child_len_ + 1023) >> 10; 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int start = child_offset_ >> 10; 751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int partial_start_bytes = PartialBlockLength(start); 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int found = start; 753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int bits_found = child_map_.FindBits(&found, last_bit, true); 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We don't care if there is a partial block in the middle of the range. 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int block_offset = child_offset_ & (kBlockSize - 1); 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!bits_found && partial_start_bytes <= block_offset) 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return child_len_; 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We are done. Just break the loop and reset result_ to our real result. 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott range_found_ = true; 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // found now points to the first 1. Lets see if we have zeros before it. 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int empty_start = std::max((found << 10) - child_offset_, 0); 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int bytes_found = bits_found << 10; 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_found += PartialBlockLength(found + bits_found); 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (start == found) 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_found -= block_offset; 771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the user is searching past the end of this child, bits_found is the 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // right result; otherwise, we have some empty space at the start of this 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // query that we have to subtract from the range that we searched. 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result_ = std::min(bytes_found, child_len_ - empty_start); 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!bits_found) { 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result_ = std::min(partial_start_bytes - block_offset, child_len_); 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott empty_start = 0; 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Only update offset_ when this query found zeros at the start. 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (empty_start) 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset_ += empty_start; 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This will actually break the loop. 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf_len_ = 0; 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::DoChildIOCompleted(int result) { 792ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LogChildOperationEnd(entry_->net_log(), operation_, result); 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) { 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We fail the whole operation if we encounter an error. 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result_ = result; 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateRange(result); 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result_ += result; 802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset_ += result; 803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf_len_ -= result; 804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We'll be reusing the user provided buffer for the next chunk. 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (buf_len_ && user_buf_) 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_buf_->DidConsume(result); 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::OnChildIOCompleted(int result) { 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(net::ERR_IO_PENDING, result); 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoChildIOCompleted(result); 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (abort_) { 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We'll return the current result of the operation, which may be less than 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the bytes to read or write, but the user cancelled the operation. 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott abort_ = false; 818ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (entry_->net_log().IsLoggingAllEvents()) { 819ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry_->net_log().AddEvent(net::NetLog::TYPE_CANCELLED, NULL); 820ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen entry_->net_log().EndEvent(GetSparseEventType(operation_), NULL); 821ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoUserCallback(); 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoAbortCallbacks(); 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We are running a callback from the message loop. It's time to restart what 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we were doing before. 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoChildrenIO(); 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::DoUserCallback() { 832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(user_callback_); 833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::CompletionCallback* c = user_callback_; 834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = NULL; 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_buf_ = NULL; 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pending_ = false; 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott operation_ = kNoOperation; 838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_->Release(); // Don't touch object after this line. 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(result_); 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SparseControl::DoAbortCallbacks() { 843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < abort_callbacks_.size(); i++) { 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Releasing all references to entry_ may result in the destruction of this 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // object so we should not be touching it after the last Release(). 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::CompletionCallback* c = abort_callbacks_[i]; 847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == abort_callbacks_.size() - 1) 848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott abort_callbacks_.clear(); 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_->Release(); // Don't touch object after this line. 851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(net::OK); 852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace disk_cache 856