| Index: net/disk_cache/memory/mem_entry_impl.cc
|
| diff --git a/net/disk_cache/memory/mem_entry_impl.cc b/net/disk_cache/memory/mem_entry_impl.cc
|
| deleted file mode 100644
|
| index 7c6199b951b28febf2c2d2cb3b1c595a67ab0324..0000000000000000000000000000000000000000
|
| --- a/net/disk_cache/memory/mem_entry_impl.cc
|
| +++ /dev/null
|
| @@ -1,631 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/disk_cache/memory/mem_entry_impl.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/logging.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/values.h"
|
| -#include "net/base/io_buffer.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/disk_cache/memory/mem_backend_impl.h"
|
| -#include "net/disk_cache/net_log_parameters.h"
|
| -
|
| -using base::Time;
|
| -
|
| -namespace {
|
| -
|
| -const int kSparseData = 1;
|
| -
|
| -// Maximum size of a sparse entry is 2 to the power of this number.
|
| -const int kMaxSparseEntryBits = 12;
|
| -
|
| -// Sparse entry has maximum size of 4KB.
|
| -const int kMaxSparseEntrySize = 1 << kMaxSparseEntryBits;
|
| -
|
| -// Convert global offset to child index.
|
| -inline int ToChildIndex(int64 offset) {
|
| - return static_cast<int>(offset >> kMaxSparseEntryBits);
|
| -}
|
| -
|
| -// Convert global offset to offset in child entry.
|
| -inline int ToChildOffset(int64 offset) {
|
| - return static_cast<int>(offset & (kMaxSparseEntrySize - 1));
|
| -}
|
| -
|
| -// Returns a name for a child entry given the base_name of the parent and the
|
| -// child_id. This name is only used for logging purposes.
|
| -// If the entry is called entry_name, child entries will be named something
|
| -// like Range_entry_name:YYY where YYY is the number of the particular child.
|
| -std::string GenerateChildName(const std::string& base_name, int child_id) {
|
| - return base::StringPrintf("Range_%s:%i", base_name.c_str(), child_id);
|
| -}
|
| -
|
| -// Returns NetLog parameters for the creation of a child MemEntryImpl. Separate
|
| -// function needed because child entries don't suppport GetKey().
|
| -base::Value* NetLogChildEntryCreationCallback(
|
| - const disk_cache::MemEntryImpl* parent,
|
| - int child_id,
|
| - net::NetLog::LogLevel /* log_level */) {
|
| - base::DictionaryValue* dict = new base::DictionaryValue();
|
| - dict->SetString("key", GenerateChildName(parent->GetKey(), child_id));
|
| - dict->SetBoolean("created", true);
|
| - return dict;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -namespace disk_cache {
|
| -
|
| -MemEntryImpl::MemEntryImpl(MemBackendImpl* backend) {
|
| - doomed_ = false;
|
| - backend_ = backend;
|
| - ref_count_ = 0;
|
| - parent_ = NULL;
|
| - child_id_ = 0;
|
| - child_first_pos_ = 0;
|
| - next_ = NULL;
|
| - prev_ = NULL;
|
| - for (int i = 0; i < NUM_STREAMS; i++)
|
| - data_size_[i] = 0;
|
| -}
|
| -
|
| -// ------------------------------------------------------------------------
|
| -
|
| -bool MemEntryImpl::CreateEntry(const std::string& key, net::NetLog* net_log) {
|
| - key_ = key;
|
| - Time current = Time::Now();
|
| - last_modified_ = current;
|
| - last_used_ = current;
|
| -
|
| - net_log_ = net::BoundNetLog::Make(net_log,
|
| - net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
|
| - // Must be called after |key_| is set, so GetKey() works.
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
|
| - CreateNetLogEntryCreationCallback(this, true));
|
| -
|
| - Open();
|
| - backend_->ModifyStorageSize(0, static_cast<int32>(key.size()));
|
| - return true;
|
| -}
|
| -
|
| -void MemEntryImpl::InternalDoom() {
|
| - net_log_.AddEvent(net::NetLog::TYPE_ENTRY_DOOM);
|
| - doomed_ = true;
|
| - if (!ref_count_) {
|
| - if (type() == kParentEntry) {
|
| - // If this is a parent entry, we need to doom all the child entries.
|
| - if (children_.get()) {
|
| - EntryMap children;
|
| - children.swap(*children_);
|
| - for (EntryMap::iterator i = children.begin();
|
| - i != children.end(); ++i) {
|
| - // Since a pointer to this object is also saved in the map, avoid
|
| - // dooming it.
|
| - if (i->second != this)
|
| - i->second->Doom();
|
| - }
|
| - DCHECK(children_->empty());
|
| - }
|
| - } else {
|
| - // If this is a child entry, detach it from the parent.
|
| - parent_->DetachChild(child_id_);
|
| - }
|
| - delete this;
|
| - }
|
| -}
|
| -
|
| -void MemEntryImpl::Open() {
|
| - // Only a parent entry can be opened.
|
| - // TODO(hclam): make sure it's correct to not apply the concept of ref
|
| - // counting to child entry.
|
| - DCHECK(type() == kParentEntry);
|
| - ref_count_++;
|
| - DCHECK_GE(ref_count_, 0);
|
| - DCHECK(!doomed_);
|
| -}
|
| -
|
| -bool MemEntryImpl::InUse() {
|
| - if (type() == kParentEntry) {
|
| - return ref_count_ > 0;
|
| - } else {
|
| - // A child entry is always not in use. The consequence is that a child entry
|
| - // can always be evicted while the associated parent entry is currently in
|
| - // used (i.e. opened).
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -// ------------------------------------------------------------------------
|
| -
|
| -void MemEntryImpl::Doom() {
|
| - if (doomed_)
|
| - return;
|
| - if (type() == kParentEntry) {
|
| - // Perform internal doom from the backend if this is a parent entry.
|
| - backend_->InternalDoomEntry(this);
|
| - } else {
|
| - // Manually detach from the backend and perform internal doom.
|
| - backend_->RemoveFromRankingList(this);
|
| - InternalDoom();
|
| - }
|
| -}
|
| -
|
| -void MemEntryImpl::Close() {
|
| - // Only a parent entry can be closed.
|
| - DCHECK(type() == kParentEntry);
|
| - ref_count_--;
|
| - DCHECK_GE(ref_count_, 0);
|
| - if (!ref_count_ && doomed_)
|
| - InternalDoom();
|
| -}
|
| -
|
| -std::string MemEntryImpl::GetKey() const {
|
| - // A child entry doesn't have key so this method should not be called.
|
| - DCHECK(type() == kParentEntry);
|
| - return key_;
|
| -}
|
| -
|
| -Time MemEntryImpl::GetLastUsed() const {
|
| - return last_used_;
|
| -}
|
| -
|
| -Time MemEntryImpl::GetLastModified() const {
|
| - return last_modified_;
|
| -}
|
| -
|
| -int32 MemEntryImpl::GetDataSize(int index) const {
|
| - if (index < 0 || index >= NUM_STREAMS)
|
| - return 0;
|
| - return data_size_[index];
|
| -}
|
| -
|
| -int MemEntryImpl::ReadData(int index, int offset, IOBuffer* buf, int buf_len,
|
| - const CompletionCallback& callback) {
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_ENTRY_READ_DATA,
|
| - CreateNetLogReadWriteDataCallback(index, offset, buf_len, false));
|
| - }
|
| -
|
| - int result = InternalReadData(index, offset, buf, buf_len);
|
| -
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.EndEvent(
|
| - net::NetLog::TYPE_ENTRY_READ_DATA,
|
| - CreateNetLogReadWriteCompleteCallback(result));
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -int MemEntryImpl::WriteData(int index, int offset, IOBuffer* buf, int buf_len,
|
| - const CompletionCallback& callback, bool truncate) {
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_ENTRY_WRITE_DATA,
|
| - CreateNetLogReadWriteDataCallback(index, offset, buf_len, truncate));
|
| - }
|
| -
|
| - int result = InternalWriteData(index, offset, buf, buf_len, truncate);
|
| -
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.EndEvent(
|
| - net::NetLog::TYPE_ENTRY_WRITE_DATA,
|
| - CreateNetLogReadWriteCompleteCallback(result));
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -int MemEntryImpl::ReadSparseData(int64 offset, IOBuffer* buf, int buf_len,
|
| - const CompletionCallback& callback) {
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_SPARSE_READ,
|
| - CreateNetLogSparseOperationCallback(offset, buf_len));
|
| - }
|
| - int result = InternalReadSparseData(offset, buf, buf_len);
|
| - if (net_log_.IsLogging())
|
| - net_log_.EndEvent(net::NetLog::TYPE_SPARSE_READ);
|
| - return result;
|
| -}
|
| -
|
| -int MemEntryImpl::WriteSparseData(int64 offset, IOBuffer* buf, int buf_len,
|
| - const CompletionCallback& callback) {
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_SPARSE_WRITE,
|
| - CreateNetLogSparseOperationCallback(offset, buf_len));
|
| - }
|
| - int result = InternalWriteSparseData(offset, buf, buf_len);
|
| - if (net_log_.IsLogging())
|
| - net_log_.EndEvent(net::NetLog::TYPE_SPARSE_WRITE);
|
| - return result;
|
| -}
|
| -
|
| -int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start,
|
| - const CompletionCallback& callback) {
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_SPARSE_GET_RANGE,
|
| - CreateNetLogSparseOperationCallback(offset, len));
|
| - }
|
| - int result = GetAvailableRange(offset, len, start);
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.EndEvent(
|
| - net::NetLog::TYPE_SPARSE_GET_RANGE,
|
| - CreateNetLogGetAvailableRangeResultCallback(*start, result));
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -bool MemEntryImpl::CouldBeSparse() const {
|
| - DCHECK_EQ(kParentEntry, type());
|
| - return (children_.get() != NULL);
|
| -}
|
| -
|
| -int MemEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
|
| - return net::OK;
|
| -}
|
| -
|
| -// ------------------------------------------------------------------------
|
| -
|
| -MemEntryImpl::~MemEntryImpl() {
|
| - for (int i = 0; i < NUM_STREAMS; i++)
|
| - backend_->ModifyStorageSize(data_size_[i], 0);
|
| - backend_->ModifyStorageSize(static_cast<int32>(key_.size()), 0);
|
| - net_log_.EndEvent(net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL);
|
| -}
|
| -
|
| -int MemEntryImpl::InternalReadData(int index, int offset, IOBuffer* buf,
|
| - int buf_len) {
|
| - DCHECK(type() == kParentEntry || index == kSparseData);
|
| -
|
| - if (index < 0 || index >= NUM_STREAMS)
|
| - return net::ERR_INVALID_ARGUMENT;
|
| -
|
| - int entry_size = GetDataSize(index);
|
| - if (offset >= entry_size || offset < 0 || !buf_len)
|
| - return 0;
|
| -
|
| - if (buf_len < 0)
|
| - return net::ERR_INVALID_ARGUMENT;
|
| -
|
| - if (offset + buf_len > entry_size)
|
| - buf_len = entry_size - offset;
|
| -
|
| - UpdateRank(false);
|
| -
|
| - memcpy(buf->data(), &(data_[index])[offset], buf_len);
|
| - return buf_len;
|
| -}
|
| -
|
| -int MemEntryImpl::InternalWriteData(int index, int offset, IOBuffer* buf,
|
| - int buf_len, bool truncate) {
|
| - DCHECK(type() == kParentEntry || index == kSparseData);
|
| -
|
| - if (index < 0 || index >= NUM_STREAMS)
|
| - return net::ERR_INVALID_ARGUMENT;
|
| -
|
| - if (offset < 0 || buf_len < 0)
|
| - return net::ERR_INVALID_ARGUMENT;
|
| -
|
| - int max_file_size = backend_->MaxFileSize();
|
| -
|
| - // offset of buf_len could be negative numbers.
|
| - if (offset > max_file_size || buf_len > max_file_size ||
|
| - offset + buf_len > max_file_size) {
|
| - return net::ERR_FAILED;
|
| - }
|
| -
|
| - // Read the size at this point.
|
| - int entry_size = GetDataSize(index);
|
| -
|
| - PrepareTarget(index, offset, buf_len);
|
| -
|
| - if (entry_size < offset + buf_len) {
|
| - backend_->ModifyStorageSize(entry_size, offset + buf_len);
|
| - data_size_[index] = offset + buf_len;
|
| - } else if (truncate) {
|
| - if (entry_size > offset + buf_len) {
|
| - backend_->ModifyStorageSize(entry_size, offset + buf_len);
|
| - data_size_[index] = offset + buf_len;
|
| - }
|
| - }
|
| -
|
| - UpdateRank(true);
|
| -
|
| - if (!buf_len)
|
| - return 0;
|
| -
|
| - memcpy(&(data_[index])[offset], buf->data(), buf_len);
|
| - return buf_len;
|
| -}
|
| -
|
| -int MemEntryImpl::InternalReadSparseData(int64 offset, IOBuffer* buf,
|
| - int buf_len) {
|
| - DCHECK(type() == kParentEntry);
|
| -
|
| - if (!InitSparseInfo())
|
| - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
|
| -
|
| - if (offset < 0 || buf_len < 0)
|
| - return net::ERR_INVALID_ARGUMENT;
|
| -
|
| - // We will keep using this buffer and adjust the offset in this buffer.
|
| - scoped_refptr<net::DrainableIOBuffer> io_buf(
|
| - new net::DrainableIOBuffer(buf, buf_len));
|
| -
|
| - // Iterate until we have read enough.
|
| - while (io_buf->BytesRemaining()) {
|
| - MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), false);
|
| -
|
| - // No child present for that offset.
|
| - if (!child)
|
| - break;
|
| -
|
| - // We then need to prepare the child offset and len.
|
| - int child_offset = ToChildOffset(offset + io_buf->BytesConsumed());
|
| -
|
| - // If we are trying to read from a position that the child entry has no data
|
| - // we should stop.
|
| - if (child_offset < child->child_first_pos_)
|
| - break;
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_SPARSE_READ_CHILD_DATA,
|
| - CreateNetLogSparseReadWriteCallback(child->net_log().source(),
|
| - io_buf->BytesRemaining()));
|
| - }
|
| - int ret = child->ReadData(kSparseData, child_offset, io_buf.get(),
|
| - io_buf->BytesRemaining(), CompletionCallback());
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.EndEventWithNetErrorCode(
|
| - net::NetLog::TYPE_SPARSE_READ_CHILD_DATA, ret);
|
| - }
|
| -
|
| - // If we encounter an error in one entry, return immediately.
|
| - if (ret < 0)
|
| - return ret;
|
| - else if (ret == 0)
|
| - break;
|
| -
|
| - // Increment the counter by number of bytes read in the child entry.
|
| - io_buf->DidConsume(ret);
|
| - }
|
| -
|
| - UpdateRank(false);
|
| -
|
| - return io_buf->BytesConsumed();
|
| -}
|
| -
|
| -int MemEntryImpl::InternalWriteSparseData(int64 offset, IOBuffer* buf,
|
| - int buf_len) {
|
| - DCHECK(type() == kParentEntry);
|
| -
|
| - if (!InitSparseInfo())
|
| - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
|
| -
|
| - if (offset < 0 || buf_len < 0)
|
| - return net::ERR_INVALID_ARGUMENT;
|
| -
|
| - scoped_refptr<net::DrainableIOBuffer> io_buf(
|
| - new net::DrainableIOBuffer(buf, buf_len));
|
| -
|
| - // This loop walks through child entries continuously starting from |offset|
|
| - // and writes blocks of data (of maximum size kMaxSparseEntrySize) into each
|
| - // child entry until all |buf_len| bytes are written. The write operation can
|
| - // start in the middle of an entry.
|
| - while (io_buf->BytesRemaining()) {
|
| - MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), true);
|
| - int child_offset = ToChildOffset(offset + io_buf->BytesConsumed());
|
| -
|
| - // Find the right amount to write, this evaluates the remaining bytes to
|
| - // write and remaining capacity of this child entry.
|
| - int write_len = std::min(static_cast<int>(io_buf->BytesRemaining()),
|
| - kMaxSparseEntrySize - child_offset);
|
| -
|
| - // Keep a record of the last byte position (exclusive) in the child.
|
| - int data_size = child->GetDataSize(kSparseData);
|
| -
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA,
|
| - CreateNetLogSparseReadWriteCallback(child->net_log().source(),
|
| - write_len));
|
| - }
|
| -
|
| - // Always writes to the child entry. This operation may overwrite data
|
| - // previously written.
|
| - // TODO(hclam): if there is data in the entry and this write is not
|
| - // continuous we may want to discard this write.
|
| - int ret = child->WriteData(kSparseData, child_offset, io_buf.get(),
|
| - write_len, CompletionCallback(), true);
|
| - if (net_log_.IsLogging()) {
|
| - net_log_.EndEventWithNetErrorCode(
|
| - net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA, ret);
|
| - }
|
| - if (ret < 0)
|
| - return ret;
|
| - else if (ret == 0)
|
| - break;
|
| -
|
| - // Keep a record of the first byte position in the child if the write was
|
| - // not aligned nor continuous. This is to enable witting to the middle
|
| - // of an entry and still keep track of data off the aligned edge.
|
| - if (data_size != child_offset)
|
| - child->child_first_pos_ = child_offset;
|
| -
|
| - // Adjust the offset in the IO buffer.
|
| - io_buf->DidConsume(ret);
|
| - }
|
| -
|
| - UpdateRank(true);
|
| -
|
| - return io_buf->BytesConsumed();
|
| -}
|
| -
|
| -int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start) {
|
| - DCHECK(type() == kParentEntry);
|
| - DCHECK(start);
|
| -
|
| - if (!InitSparseInfo())
|
| - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
|
| -
|
| - if (offset < 0 || len < 0 || !start)
|
| - return net::ERR_INVALID_ARGUMENT;
|
| -
|
| - MemEntryImpl* current_child = NULL;
|
| -
|
| - // Find the first child and record the number of empty bytes.
|
| - int empty = FindNextChild(offset, len, ¤t_child);
|
| - if (current_child) {
|
| - *start = offset + empty;
|
| - len -= empty;
|
| -
|
| - // Counts the number of continuous bytes.
|
| - int continuous = 0;
|
| -
|
| - // This loop scan for continuous bytes.
|
| - while (len && current_child) {
|
| - // Number of bytes available in this child.
|
| - int data_size = current_child->GetDataSize(kSparseData) -
|
| - ToChildOffset(*start + continuous);
|
| - if (data_size > len)
|
| - data_size = len;
|
| -
|
| - // We have found more continuous bytes so increment the count. Also
|
| - // decrement the length we should scan.
|
| - continuous += data_size;
|
| - len -= data_size;
|
| -
|
| - // If the next child is discontinuous, break the loop.
|
| - if (FindNextChild(*start + continuous, len, ¤t_child))
|
| - break;
|
| - }
|
| - return continuous;
|
| - }
|
| - *start = offset;
|
| - return 0;
|
| -}
|
| -
|
| -void MemEntryImpl::PrepareTarget(int index, int offset, int buf_len) {
|
| - int entry_size = GetDataSize(index);
|
| -
|
| - if (entry_size >= offset + buf_len)
|
| - return; // Not growing the stored data.
|
| -
|
| - if (static_cast<int>(data_[index].size()) < offset + buf_len)
|
| - data_[index].resize(offset + buf_len);
|
| -
|
| - if (offset <= entry_size)
|
| - return; // There is no "hole" on the stored data.
|
| -
|
| - // Cleanup the hole not written by the user. The point is to avoid returning
|
| - // random stuff later on.
|
| - memset(&(data_[index])[entry_size], 0, offset - entry_size);
|
| -}
|
| -
|
| -void MemEntryImpl::UpdateRank(bool modified) {
|
| - Time current = Time::Now();
|
| - last_used_ = current;
|
| -
|
| - if (modified)
|
| - last_modified_ = current;
|
| -
|
| - if (!doomed_)
|
| - backend_->UpdateRank(this);
|
| -}
|
| -
|
| -bool MemEntryImpl::InitSparseInfo() {
|
| - DCHECK(type() == kParentEntry);
|
| -
|
| - if (!children_.get()) {
|
| - // If we already have some data in sparse stream but we are being
|
| - // initialized as a sparse entry, we should fail.
|
| - if (GetDataSize(kSparseData))
|
| - return false;
|
| - children_.reset(new EntryMap());
|
| -
|
| - // The parent entry stores data for the first block, so save this object to
|
| - // index 0.
|
| - (*children_)[0] = this;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool MemEntryImpl::InitChildEntry(MemEntryImpl* parent, int child_id,
|
| - net::NetLog* net_log) {
|
| - DCHECK(!parent_);
|
| - DCHECK(!child_id_);
|
| -
|
| - net_log_ = net::BoundNetLog::Make(net_log,
|
| - net::NetLog::SOURCE_MEMORY_CACHE_ENTRY);
|
| - net_log_.BeginEvent(
|
| - net::NetLog::TYPE_DISK_CACHE_MEM_ENTRY_IMPL,
|
| - base::Bind(&NetLogChildEntryCreationCallback, parent, child_id_));
|
| -
|
| - parent_ = parent;
|
| - child_id_ = child_id;
|
| - Time current = Time::Now();
|
| - last_modified_ = current;
|
| - last_used_ = current;
|
| - // Insert this to the backend's ranking list.
|
| - backend_->InsertIntoRankingList(this);
|
| - return true;
|
| -}
|
| -
|
| -MemEntryImpl* MemEntryImpl::OpenChild(int64 offset, bool create) {
|
| - DCHECK(type() == kParentEntry);
|
| - int index = ToChildIndex(offset);
|
| - EntryMap::iterator i = children_->find(index);
|
| - if (i != children_->end()) {
|
| - return i->second;
|
| - } else if (create) {
|
| - MemEntryImpl* child = new MemEntryImpl(backend_);
|
| - child->InitChildEntry(this, index, net_log_.net_log());
|
| - (*children_)[index] = child;
|
| - return child;
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -int MemEntryImpl::FindNextChild(int64 offset, int len, MemEntryImpl** child) {
|
| - DCHECK(child);
|
| - *child = NULL;
|
| - int scanned_len = 0;
|
| -
|
| - // This loop tries to find the first existing child.
|
| - while (scanned_len < len) {
|
| - // This points to the current offset in the child.
|
| - int current_child_offset = ToChildOffset(offset + scanned_len);
|
| - MemEntryImpl* current_child = OpenChild(offset + scanned_len, false);
|
| - if (current_child) {
|
| - int child_first_pos = current_child->child_first_pos_;
|
| -
|
| - // This points to the first byte that we should be reading from, we need
|
| - // to take care of the filled region and the current offset in the child.
|
| - int first_pos = std::max(current_child_offset, child_first_pos);
|
| -
|
| - // If the first byte position we should read from doesn't exceed the
|
| - // filled region, we have found the first child.
|
| - if (first_pos < current_child->GetDataSize(kSparseData)) {
|
| - *child = current_child;
|
| -
|
| - // We need to advance the scanned length.
|
| - scanned_len += first_pos - current_child_offset;
|
| - break;
|
| - }
|
| - }
|
| - scanned_len += kMaxSparseEntrySize - current_child_offset;
|
| - }
|
| - return scanned_len;
|
| -}
|
| -
|
| -void MemEntryImpl::DetachChild(int child_id) {
|
| - children_->erase(child_id);
|
| -}
|
| -
|
| -} // namespace disk_cache
|
|
|