Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Unified Diff: net/disk_cache/v3/sparse_control_v3.cc

Issue 17507006: Disk cache v3 ref2 Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Incl IndexTable cl Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/disk_cache/v3/sparse_control_v3.h ('k') | net/net.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/disk_cache/v3/sparse_control_v3.cc
===================================================================
--- net/disk_cache/v3/sparse_control_v3.cc (revision 232523)
+++ net/disk_cache/v3/sparse_control_v3.cc (working copy)
@@ -2,23 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/disk_cache/sparse_control.h"
+#include "net/disk_cache/v3/sparse_control_v3.h"
#include "base/bind.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
-#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
-#include "net/disk_cache/backend_impl.h"
-#include "net/disk_cache/entry_impl.h"
-#include "net/disk_cache/file.h"
#include "net/disk_cache/net_log_parameters.h"
+#include "net/disk_cache/v3/backend_impl_v3.h"
+#include "net/disk_cache/v3/entry_impl_v3.h"
using base::Time;
+using base::Bind;
namespace {
@@ -49,57 +48,49 @@
}
// This class deletes the children of a sparse entry.
-class ChildrenDeleter
- : public base::RefCounted<ChildrenDeleter>,
- public disk_cache::FileIOCallback {
+class ChildrenDeleter : public base::RefCountedThreadSafe<ChildrenDeleter> {
public:
- ChildrenDeleter(disk_cache::BackendImpl* backend, const std::string& name)
+ ChildrenDeleter(disk_cache::BackendImplV3* backend, const std::string& name)
: backend_(backend->GetWeakPtr()), name_(name), signature_(0) {}
- virtual void OnFileIOComplete(int bytes_copied) OVERRIDE;
-
// Two ways of deleting the children: if we have the children map, use Start()
// directly, otherwise pass the data address to ReadData().
- void Start(char* buffer, int len);
+ void Start(net::IOBuffer* buffer, int len);
void ReadData(disk_cache::Addr address, int len);
private:
- friend class base::RefCounted<ChildrenDeleter>;
+ friend class base::RefCountedThreadSafe<ChildrenDeleter>;
virtual ~ChildrenDeleter() {}
void DeleteChildren();
+ void OnReadComplete(int result);
+ void OnDoomComplete(int result);
- base::WeakPtr<disk_cache::BackendImpl> backend_;
+ base::WeakPtr<disk_cache::BackendImplV3> backend_;
std::string name_;
disk_cache::Bitmap children_map_;
int64 signature_;
- scoped_ptr<char[]> buffer_;
+ scoped_refptr<net::IOBuffer> buffer_;
DISALLOW_COPY_AND_ASSIGN(ChildrenDeleter);
};
-// This is the callback of the file operation.
-void ChildrenDeleter::OnFileIOComplete(int bytes_copied) {
- char* buffer = buffer_.release();
- Start(buffer, bytes_copied);
-}
-
-void ChildrenDeleter::Start(char* buffer, int len) {
- buffer_.reset(buffer);
+void ChildrenDeleter::Start(net::IOBuffer* buffer, int len) {
if (len < static_cast<int>(sizeof(disk_cache::SparseData)))
return Release();
// Just copy the information from |buffer|, delete |buffer| and start deleting
// the child entries.
disk_cache::SparseData* data =
- reinterpret_cast<disk_cache::SparseData*>(buffer);
+ reinterpret_cast<disk_cache::SparseData*>(buffer->data());
signature_ = data->header.signature;
int num_bits = (len - sizeof(disk_cache::SparseHeader)) * 8;
children_map_.Resize(num_bits, false);
children_map_.SetMap(data->bitmap, num_bits / 32);
- buffer_.reset();
- DeleteChildren();
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ Bind(&ChildrenDeleter::DeleteChildren,
+ this));
}
void ChildrenDeleter::ReadData(disk_cache::Addr address, int len) {
@@ -107,50 +98,44 @@
if (!backend_)
return Release();
- disk_cache::File* file(backend_->File(address));
- if (!file)
- return Release();
-
- size_t file_offset = address.start_block() * address.BlockSize() +
- disk_cache::kBlockHeaderSize;
-
- buffer_.reset(new char[len]);
- bool completed;
- if (!file->Read(buffer_.get(), len, file_offset, this, &completed))
- return Release();
-
- if (completed)
- OnFileIOComplete(len);
-
- // And wait until OnFileIOComplete gets called.
+ buffer_ = new net::IOBuffer(len);
+ backend_->ReadData(NULL, address, 0, buffer_, len,
+ Bind(&ChildrenDeleter::OnReadComplete, this));
}
void ChildrenDeleter::DeleteChildren() {
int child_id = 0;
- if (!children_map_.FindNextSetBit(&child_id) || !backend_) {
- // We are done. Just delete this object.
- return Release();
+ for (int rv = net::OK; rv != net::ERR_IO_PENDING;) {
+ if (!children_map_.FindNextSetBit(&child_id) || !backend_) {
+ // We are done. Just delete this object.
+ return Release();
+ }
+ std::string child_name = GenerateChildName(name_, signature_, child_id);
+ rv = backend_->DoomEntry(child_name,
+ Bind(&ChildrenDeleter::OnDoomComplete, this));
+ children_map_.Set(child_id, false);
}
- std::string child_name = GenerateChildName(name_, signature_, child_id);
- backend_->SyncDoomEntry(child_name);
- children_map_.Set(child_id, false);
+}
- // Post a task to delete the next child.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&ChildrenDeleter::DeleteChildren, this));
+void ChildrenDeleter::OnReadComplete(int result) {
+ Start(buffer_, result);
}
+void ChildrenDeleter::OnDoomComplete(int result) {
+ DeleteChildren();
+}
+
// -----------------------------------------------------------------------
// Returns the NetLog event type corresponding to a SparseOperation.
net::NetLog::EventType GetSparseEventType(
- disk_cache::SparseControl::SparseOperation operation) {
+ disk_cache::SparseControlV3::SparseOperation operation) {
switch (operation) {
- case disk_cache::SparseControl::kReadOperation:
+ case disk_cache::SparseControlV3::kReadOperation:
return net::NetLog::TYPE_SPARSE_READ;
- case disk_cache::SparseControl::kWriteOperation:
+ case disk_cache::SparseControlV3::kWriteOperation:
return net::NetLog::TYPE_SPARSE_WRITE;
- case disk_cache::SparseControl::kGetRangeOperation:
+ case disk_cache::SparseControlV3::kGetRangeOperation:
return net::NetLog::TYPE_SPARSE_GET_RANGE;
default:
NOTREACHED();
@@ -158,63 +143,57 @@
}
}
-// Logs the end event for |operation| on a child entry. Range operations log
-// no events for each child they search through.
-void LogChildOperationEnd(const net::BoundNetLog& net_log,
- disk_cache::SparseControl::SparseOperation operation,
- int result) {
- if (net_log.IsLoggingAllEvents()) {
- net::NetLog::EventType event_type;
- switch (operation) {
- case disk_cache::SparseControl::kReadOperation:
- event_type = net::NetLog::TYPE_SPARSE_READ_CHILD_DATA;
- break;
- case disk_cache::SparseControl::kWriteOperation:
- event_type = net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA;
- break;
- case disk_cache::SparseControl::kGetRangeOperation:
- return;
- default:
- NOTREACHED();
- return;
- }
- net_log.EndEventWithNetErrorCode(event_type, result);
- }
-}
-
} // namespace.
namespace disk_cache {
-SparseControl::SparseControl(EntryImpl* entry)
+SparseControlV3::SparseControlV3(EntryImplV3* entry)
: entry_(entry),
child_(NULL),
operation_(kNoOperation),
- pending_(false),
- finished_(false),
+ next_state_(STATE_NONE),
init_(false),
range_found_(false),
abort_(false),
+ valid_(false),
+ closing_(false),
child_map_(child_data_.bitmap, kNumSparseBits, kNumSparseBits / 32),
+ callback_(base::Bind(&SparseControlV3::OnIOComplete,
+ base::Unretained(this))),
offset_(0),
buf_len_(0),
child_offset_(0),
child_len_(0),
- result_(0) {
+ result_(0),
+ range_start_(NULL) {
memset(&sparse_header_, 0, sizeof(sparse_header_));
memset(&child_data_, 0, sizeof(child_data_));
}
-SparseControl::~SparseControl() {
- if (child_)
- CloseChild();
- if (init_)
- WriteSparseData();
+SparseControlV3::~SparseControlV3() {
}
-bool SparseControl::CouldBeSparse() const {
- DCHECK(!init_);
+void SparseControlV3::Close() {
+ if (closing_)
+ return;
+ if (operation_ != kNoOperation || valid_) {
+ closing_ = true;
+ entry_->AddRef();
+ if (operation_ != kNoOperation)
+ return;
+ DCHECK_EQ(next_state_, STATE_NONE);
+ DCHECK(user_callback_.is_null());
+ next_state_ = STATE_CLOSE;
+ int rv = DoLoop(net::OK);
+ return;
+ }
+}
+
+bool SparseControlV3::CouldBeSparse() const {
+ if (init_)
+ return valid_;
+
if (entry_->GetDataSize(kSparseData))
return false;
@@ -222,9 +201,9 @@
return (entry_->GetDataSize(kSparseIndex) != 0);
}
-int SparseControl::StartIO(SparseOperation op, int64 offset, net::IOBuffer* buf,
- int buf_len, const CompletionCallback& callback) {
- DCHECK(init_);
+int SparseControlV3::StartIO(SparseOperation op, int64 offset,
+ net::IOBuffer* buf, int buf_len,
+ const CompletionCallback& callback) {
// We don't support simultaneous IO for sparse data.
if (operation_ != kNoOperation)
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
@@ -239,6 +218,9 @@
DCHECK(!user_buf_);
DCHECK(user_callback_.is_null());
+ if (init_ && !valid_)
+ return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
+
if (!buf && (op == kReadOperation || op == kWriteOperation))
return 0;
@@ -247,11 +229,8 @@
offset_ = offset;
user_buf_ = buf ? new net::DrainableIOBuffer(buf, buf_len) : NULL;
buf_len_ = buf_len;
- user_callback_ = callback;
result_ = 0;
- pending_ = false;
- finished_ = false;
abort_ = false;
if (entry_->net_log().IsLoggingAllEvents()) {
@@ -259,60 +238,63 @@
GetSparseEventType(operation_),
CreateNetLogSparseOperationCallback(offset_, buf_len_));
}
- DoChildrenIO();
- if (!pending_) {
- // Everything was done synchronously.
+ DCHECK_EQ(next_state_, STATE_NONE);
+ next_state_ = init_ ? STATE_GET_CHILD_KEY : STATE_INIT;
+
+ int rv = DoLoop(net::OK);
+ if (rv == net::ERR_IO_PENDING) {
+ user_callback_ = callback;
+ entry_->AddRef(); // Self preservation while we're working.
+ } else {
operation_ = kNoOperation;
user_buf_ = NULL;
- user_callback_.Reset();
- return result_;
}
- return net::ERR_IO_PENDING;
+ return rv;
}
-int SparseControl::GetAvailableRange(int64 offset, int len, int64* start) {
- DCHECK(init_);
+int SparseControlV3::GetAvailableRange(int64 offset, int len, int64* start,
+ const CompletionCallback& callback) {
// We don't support simultaneous IO for sparse data.
if (operation_ != kNoOperation)
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
DCHECK(start);
+ // If there is a failure, we want to return a valid start.
+ *start = offset;
range_found_ = false;
- int result = StartIO(
- kGetRangeOperation, offset, NULL, len, CompletionCallback());
+ range_start_ = start;
+ int result = StartIO(kGetRangeOperation, offset, NULL, len, callback);
if (range_found_) {
*start = offset_;
return result;
}
- // This is a failure. We want to return a valid start value in any case.
- *start = offset;
- return result < 0 ? result : 0; // Don't mask error codes to the caller.
+ return result;
}
-void SparseControl::CancelIO() {
+void SparseControlV3::CancelIO() {
if (operation_ == kNoOperation)
return;
abort_ = true;
}
-int SparseControl::ReadyToUse(const CompletionCallback& callback) {
+int SparseControlV3::ReadyToUse(const CompletionCallback& callback) {
if (!abort_)
return net::OK;
// We'll grab another reference to keep this object alive because we just have
// one extra reference due to the pending IO operation itself, but we'll
// release that one before invoking user_callback_.
- entry_->AddRef(); // Balanced in DoAbortCallbacks.
+ entry_->AddRef(); // Balanced in HanldeAbortCallbacks.
abort_callbacks_.push_back(callback);
return net::ERR_IO_PENDING;
}
// Static
-void SparseControl::DeleteChildren(EntryImpl* entry) {
+void SparseControlV3::DeleteChildren(EntryImplV3* entry) {
DCHECK(entry->GetEntryFlags() & PARENT_ENTRY);
int data_len = entry->GetDataSize(kSparseIndex);
if (data_len < static_cast<int>(sizeof(SparseData)) ||
@@ -323,7 +305,7 @@
if (map_len > kMaxMapSize || map_len % 4)
return;
- char* buffer;
+ scoped_refptr<net::IOBuffer> buffer;
Addr address;
entry->GetData(kSparseIndex, &buffer, &address);
if (!buffer && !address.is_initialized())
@@ -337,20 +319,100 @@
// The object will self destruct when finished.
deleter->AddRef();
- if (buffer) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&ChildrenDeleter::Start, deleter, buffer, data_len));
- } else {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&ChildrenDeleter::ReadData, deleter, address, data_len));
- }
+ if (buffer)
+ deleter->Start(buffer, data_len);
+ else
+ deleter->ReadData(address, data_len);
}
// -----------------------------------------------------------------------
-int SparseControl::Init() {
+int SparseControlV3::DoLoop(int result) {
+ DCHECK(next_state_ != STATE_NONE);
+
+ int rv = result;
+ do {
+ State state = next_state_;
+ next_state_ = STATE_NONE;
+ switch (state) {
+ case STATE_INIT:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoInit();
+ break;
+ case STATE_CREATE_SPARSE_ENTRY:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoCreateSparseEntry();
+ break;
+ case STATE_CREATE_SPARSE_ENTRY_COMPLETE:
+ rv = DoCreateSparseEntryComplete(rv);
+ break;
+ case STATE_OPEN_SPARSE_ENTRY:
+ rv = DoOpenSparseEntry(rv);
+ break;
+ case STATE_OPEN_SPARSE_ENTRY_COMPLETE:
+ rv = DoOpenSparseEntryComplete(rv);
+ break;
+ case STATE_READ_BITMAP_COMPLETE:
+ rv = DoReadBitmapComplete(rv);
+ break;
+ case STATE_GET_CHILD_KEY:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoGetChildKey();
+ break;
+ case STATE_OPEN_CHILD:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoOpenChild();
+ break;
+ case STATE_OPEN_CHILD_COMPLETE:
+ rv = DoOpenChildComplete(rv);
+ break;
+ case STATE_CREATE_CHILD:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoCreateChild();
+ break;
+ case STATE_CREATE_CHILD_COMPLETE:
+ rv = DoCreateChildComplete(rv);
+ break;
+ case STATE_READ_SIGNATURE_COMPLETE:
+ rv = DoReadSignatureComplete(rv);
+ break;
+ case STATE_CLOSE_CHILD:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoCloseChild();
+ break;
+ case STATE_CLOSE_CHILD_COMPLETE:
+ rv = DoCloseChildComplete(rv);
+ break;
+ case STATE_DO_CHILD_IO:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoChildIO();
+ break;
+ case STATE_DO_CHILD_IO_COMPLETE:
+ rv = DoChildIOComplete(rv);
+ break;
+ case STATE_CLOSE:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoClose();
+ break;
+ case STATE_WRITE_BITMAP:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoWriteBitmap();
+ break;
+ case STATE_WRITE_BITMAP_COMPLETE:
+ rv = DoWriteBitmapComplete(rv);
+ break;
+ default:
+ NOTREACHED();
+ }
+ } while (rv != net::ERR_IO_PENDING && next_state_ != STATE_NONE);
+
+ if (rv != net::ERR_IO_PENDING)
+ HandleResult(rv);
+
+ return rv;
+}
+
+int SparseControlV3::DoInit() {
DCHECK(!init_);
// We should not have sparse data for the exposed entry.
@@ -360,26 +422,23 @@
// Now see if there is something where we store our data.
int rv = net::OK;
int data_len = entry_->GetDataSize(kSparseIndex);
- if (!data_len) {
- rv = CreateSparseEntry();
- } else {
- rv = OpenSparseEntry(data_len);
+ if (data_len) {
+ next_state_ = STATE_OPEN_SPARSE_ENTRY;
+ return data_len;
}
-
- if (rv == net::OK)
- init_ = true;
- return rv;
+ next_state_ = STATE_CREATE_SPARSE_ENTRY;
+ return net::OK;
}
// We are going to start using this entry to store sparse data, so we have to
// initialize our control info.
-int SparseControl::CreateSparseEntry() {
+int SparseControlV3::DoCreateSparseEntry() {
if (CHILD_ENTRY & entry_->GetEntryFlags())
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
memset(&sparse_header_, 0, sizeof(sparse_header_));
sparse_header_.signature = Time::Now().ToInternalValue();
- sparse_header_.magic = kIndexMagic;
+ sparse_header_.magic = kIndexMagicV3;
sparse_header_.parent_key_len = entry_->GetKey().size();
children_map_.Resize(kNumSparseBits, true);
@@ -387,19 +446,26 @@
scoped_refptr<net::IOBuffer> buf(
new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_)));
- int rv = entry_->WriteData(kSparseIndex, 0, buf.get(), sizeof(sparse_header_),
- CompletionCallback(), false);
- if (rv != sizeof(sparse_header_)) {
+ next_state_ = STATE_CREATE_SPARSE_ENTRY_COMPLETE;
+ return entry_->WriteData(kSparseIndex, 0, buf, sizeof(sparse_header_),
+ callback_, false);
+}
+
+int SparseControlV3::DoCreateSparseEntryComplete(int result) {
+ if (result != sizeof(sparse_header_)) {
DLOG(ERROR) << "Unable to save sparse_header_";
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
}
entry_->SetEntryFlags(PARENT_ENTRY);
+ init_ = true;
+ valid_ = true;
+ next_state_ = STATE_GET_CHILD_KEY;
return net::OK;
}
// We are opening an entry from disk. Make sure that our control data is there.
-int SparseControl::OpenSparseEntry(int data_len) {
+int SparseControlV3::DoOpenSparseEntry(int data_len) {
if (data_len < static_cast<int>(sizeof(SparseData)))
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
@@ -418,71 +484,102 @@
new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_)));
// Read header.
- int rv = entry_->ReadData(kSparseIndex, 0, buf.get(), sizeof(sparse_header_),
- CompletionCallback());
- if (rv != static_cast<int>(sizeof(sparse_header_)))
+ next_state_ = STATE_OPEN_SPARSE_ENTRY_COMPLETE;
+ return entry_->ReadData(kSparseIndex, 0, buf, sizeof(sparse_header_),
+ callback_);
+}
+
+int SparseControlV3::DoOpenSparseEntryComplete(int result) {
+ if (result != static_cast<int>(sizeof(sparse_header_)))
return net::ERR_CACHE_READ_FAILURE;
// The real validation should be performed by the caller. This is just to
// double check.
- if (sparse_header_.magic != kIndexMagic ||
+ if (sparse_header_.magic != kIndexMagicV3 ||
sparse_header_.parent_key_len !=
static_cast<int>(entry_->GetKey().size()))
return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
// Read the actual bitmap.
- buf = new net::IOBuffer(map_len);
- rv = entry_->ReadData(kSparseIndex, sizeof(sparse_header_), buf.get(),
- map_len, CompletionCallback());
- if (rv != map_len)
+ int map_len = entry_->GetDataSize(kSparseIndex) - sizeof(sparse_header_);
+ buf_ = new net::IOBuffer(map_len);
+ next_state_ = STATE_READ_BITMAP_COMPLETE;
+ return entry_->ReadData(kSparseIndex, sizeof(sparse_header_), buf_, map_len,
+ callback_);
+}
+
+int SparseControlV3::DoReadBitmapComplete(int result) {
+ int map_len = entry_->GetDataSize(kSparseIndex) - sizeof(sparse_header_);
+ if (result != map_len)
return net::ERR_CACHE_READ_FAILURE;
// Grow the bitmap to the current size and copy the bits.
children_map_.Resize(map_len * 8, false);
- children_map_.SetMap(reinterpret_cast<uint32*>(buf->data()), map_len);
+ children_map_.SetMap(reinterpret_cast<uint32*>(buf_->data()), map_len);
+ init_ = true;
+ valid_ = true;
+ next_state_ = STATE_GET_CHILD_KEY;
return net::OK;
}
-bool SparseControl::OpenChild() {
- DCHECK_GE(result_, 0);
-
- std::string key = GenerateChildKey();
+int SparseControlV3::DoGetChildKey() {
+ key_ = GenerateChildKey();
if (child_) {
// Keep using the same child or open another one?.
- if (key == child_->GetKey())
- return true;
- CloseChild();
+ if (key_ == child_->GetKey()) {
+ next_state_ = STATE_DO_CHILD_IO;
+ return net::OK;
+ }
+ next_state_ = STATE_CLOSE_CHILD;
+ return net::OK;
}
+ next_state_ = STATE_OPEN_CHILD;
+ return net::OK;
+}
+int SparseControlV3::DoOpenChild() {
// See if we are tracking this child.
- if (!ChildPresent())
- return ContinueWithoutChild(key);
+ if (!ChildPresent()) {
+ next_state_ = STATE_CREATE_CHILD;
+ return net::OK;
+ }
if (!entry_->backend_)
- return false;
+ return net::ERR_FAILED;
- child_ = entry_->backend_->OpenEntryImpl(key);
- if (!child_)
- return ContinueWithoutChild(key);
+ next_state_ = STATE_OPEN_CHILD_COMPLETE;
+ return entry_->backend_->OpenEntry(key_, &child_, callback_);
+}
- EntryImpl* child = static_cast<EntryImpl*>(child_);
+int SparseControlV3::DoOpenChildComplete(int result) {
+ if (!child_) {
+ next_state_ = STATE_CREATE_CHILD;
+ return net::OK;
+ }
+
+ EntryImplV3* child = static_cast<EntryImplV3*>(child_);
if (!(CHILD_ENTRY & child->GetEntryFlags()) ||
child->GetDataSize(kSparseIndex) <
- static_cast<int>(sizeof(child_data_)))
- return KillChildAndContinue(key, false);
+ static_cast<int>(sizeof(child_data_))) {
+ return KillChildAndContinue();
+ }
scoped_refptr<net::WrappedIOBuffer> buf(
new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
// Read signature.
- int rv = child_->ReadData(kSparseIndex, 0, buf.get(), sizeof(child_data_),
- CompletionCallback());
- if (rv != sizeof(child_data_))
- return KillChildAndContinue(key, true); // This is a fatal failure.
+ next_state_ = STATE_READ_SIGNATURE_COMPLETE;
+ return child_->ReadData(kSparseIndex, 0, buf, sizeof(child_data_),
+ callback_);
+}
+int SparseControlV3::DoReadSignatureComplete(int result) {
+ if (result != sizeof(child_data_))
+ return KillChildAndContinue();
+
if (child_data_.header.signature != sparse_header_.signature ||
- child_data_.header.magic != kIndexMagic)
- return KillChildAndContinue(key, false);
+ child_data_.header.magic != kIndexMagicV3)
+ return KillChildAndContinue();
if (child_data_.header.last_block_len < 0 ||
child_data_.header.last_block_len > kBlockSize) {
@@ -491,160 +588,156 @@
child_data_.header.last_block = -1;
}
- return true;
+ next_state_ = STATE_DO_CHILD_IO;
+ return net::OK;
}
-void SparseControl::CloseChild() {
+int SparseControlV3::DoCloseChild() {
+ next_state_ = STATE_CLOSE_CHILD_COMPLETE;
scoped_refptr<net::WrappedIOBuffer> buf(
new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
// Save the allocation bitmap before closing the child entry.
- int rv = child_->WriteData(kSparseIndex, 0, buf.get(), sizeof(child_data_),
- CompletionCallback(),
- false);
- if (rv != sizeof(child_data_))
+ return child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_),
+ callback_, false);
+}
+
+int SparseControlV3::DoCloseChildComplete(int result) {
+ if (result != sizeof(child_data_))
DLOG(ERROR) << "Failed to save child data";
- child_->Release();
+ child_->Close();
child_ = NULL;
+
+ DCHECK(valid_);
+ if (closing_ && user_callback_.is_null())
+ next_state_= STATE_WRITE_BITMAP;
+ else
+ next_state_ = STATE_OPEN_CHILD;
+
+ return net::OK;
}
// We were not able to open this child; see what we can do.
-bool SparseControl::ContinueWithoutChild(const std::string& key) {
+int SparseControlV3::DoCreateChild() {
if (kReadOperation == operation_)
- return false;
- if (kGetRangeOperation == operation_)
- return true;
+ return 0;
+ if (kGetRangeOperation == operation_) {
+ next_state_ = STATE_DO_CHILD_IO;
+ return net::OK;
+ }
if (!entry_->backend_)
- return false;
+ return net::ERR_FAILED;
- child_ = entry_->backend_->CreateEntryImpl(key);
- if (!child_) {
- child_ = NULL;
- result_ = net::ERR_CACHE_READ_FAILURE;
- return false;
- }
+ next_state_ = STATE_CREATE_CHILD_COMPLETE;
+ return entry_->backend_->CreateEntry(key_, &child_, callback_);
+}
+
+int SparseControlV3::DoCreateChildComplete(int result) {
+ if (result != net::OK)
+ return net::ERR_CACHE_READ_FAILURE;
+
// Write signature.
InitChildData();
- return true;
+ next_state_ = STATE_DO_CHILD_IO;
+ return net::OK;
}
-void SparseControl::WriteSparseData() {
+int SparseControlV3::DoWriteBitmap() {
+ next_state_ = STATE_WRITE_BITMAP_COMPLETE;
scoped_refptr<net::IOBuffer> buf(new net::WrappedIOBuffer(
reinterpret_cast<const char*>(children_map_.GetMap())));
int len = children_map_.ArraySize() * 4;
- int rv = entry_->WriteData(kSparseIndex, sizeof(sparse_header_), buf.get(),
- len, CompletionCallback(), false);
- if (rv != len) {
+ return entry_->WriteData(kSparseIndex, sizeof(sparse_header_), buf, len,
+ callback_, false);
+}
+
+int SparseControlV3::DoWriteBitmapComplete(int result) {
+ if (result != children_map_.ArraySize() * 4) {
DLOG(ERROR) << "Unable to save sparse map";
}
+ return net::OK;
}
-bool SparseControl::DoChildIO() {
- finished_ = true;
- if (!buf_len_ || result_ < 0)
- return false;
-
- if (!OpenChild())
- return false;
-
+int SparseControlV3::DoChildIO() {
if (!VerifyRange())
- return false;
+ return 0;
- // We have more work to do. Let's not trigger a callback to the caller.
- finished_ = false;
- CompletionCallback callback;
- if (!user_callback_.is_null()) {
- callback =
- base::Bind(&SparseControl::OnChildIOCompleted, base::Unretained(this));
- }
-
int rv = 0;
switch (operation_) {
case kReadOperation:
- if (entry_->net_log().IsLoggingAllEvents()) {
- entry_->net_log().BeginEvent(
- net::NetLog::TYPE_SPARSE_READ_CHILD_DATA,
- CreateNetLogSparseReadWriteCallback(child_->net_log().source(),
- child_len_));
- }
- rv = child_->ReadDataImpl(kSparseData, child_offset_, user_buf_.get(),
- child_len_, callback);
+ LogChildOperationStart();
+ rv = child_->ReadData(kSparseData, child_offset_, user_buf_,
+ child_len_, callback_);
break;
case kWriteOperation:
- if (entry_->net_log().IsLoggingAllEvents()) {
- entry_->net_log().BeginEvent(
- net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA,
- CreateNetLogSparseReadWriteCallback(child_->net_log().source(),
- child_len_));
- }
- rv = child_->WriteDataImpl(kSparseData, child_offset_, user_buf_.get(),
- child_len_, callback, false);
+ LogChildOperationStart();
+ rv = child_->WriteData(kSparseData, child_offset_, user_buf_,
+ child_len_, callback_, false);
break;
case kGetRangeOperation:
- rv = DoGetAvailableRange();
+ rv = GetAvailableRangeImpl();
break;
default:
NOTREACHED();
}
- if (rv == net::ERR_IO_PENDING) {
- if (!pending_) {
- pending_ = true;
- // The child will protect himself against closing the entry while IO is in
- // progress. However, this entry can still be closed, and that would not
- // be a good thing for us, so we increase the refcount until we're
- // finished doing sparse stuff.
- entry_->AddRef(); // Balanced in DoUserCallback.
- }
- return false;
- }
- if (!rv)
- return false;
-
- DoChildIOCompleted(rv);
- return true;
+ next_state_ = STATE_DO_CHILD_IO_COMPLETE;
+ return rv;
}
-void SparseControl::DoChildIOCompleted(int result) {
- LogChildOperationEnd(entry_->net_log(), operation_, result);
- if (result < 0) {
- // We fail the whole operation if we encounter an error.
- result_ = result;
- return;
- }
+int SparseControlV3::DoChildIOComplete(int result) {
+ LogChildOperationEnd(result);
+ if (result < 0)
+ return LogCompletion(result);
+
UpdateRange(result);
- result_ += result;
+ if (operation_ != kGetRangeOperation)
+ result_ += result;
offset_ += result;
buf_len_ -= result;
+ if (!buf_len_)
+ return LogCompletion(result_);
+
// We'll be reusing the user provided buffer for the next chunk.
if (buf_len_ && user_buf_)
user_buf_->DidConsume(result);
+
+ next_state_ = STATE_GET_CHILD_KEY;
+ return net::OK;
}
-std::string SparseControl::GenerateChildKey() {
+int SparseControlV3::DoClose() {
+ DCHECK(valid_);
+ DCHECK(user_callback_.is_null());
+ if (child_)
+ next_state_= STATE_CLOSE_CHILD;
+ else if (valid_)
+ next_state_= STATE_WRITE_BITMAP;
+
+ return net::OK;
+}
+
+std::string SparseControlV3::GenerateChildKey() {
return GenerateChildName(entry_->GetKey(), sparse_header_.signature,
offset_ >> 20);
}
// We are deleting the child because something went wrong.
-bool SparseControl::KillChildAndContinue(const std::string& key, bool fatal) {
+int SparseControlV3::KillChildAndContinue() {
SetChildBit(false);
- child_->DoomImpl();
- child_->Release();
+ child_->Doom();
+ child_->Close();
child_ = NULL;
- if (fatal) {
- result_ = net::ERR_CACHE_READ_FAILURE;
- return false;
- }
- return ContinueWithoutChild(key);
+ next_state_ = STATE_CREATE_CHILD;
+ return net::OK;
}
-bool SparseControl::ChildPresent() {
+bool SparseControlV3::ChildPresent() {
int child_bit = static_cast<int>(offset_ >> 20);
if (children_map_.Size() <= child_bit)
return false;
@@ -652,7 +745,7 @@
return children_map_.Get(child_bit);
}
-void SparseControl::SetChildBit(bool value) {
+void SparseControlV3::SetChildBit(bool value) {
int child_bit = static_cast<int>(offset_ >> 20);
// We may have to increase the bitmap of child entries.
@@ -662,9 +755,7 @@
children_map_.Set(child_bit, value);
}
-bool SparseControl::VerifyRange() {
- DCHECK_GE(result_, 0);
-
+bool SparseControlV3::VerifyRange() {
child_offset_ = static_cast<int>(offset_) & (kMaxEntrySize - 1);
child_len_ = std::min(buf_len_, kMaxEntrySize - child_offset_);
@@ -698,7 +789,7 @@
return true;
}
-void SparseControl::UpdateRange(int result) {
+void SparseControlV3::UpdateRange(int result) {
if (result <= 0 || operation_ != kWriteOperation)
return;
@@ -735,7 +826,7 @@
child_map_.SetRange(first_bit, last_bit, true);
}
-int SparseControl::PartialBlockLength(int block_index) const {
+int SparseControlV3::PartialBlockLength(int block_index) const {
if (block_index == child_data_.header.last_block)
return child_data_.header.last_block_len;
@@ -748,9 +839,9 @@
return 0;
}
-void SparseControl::InitChildData() {
+void SparseControlV3::InitChildData() {
// We know the real type of child_.
- EntryImpl* child = static_cast<EntryImpl*>(child_);
+ EntryImplV3* child = static_cast<EntryImplV3*>(child_);
child->SetEntryFlags(CHILD_ENTRY);
memset(&child_data_, 0, sizeof(child_data_));
@@ -759,14 +850,14 @@
scoped_refptr<net::WrappedIOBuffer> buf(
new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
- int rv = child_->WriteData(kSparseIndex, 0, buf.get(), sizeof(child_data_),
+ int rv = child_->WriteData(kSparseIndex, 0, buf, sizeof(child_data_),
CompletionCallback(), false);
if (rv != sizeof(child_data_))
DLOG(ERROR) << "Failed to save child data";
SetChildBit(true);
}
-int SparseControl::DoGetAvailableRange() {
+int SparseControlV3::GetAvailableRangeImpl() {
if (!child_)
return child_len_; // Move on to the next child.
@@ -813,19 +904,91 @@
return 0;
}
-void SparseControl::DoUserCallback() {
- DCHECK(!user_callback_.is_null());
+void SparseControlV3::LogChildOperationStart() {
+ net::NetLog::EventType type = (operation_ == kReadOperation) ?
+ net::NetLog::TYPE_SPARSE_READ_CHILD_DATA :
+ net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA;
+
+ if (entry_->net_log().IsLoggingAllEvents()) {
+ disk_cache::EntryImplV3* entry =
+ reinterpret_cast<disk_cache::EntryImplV3*>(child_);
+ entry_->net_log().BeginEvent(
+ type,
+ CreateNetLogSparseReadWriteCallback(entry->net_log().source(),
+ child_len_));
+ }
+}
+
+void SparseControlV3::LogChildOperationEnd(int result) {
+ if (entry_->net_log().IsLoggingAllEvents()) {
+ net::NetLog::EventType event_type;
+ switch (operation_) {
+ case disk_cache::SparseControlV3::kReadOperation:
+ event_type = net::NetLog::TYPE_SPARSE_READ_CHILD_DATA;
+ break;
+ case disk_cache::SparseControlV3::kWriteOperation:
+ event_type = net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA;
+ break;
+ case disk_cache::SparseControlV3::kGetRangeOperation:
+ return;
+ default:
+ NOTREACHED();
+ return;
+ }
+ entry_->net_log().EndEventWithNetErrorCode(event_type, result);
+ }
+}
+
+int SparseControlV3::LogCompletion(int result) {
+ if (!entry_->net_log().IsLoggingAllEvents())
+ return result;
+
+ if (kGetRangeOperation == operation_) {
+ entry_->net_log().EndEvent(
+ net::NetLog::TYPE_SPARSE_GET_RANGE,
+ CreateNetLogGetAvailableRangeResultCallback(offset_, result));
+ } else {
+ entry_->net_log().EndEvent(GetSparseEventType(operation_));
+ }
+ return result;
+}
+
+void SparseControlV3::HandleResult(int result) {
+ if (!result && result_)
+ result = result_;
+
+ if (result > 0 && operation_ == kGetRangeOperation)
+ *range_start_ = offset_;
+
+ user_buf_ = NULL;
+ operation_ = kNoOperation;
+ next_state_ = STATE_NONE;
+
+ if (user_callback_.is_null()) {
+ if (closing_) {
+ closing_ = false;
+ entry_->Release(); // Don't touch object after this line.
+ }
+ return;
+ }
+
CompletionCallback cb = user_callback_;
user_callback_.Reset();
- user_buf_ = NULL;
- pending_ = false;
- operation_ = kNoOperation;
- int rv = result_;
+ bool closing = closing_;
+ DCHECK(!closing_ || !entry_->HasOneRef());
+
entry_->Release(); // Don't touch object after this line.
- cb.Run(rv);
+ cb.Run(result);
+
+ if (closing) {
+ // This object is not gone yet, but there's more work to do before the
+ // destructor runs.
+ next_state_ = STATE_CLOSE;
+ int rv = DoLoop(net::OK);
+ }
}
-void SparseControl::DoAbortCallbacks() {
+void SparseControlV3::HanldeAbortCallbacks() {
for (size_t i = 0; i < abort_callbacks_.size(); i++) {
// Releasing all references to entry_ may result in the destruction of this
// object so we should not be touching it after the last Release().
@@ -838,9 +1001,8 @@
}
}
-void SparseControl::OnChildIOCompleted(int result) {
+void SparseControlV3::OnIOComplete(int result) {
DCHECK_NE(net::ERR_IO_PENDING, result);
- DoChildIOCompleted(result);
if (abort_) {
// We'll return the current result of the operation, which may be less than
@@ -852,17 +1014,15 @@
}
// We have an indirect reference to this object for every callback so if
// there is only one callback, we may delete this object before reaching
- // DoAbortCallbacks.
+ // HanldeAbortCallbacks.
bool has_abort_callbacks = !abort_callbacks_.empty();
- DoUserCallback();
+ HandleResult(result);
if (has_abort_callbacks)
- DoAbortCallbacks();
+ HanldeAbortCallbacks();
return;
}
- // We are running a callback from the message loop. It's time to restart what
- // we were doing before.
- DoChildrenIO();
+ DoLoop(result);
}
} // namespace disk_cache
« no previous file with comments | « net/disk_cache/v3/sparse_control_v3.h ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698