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, ¤t_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, ¤t_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