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