15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/memory/mem_entry_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/memory/mem_backend_impl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/disk_cache/net_log_parameters.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSparseData = 1;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum size of a sparse entry is 2 to the power of this number.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxSparseEntryBits = 12;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sparse entry has maximum size of 4KB.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxSparseEntrySize = 1 << kMaxSparseEntryBits;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert global offset to child index.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int ToChildIndex(int64 offset) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(offset >> kMaxSparseEntryBits);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convert global offset to offset in child entry.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int ToChildOffset(int64 offset) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<int>(offset & (kMaxSparseEntrySize - 1));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a name for a child entry given the base_name of the parent and the
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// child_id.  This name is only used for logging purposes.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the entry is called entry_name, child entries will be named something
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// like Range_entry_name:YYY where YYY is the number of the particular child.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateChildName(const std::string& base_name, int child_id) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPrintf("Range_%s:%i", base_name.c_str(), child_id);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns NetLog parameters for the creation of a child MemEntryImpl.  Separate
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function needed because child entries don't suppport GetKey().
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)base::Value* NetLogChildEntryCreationCallback(
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const disk_cache::MemEntryImpl* parent,
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int child_id,
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    net::NetLog::LogLevel /* log_level */) {
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString("key", GenerateChildName(parent->GetKey(), child_id));
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetBoolean("created", true);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MemEntryImpl::MemEntryImpl(MemBackendImpl* backend) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  doomed_ = false;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_ = backend;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_count_ = 0;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parent_ = NULL;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  child_id_ = 0;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  child_first_pos_ = 0;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_ = NULL;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prev_ = NULL;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < NUM_STREAMS; i++)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_size_[i] = 0;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ------------------------------------------------------------------------
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MemEntryImpl::CreateEntry(const std::string& key, net::NetLog* net_log) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_ = key;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time current = Time::Now();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_modified_ = current;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_used_ = current;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_ = net::BoundNetLog::Make(net_log,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must be called after |key_| is set, so GetKey() works.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateNetLogEntryCreationCallback(this, true));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Open();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->ModifyStorageSize(0, static_cast<int32>(key.size()));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MemEntryImpl::InternalDoom() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(net::NetLog::TYPE_ENTRY_DOOM);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  doomed_ = true;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ref_count_) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type() == kParentEntry) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If this is a parent entry, we need to doom all the child entries.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (children_.get()) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EntryMap children;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        children.swap(*children_);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (EntryMap::iterator i = children.begin();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             i != children.end(); ++i) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Since a pointer to this object is also saved in the map, avoid
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // dooming it.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (i->second != this)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            i->second->Doom();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(children_->empty());
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If this is a child entry, detach it from the parent.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parent_->DetachChild(child_id_);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MemEntryImpl::Open() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only a parent entry can be opened.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): make sure it's correct to not apply the concept of ref
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // counting to child entry.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_count_++;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(ref_count_, 0);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!doomed_);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MemEntryImpl::InUse() {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type() == kParentEntry) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ref_count_ > 0;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A child entry is always not in use. The consequence is that a child entry
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // can always be evicted while the associated parent entry is currently in
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // used (i.e. opened).
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ------------------------------------------------------------------------
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MemEntryImpl::Doom() {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (doomed_)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type() == kParentEntry) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Perform internal doom from the backend if this is a parent entry.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_->InternalDoomEntry(this);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Manually detach from the backend and perform internal doom.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_->RemoveFromRankingList(this);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InternalDoom();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MemEntryImpl::Close() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only a parent entry can be closed.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ref_count_--;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(ref_count_, 0);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ref_count_ && doomed_)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InternalDoom();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string MemEntryImpl::GetKey() const {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A child entry doesn't have key so this method should not be called.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return key_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Time MemEntryImpl::GetLastUsed() const {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return last_used_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Time MemEntryImpl::GetLastModified() const {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return last_modified_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32 MemEntryImpl::GetDataSize(int index) const {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index < 0 || index >= NUM_STREAMS)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_size_[index];
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::ReadData(int index, int offset, IOBuffer* buf, int buf_len,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const CompletionCallback& callback) {
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging()) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.BeginEvent(
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_ENTRY_READ_DATA,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogReadWriteDataCallback(index, offset, buf_len, false));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = InternalReadData(index, offset, buf, buf_len);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging()) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEvent(
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_ENTRY_READ_DATA,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogReadWriteCompleteCallback(result));
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::WriteData(int index, int offset, IOBuffer* buf, int buf_len,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const CompletionCallback& callback, bool truncate) {
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging()) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.BeginEvent(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_ENTRY_WRITE_DATA,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogReadWriteDataCallback(index, offset, buf_len, truncate));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = InternalWriteData(index, offset, buf, buf_len, truncate);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging()) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEvent(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_ENTRY_WRITE_DATA,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogReadWriteCompleteCallback(result));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::ReadSparseData(int64 offset, IOBuffer* buf, int buf_len,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const CompletionCallback& callback) {
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging()) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.BeginEvent(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_SPARSE_READ,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogSparseOperationCallback(offset, buf_len));
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = InternalReadSparseData(offset, buf, buf_len);
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging())
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEvent(net::NetLog::TYPE_SPARSE_READ);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::WriteSparseData(int64 offset, IOBuffer* buf, int buf_len,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const CompletionCallback& callback) {
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging()) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.BeginEvent(
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_SPARSE_WRITE,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogSparseOperationCallback(offset, buf_len));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = InternalWriteSparseData(offset, buf, buf_len);
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging())
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEvent(net::NetLog::TYPE_SPARSE_WRITE);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const CompletionCallback& callback) {
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging()) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.BeginEvent(
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_SPARSE_GET_RANGE,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogSparseOperationCallback(offset, len));
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = GetAvailableRange(offset, len, start);
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (net_log_.IsLogging()) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEvent(
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_SPARSE_GET_RANGE,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogGetAvailableRangeResultCallback(*start, result));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MemEntryImpl::CouldBeSparse() const {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kParentEntry, type());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (children_.get() != NULL);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net::OK;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ------------------------------------------------------------------------
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MemEntryImpl::~MemEntryImpl() {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < NUM_STREAMS; i++)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_->ModifyStorageSize(data_size_[i], 0);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->ModifyStorageSize(static_cast<int32>(key_.size()), 0);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEvent(net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::InternalReadData(int index, int offset, IOBuffer* buf,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int buf_len) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry || index == kSparseData);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index < 0 || index >= NUM_STREAMS)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int entry_size = GetDataSize(index);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset >= entry_size || offset < 0 || !buf_len)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buf_len < 0)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset + buf_len > entry_size)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf_len = entry_size - offset;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateRank(false);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buf->data(), &(data_[index])[offset], buf_len);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return buf_len;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::InternalWriteData(int index, int offset, IOBuffer* buf,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int buf_len, bool truncate) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry || index == kSparseData);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index < 0 || index >= NUM_STREAMS)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset < 0 || buf_len < 0)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int max_file_size = backend_->MaxFileSize();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // offset of buf_len could be negative numbers.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset > max_file_size || buf_len > max_file_size ||
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      offset + buf_len > max_file_size) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_FAILED;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the size at this point.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int entry_size = GetDataSize(index);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrepareTarget(index, offset, buf_len);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_size < offset + buf_len) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_->ModifyStorageSize(entry_size, offset + buf_len);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_size_[index] = offset + buf_len;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (truncate) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry_size > offset + buf_len) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_->ModifyStorageSize(entry_size, offset + buf_len);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_size_[index] = offset + buf_len;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateRank(true);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buf_len)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&(data_[index])[offset], buf->data(), buf_len);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return buf_len;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::InternalReadSparseData(int64 offset, IOBuffer* buf,
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int buf_len) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InitSparseInfo())
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset < 0 || buf_len < 0)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We will keep using this buffer and adjust the offset in this buffer.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::DrainableIOBuffer> io_buf(
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new net::DrainableIOBuffer(buf, buf_len));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Iterate until we have read enough.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (io_buf->BytesRemaining()) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), false);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No child present for that offset.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!child)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We then need to prepare the child offset and len.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int child_offset = ToChildOffset(offset + io_buf->BytesConsumed());
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we are trying to read from a position that the child entry has no data
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we should stop.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child_offset < child->child_first_pos_)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (net_log_.IsLogging()) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.BeginEvent(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_SPARSE_READ_CHILD_DATA,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogSparseReadWriteCallback(child->net_log().source(),
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              io_buf->BytesRemaining()));
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int ret = child->ReadData(kSparseData, child_offset, io_buf.get(),
3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                              io_buf->BytesRemaining(), CompletionCallback());
384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (net_log_.IsLogging()) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.EndEventWithNetErrorCode(
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_SPARSE_READ_CHILD_DATA, ret);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we encounter an error in one entry, return immediately.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret < 0)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ret;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (ret == 0)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Increment the counter by number of bytes read in the child entry.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_buf->DidConsume(ret);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateRank(false);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return io_buf->BytesConsumed();
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::InternalWriteSparseData(int64 offset, IOBuffer* buf,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int buf_len) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InitSparseInfo())
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset < 0 || buf_len < 0)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::DrainableIOBuffer> io_buf(
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new net::DrainableIOBuffer(buf, buf_len));
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This loop walks through child entries continuously starting from |offset|
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and writes blocks of data (of maximum size kMaxSparseEntrySize) into each
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // child entry until all |buf_len| bytes are written. The write operation can
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // start in the middle of an entry.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (io_buf->BytesRemaining()) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), true);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int child_offset = ToChildOffset(offset + io_buf->BytesConsumed());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find the right amount to write, this evaluates the remaining bytes to
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // write and remaining capacity of this child entry.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int write_len = std::min(static_cast<int>(io_buf->BytesRemaining()),
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kMaxSparseEntrySize - child_offset);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Keep a record of the last byte position (exclusive) in the child.
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int data_size = child->GetDataSize(kSparseData);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (net_log_.IsLogging()) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.BeginEvent(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogSparseReadWriteCallback(child->net_log().source(),
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              write_len));
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Always writes to the child entry. This operation may overwrite data
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // previously written.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(hclam): if there is data in the entry and this write is not
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // continuous we may want to discard this write.
4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    int ret = child->WriteData(kSparseData, child_offset, io_buf.get(),
4457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                               write_len, CompletionCallback(), true);
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (net_log_.IsLogging()) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.EndEventWithNetErrorCode(
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA, ret);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret < 0)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ret;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (ret == 0)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Keep a record of the first byte position in the child if the write was
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // not aligned nor continuous. This is to enable witting to the middle
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of an entry and still keep track of data off the aligned edge.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data_size != child_offset)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      child->child_first_pos_ = child_offset;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Adjust the offset in the IO buffer.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_buf->DidConsume(ret);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateRank(true);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return io_buf->BytesConsumed();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(start);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InitSparseInfo())
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset < 0 || len < 0 || !start)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_INVALID_ARGUMENT;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemEntryImpl* current_child = NULL;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the first child and record the number of empty bytes.
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int empty = FindNextChild(offset, len, &current_child);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_child) {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *start = offset + empty;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len -= empty;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Counts the number of continuous bytes.
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int continuous = 0;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This loop scan for continuous bytes.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (len && current_child) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Number of bytes available in this child.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int data_size = current_child->GetDataSize(kSparseData) -
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ToChildOffset(*start + continuous);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (data_size > len)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data_size = len;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We have found more continuous bytes so increment the count. Also
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // decrement the length we should scan.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continuous += data_size;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      len -= data_size;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the next child is discontinuous, break the loop.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (FindNextChild(*start + continuous, len, &current_child))
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return continuous;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *start = offset;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MemEntryImpl::PrepareTarget(int index, int offset, int buf_len) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int entry_size = GetDataSize(index);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (entry_size >= offset + buf_len)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Not growing the stored data.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (static_cast<int>(data_[index].size()) < offset + buf_len)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_[index].resize(offset + buf_len);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (offset <= entry_size)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // There is no "hole" on the stored data.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cleanup the hole not written by the user. The point is to avoid returning
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // random stuff later on.
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&(data_[index])[entry_size], 0, offset - entry_size);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MemEntryImpl::UpdateRank(bool modified) {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time current = Time::Now();
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_used_ = current;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (modified)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_modified_ = current;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!doomed_)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backend_->UpdateRank(this);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MemEntryImpl::InitSparseInfo() {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!children_.get()) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we already have some data in sparse stream but we are being
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // initialized as a sparse entry, we should fail.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetDataSize(kSparseData))
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    children_.reset(new EntryMap());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The parent entry stores data for the first block, so save this object to
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // index 0.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*children_)[0] = this;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MemEntryImpl::InitChildEntry(MemEntryImpl* parent, int child_id,
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  net::NetLog* net_log) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!parent_);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!child_id_);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_ = net::BoundNetLog::Make(net_log,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetLogChildEntryCreationCallback, parent, child_id_));
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parent_ = parent;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  child_id_ = child_id;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time current = Time::Now();
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_modified_ = current;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_used_ = current;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Insert this to the backend's ranking list.
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->InsertIntoRankingList(this);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MemEntryImpl* MemEntryImpl::OpenChild(int64 offset, bool create) {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type() == kParentEntry);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index = ToChildIndex(offset);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EntryMap::iterator i = children_->find(index);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != children_->end()) {
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return i->second;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (create) {
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MemEntryImpl* child = new MemEntryImpl(backend_);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    child->InitChildEntry(this, index, net_log_.net_log());
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*children_)[index] = child;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return child;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MemEntryImpl::FindNextChild(int64 offset, int len, MemEntryImpl** child) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(child);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *child = NULL;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int scanned_len = 0;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This loop tries to find the first existing child.
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (scanned_len < len) {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This points to the current offset in the child.
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int current_child_offset = ToChildOffset(offset + scanned_len);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MemEntryImpl* current_child = OpenChild(offset + scanned_len, false);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current_child) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int child_first_pos = current_child->child_first_pos_;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This points to the first byte that we should be reading from, we need
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to take care of the filled region and the current offset in the child.
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int first_pos =  std::max(current_child_offset, child_first_pos);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the first byte position we should read from doesn't exceed the
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // filled region, we have found the first child.
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (first_pos < current_child->GetDataSize(kSparseData)) {
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *child = current_child;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         // We need to advance the scanned length.
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         scanned_len += first_pos - current_child_offset;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         break;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scanned_len += kMaxSparseEntrySize - current_child_offset;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scanned_len;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MemEntryImpl::DetachChild(int child_id) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  children_->erase(child_id);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace disk_cache
632