1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/mem_entry_impl.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/stringprintf.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/mem_backend_impl.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/disk_cache/net_log_parameters.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time; 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kSparseData = 1; 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Maximum size of a sparse entry is 2 to the power of this number. 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kMaxSparseEntryBits = 12; 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Sparse entry has maximum size of 4KB. 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kMaxSparseEntrySize = 1 << kMaxSparseEntryBits; 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Convert global offset to child index. 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline int ToChildIndex(int64 offset) { 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return static_cast<int>(offset >> kMaxSparseEntryBits); 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Convert global offset to offset in child entry. 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline int ToChildOffset(int64 offset) { 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return static_cast<int>(offset & (kMaxSparseEntrySize - 1)); 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Returns a name for a child entry given the base_name of the parent and the 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// child_id. This name is only used for logging purposes. 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// If the entry is called entry_name, child entries will be named something 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// like Range_entry_name:YYY where YYY is the number of the particular child. 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::string GenerateChildName(const std::string& base_name, int child_id) { 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return base::StringPrintf("Range_%s:%i", base_name.c_str(), child_id); 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache { 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMemEntryImpl::MemEntryImpl(MemBackendImpl* backend) { 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott doomed_ = false; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_ = backend; 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ref_count_ = 0; 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parent_ = NULL; 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_id_ = 0; 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_first_pos_ = 0; 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_ = NULL; 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott prev_ = NULL; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < NUM_STREAMS; i++) 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_size_[i] = 0; 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// ------------------------------------------------------------------------ 6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool MemEntryImpl::CreateEntry(const std::string& key, net::NetLog* net_log) { 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_ = net::BoundNetLog::Make(net_log, 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::SOURCE_MEMORY_CACHE_ENTRY); 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent( 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL, 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new EntryCreationParameters(key, true))); 6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen key_ = key; 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Time current = Time::Now(); 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen last_modified_ = current; 7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen last_used_ = current; 7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Open(); 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen backend_->ModifyStorageSize(0, static_cast<int32>(key.size())); 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MemEntryImpl::InternalDoom() { 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.AddEvent(net::NetLog::TYPE_ENTRY_DOOM, NULL); 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen doomed_ = true; 8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!ref_count_) { 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (type() == kParentEntry) { 8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If this is a parent entry, we need to doom all the child entries. 8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (children_.get()) { 8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EntryMap children; 8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen children.swap(*children_); 8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (EntryMap::iterator i = children.begin(); 8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen i != children.end(); ++i) { 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Since a pointer to this object is also saved in the map, avoid 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // dooming it. 9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (i->second != this) 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen i->second->Doom(); 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(children_->empty()); 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If this is a child entry, detach it from the parent. 9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_->DetachChild(child_id_); 9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delete this; 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MemEntryImpl::Open() { 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Only a parent entry can be opened. 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(hclam): make sure it's correct to not apply the concept of ref 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // counting to child entry. 10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(type() == kParentEntry); 10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ref_count_++; 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(ref_count_ >= 0); 11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(!doomed_); 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool MemEntryImpl::InUse() { 11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (type() == kParentEntry) { 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return ref_count_ > 0; 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // A child entry is always not in use. The consequence is that a child entry 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // can always be evicted while the associated parent entry is currently in 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // used (i.e. opened). 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// ------------------------------------------------------------------------ 12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MemEntryImpl::Doom() { 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (doomed_) 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (type() == kParentEntry) { 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Perform internal doom from the backend if this is a parent entry. 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->InternalDoomEntry(this); 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Manually detach from the backend and perform internal doom. 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->RemoveFromRankingList(this); 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott InternalDoom(); 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MemEntryImpl::Close() { 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Only a parent entry can be closed. 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry); 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ref_count_--; 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(ref_count_ >= 0); 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ref_count_ && doomed_) 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott InternalDoom(); 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string MemEntryImpl::GetKey() const { 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // A child entry doesn't have key so this method should not be called. 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return key_; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTime MemEntryImpl::GetLastUsed() const { 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return last_used_; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTime MemEntryImpl::GetLastModified() const { 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return last_modified_; 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint32 MemEntryImpl::GetDataSize(int index) const { 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (index < 0 || index >= NUM_STREAMS) 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return data_size_[index]; 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MemEntryImpl::ReadData(int index, int offset, net::IOBuffer* buf, 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int buf_len, net::CompletionCallback* completion_callback) { 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent( 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_READ_DATA, 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr( 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new ReadWriteDataParameters(index, offset, buf_len, false))); 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = InternalReadData(index, offset, buf, buf_len); 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent( 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_READ_DATA, 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new ReadWriteCompleteParameters(result))); 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int buf_len, net::CompletionCallback* completion_callback, bool truncate) { 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent( 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_WRITE_DATA, 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr( 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new ReadWriteDataParameters(index, offset, buf_len, truncate))); 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = InternalWriteData(index, offset, buf, buf_len, truncate); 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent( 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_WRITE_DATA, 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new ReadWriteCompleteParameters(result))); 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::CompletionCallback* completion_callback) { 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent( 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_READ, 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr( 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new SparseOperationParameters(offset, buf_len))); 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = InternalReadSparseData(offset, buf, buf_len); 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent(net::NetLog::TYPE_SPARSE_READ, NULL); 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::CompletionCallback* completion_callback) { 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent(net::NetLog::TYPE_SPARSE_WRITE, 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr( 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new SparseOperationParameters(offset, buf_len))); 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = InternalWriteSparseData(offset, buf, buf_len); 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent(net::NetLog::TYPE_SPARSE_WRITE, NULL); 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start, 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CompletionCallback* callback) { 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent( 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_GET_RANGE, 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr( 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new SparseOperationParameters(offset, len))); 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int result = GetAvailableRange(offset, len, start); 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent( 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_GET_RANGE, 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr( 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new GetAvailableRangeResultParameters(*start, result))); 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool MemEntryImpl::CouldBeSparse() const { 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(kParentEntry, type()); 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return (children_.get() != NULL); 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::ReadyForSparseIO( 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::CompletionCallback* completion_callback) { 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return net::OK; 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// ------------------------------------------------------------------------ 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenMemEntryImpl::~MemEntryImpl() { 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < NUM_STREAMS; i++) 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen backend_->ModifyStorageSize(data_size_[i], 0); 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen backend_->ModifyStorageSize(static_cast<int32>(key_.size()), 0); 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent(net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL, NULL); 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::InternalReadData(int index, int offset, net::IOBuffer* buf, 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int buf_len) { 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry || index == kSparseData); 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (index < 0 || index >= NUM_STREAMS) 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_INVALID_ARGUMENT; 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int entry_size = GetDataSize(index); 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset >= entry_size || offset < 0 || !buf_len) 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (buf_len < 0) 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_INVALID_ARGUMENT; 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset + buf_len > entry_size) 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf_len = entry_size - offset; 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateRank(false); 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen memcpy(buf->data(), &(data_[index])[offset], buf_len); 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return buf_len; 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::InternalWriteData(int index, int offset, net::IOBuffer* buf, 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int buf_len, bool truncate) { 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry || index == kSparseData); 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (index < 0 || index >= NUM_STREAMS) 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_INVALID_ARGUMENT; 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset < 0 || buf_len < 0) 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_INVALID_ARGUMENT; 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int max_file_size = backend_->MaxFileSize(); 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // offset of buf_len could be negative numbers. 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset > max_file_size || buf_len > max_file_size || 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset + buf_len > max_file_size) { 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_FAILED; 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Read the size at this point. 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int entry_size = GetDataSize(index); 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PrepareTarget(index, offset, buf_len); 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (entry_size < offset + buf_len) { 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->ModifyStorageSize(entry_size, offset + buf_len); 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_size_[index] = offset + buf_len; 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (truncate) { 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (entry_size > offset + buf_len) { 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->ModifyStorageSize(entry_size, offset + buf_len); 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_size_[index] = offset + buf_len; 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateRank(true); 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!buf_len) 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(&(data_[index])[offset], buf->data(), buf_len); 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return buf_len; 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::InternalReadSparseData(int64 offset, net::IOBuffer* buf, 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int buf_len) { 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry); 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!InitSparseInfo()) 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset < 0 || buf_len < 0) 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_INVALID_ARGUMENT; 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We will keep using this buffer and adjust the offset in this buffer. 347513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::DrainableIOBuffer> io_buf( 348513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new net::DrainableIOBuffer(buf, buf_len)); 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Iterate until we have read enough. 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (io_buf->BytesRemaining()) { 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), false); 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // No child present for that offset. 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!child) 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We then need to prepare the child offset and len. 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int child_offset = ToChildOffset(offset + io_buf->BytesConsumed()); 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we are trying to read from a position that the child entry has no data 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we should stop. 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (child_offset < child->child_first_pos_) 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent( 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_READ_CHILD_DATA, 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new SparseReadWriteParameters( 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child->net_log().source(), 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen io_buf->BytesRemaining()))); 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int ret = child->ReadData(kSparseData, child_offset, io_buf, 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_buf->BytesRemaining(), NULL); 374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEventWithNetErrorCode( 376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_READ_CHILD_DATA, ret); 377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we encounter an error in one entry, return immediately. 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ret < 0) 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ret; 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (ret == 0) 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Increment the counter by number of bytes read in the child entry. 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_buf->DidConsume(ret); 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateRank(false); 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return io_buf->BytesConsumed(); 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MemEntryImpl::InternalWriteSparseData(int64 offset, net::IOBuffer* buf, 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int buf_len) { 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry); 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!InitSparseInfo()) 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset < 0 || buf_len < 0) 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_INVALID_ARGUMENT; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 404513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<net::DrainableIOBuffer> io_buf( 405513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new net::DrainableIOBuffer(buf, buf_len)); 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This loop walks through child entries continuously starting from |offset| 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // and writes blocks of data (of maximum size kMaxSparseEntrySize) into each 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // child entry until all |buf_len| bytes are written. The write operation can 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // start in the middle of an entry. 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (io_buf->BytesRemaining()) { 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), true); 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int child_offset = ToChildOffset(offset + io_buf->BytesConsumed()); 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Find the right amount to write, this evaluates the remaining bytes to 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // write and remaining capacity of this child entry. 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int write_len = std::min(static_cast<int>(io_buf->BytesRemaining()), 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kMaxSparseEntrySize - child_offset); 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Keep a record of the last byte position (exclusive) in the child. 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int data_size = child->GetDataSize(kSparseData); 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 424ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent( 425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA, 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new SparseReadWriteParameters( 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child->net_log().source(), 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen write_len))); 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Always writes to the child entry. This operation may overwrite data 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // previously written. 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(hclam): if there is data in the entry and this write is not 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // continuous we may want to discard this write. 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int ret = child->WriteData(kSparseData, child_offset, io_buf, write_len, 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, true); 437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (net_log_.IsLoggingAllEvents()) { 438ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEventWithNetErrorCode( 439ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA, ret); 440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ret < 0) 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ret; 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else if (ret == 0) 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Keep a record of the first byte position in the child if the write was 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // not aligned nor continuous. This is to enable witting to the middle 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // of an entry and still keep track of data off the aligned edge. 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (data_size != child_offset) 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child->child_first_pos_ = child_offset; 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Adjust the offset in the IO buffer. 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_buf->DidConsume(ret); 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateRank(true); 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return io_buf->BytesConsumed(); 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start) { 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry); 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(start); 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!InitSparseInfo()) 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset < 0 || len < 0 || !start) 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::ERR_INVALID_ARGUMENT; 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemEntryImpl* current_child = NULL; 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Find the first child and record the number of empty bytes. 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int empty = FindNextChild(offset, len, ¤t_child); 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (current_child) { 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *start = offset + empty; 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott len -= empty; 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Counts the number of continuous bytes. 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int continuous = 0; 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This loop scan for continuous bytes. 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (len && current_child) { 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Number of bytes available in this child. 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int data_size = current_child->GetDataSize(kSparseData) - 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ToChildOffset(*start + continuous); 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (data_size > len) 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_size = len; 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We have found more continuous bytes so increment the count. Also 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // decrement the length we should scan. 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continuous += data_size; 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott len -= data_size; 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the next child is discontinuous, break the loop. 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (FindNextChild(*start + continuous, len, ¤t_child)) 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return continuous; 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *start = offset; 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MemEntryImpl::PrepareTarget(int index, int offset, int buf_len) { 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int entry_size = GetDataSize(index); 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (entry_size >= offset + buf_len) 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; // Not growing the stored data. 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (static_cast<int>(data_[index].size()) < offset + buf_len) 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_[index].resize(offset + buf_len); 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset <= entry_size) 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; // There is no "hole" on the stored data. 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Cleanup the hole not written by the user. The point is to avoid returning 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // random stuff later on. 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(&(data_[index])[entry_size], 0, offset - entry_size); 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MemEntryImpl::UpdateRank(bool modified) { 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time current = Time::Now(); 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott last_used_ = current; 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (modified) 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott last_modified_ = current; 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!doomed_) 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->UpdateRank(this); 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MemEntryImpl::InitSparseInfo() { 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry); 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!children_.get()) { 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we already have some data in sparse stream but we are being 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // initialized as a sparse entry, we should fail. 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (GetDataSize(kSparseData)) 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_.reset(new EntryMap()); 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The parent entry stores data for the first block, so save this object to 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // index 0. 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*children_)[0] = this; 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool MemEntryImpl::InitChildEntry(MemEntryImpl* parent, int child_id, 551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog* net_log) { 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!parent_); 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!child_id_); 554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_ = net::BoundNetLog::Make(net_log, 556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::SOURCE_MEMORY_CACHE_ENTRY); 557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.BeginEvent( 558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL, 559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new EntryCreationParameters( 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GenerateChildName(parent->key(), child_id_), 561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen true))); 562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parent_ = parent; 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott child_id_ = child_id; 5653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Time current = Time::Now(); 5663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick last_modified_ = current; 5673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick last_used_ = current; 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Insert this to the backend's ranking list. 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->InsertIntoRankingList(this); 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMemEntryImpl* MemEntryImpl::OpenChild(int64 offset, bool create) { 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(type() == kParentEntry); 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int index = ToChildIndex(offset); 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EntryMap::iterator i = children_->find(index); 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i != children_->end()) { 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return i->second; 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (create) { 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemEntryImpl* child = new MemEntryImpl(backend_); 581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child->InitChildEntry(this, index, net_log_.net_log()); 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (*children_)[index] = child; 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return child; 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MemEntryImpl::FindNextChild(int64 offset, int len, MemEntryImpl** child) { 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(child); 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *child = NULL; 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int scanned_len = 0; 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This loop tries to find the first existing child. 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (scanned_len < len) { 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This points to the current offset in the child. 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int current_child_offset = ToChildOffset(offset + scanned_len); 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MemEntryImpl* current_child = OpenChild(offset + scanned_len, false); 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (current_child) { 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int child_first_pos = current_child->child_first_pos_; 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This points to the first byte that we should be reading from, we need 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to take care of the filled region and the current offset in the child. 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int first_pos = std::max(current_child_offset, child_first_pos); 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the first byte position we should read from doesn't exceed the 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // filled region, we have found the first child. 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (first_pos < current_child->GetDataSize(kSparseData)) { 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *child = current_child; 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We need to advance the scanned length. 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scanned_len += first_pos - current_child_offset; 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scanned_len += kMaxSparseEntrySize - current_child_offset; 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return scanned_len; 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MemEntryImpl::DetachChild(int child_id) { 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott children_->erase(child_id); 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace disk_cache 625