1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/disk_cache/blockfile/sparse_control.h"
8 #include "base/format_macros.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
16 #include "net/disk_cache/blockfile/backend_impl.h"
17 #include "net/disk_cache/blockfile/entry_impl.h"
18 #include "net/disk_cache/blockfile/file.h"
19 #include "net/disk_cache/net_log_parameters.h"
25 // Stream of the sparse data index.
26 const int kSparseIndex = 2;
28 // Stream of the sparse data.
29 const int kSparseData = 1;
31 // We can have up to 64k children.
32 const int kMaxMapSize = 8 * 1024;
34 // The maximum number of bytes that a child can store.
35 const int kMaxEntrySize = 0x100000;
37 // The size of each data block (tracked by the child allocation bitmap).
38 const int kBlockSize = 1024;
40 // Returns the name of a child entry given the base_name and signature of the
41 // parent and the child_id.
42 // If the entry is called entry_name, child entries will be named something
43 // like Range_entry_name:XXX:YYY where XXX is the entry signature and YYY is the
44 // number of the particular child.
45 std::string GenerateChildName(const std::string& base_name, int64 signature,
47 return base::StringPrintf("Range_%s:%" PRIx64 ":%" PRIx64, base_name.c_str(),
51 // This class deletes the children of a sparse entry.
53 : public base::RefCounted<ChildrenDeleter>,
54 public disk_cache::FileIOCallback {
56 ChildrenDeleter(disk_cache::BackendImpl* backend, const std::string& name)
57 : backend_(backend->GetWeakPtr()), name_(name), signature_(0) {}
59 virtual void OnFileIOComplete(int bytes_copied) override;
61 // Two ways of deleting the children: if we have the children map, use Start()
62 // directly, otherwise pass the data address to ReadData().
63 void Start(char* buffer, int len);
64 void ReadData(disk_cache::Addr address, int len);
67 friend class base::RefCounted<ChildrenDeleter>;
68 virtual ~ChildrenDeleter() {}
70 void DeleteChildren();
72 base::WeakPtr<disk_cache::BackendImpl> backend_;
74 disk_cache::Bitmap children_map_;
76 scoped_ptr<char[]> buffer_;
77 DISALLOW_COPY_AND_ASSIGN(ChildrenDeleter);
80 // This is the callback of the file operation.
81 void ChildrenDeleter::OnFileIOComplete(int bytes_copied) {
82 char* buffer = buffer_.release();
83 Start(buffer, bytes_copied);
86 void ChildrenDeleter::Start(char* buffer, int len) {
87 buffer_.reset(buffer);
88 if (len < static_cast<int>(sizeof(disk_cache::SparseData)))
91 // Just copy the information from |buffer|, delete |buffer| and start deleting
93 disk_cache::SparseData* data =
94 reinterpret_cast<disk_cache::SparseData*>(buffer);
95 signature_ = data->header.signature;
97 int num_bits = (len - sizeof(disk_cache::SparseHeader)) * 8;
98 children_map_.Resize(num_bits, false);
99 children_map_.SetMap(data->bitmap, num_bits / 32);
105 void ChildrenDeleter::ReadData(disk_cache::Addr address, int len) {
106 DCHECK(address.is_block_file());
110 disk_cache::File* file(backend_->File(address));
114 size_t file_offset = address.start_block() * address.BlockSize() +
115 disk_cache::kBlockHeaderSize;
117 buffer_.reset(new char[len]);
119 if (!file->Read(buffer_.get(), len, file_offset, this, &completed))
123 OnFileIOComplete(len);
125 // And wait until OnFileIOComplete gets called.
128 void ChildrenDeleter::DeleteChildren() {
130 if (!children_map_.FindNextSetBit(&child_id) || !backend_) {
131 // We are done. Just delete this object.
134 std::string child_name = GenerateChildName(name_, signature_, child_id);
135 backend_->SyncDoomEntry(child_name);
136 children_map_.Set(child_id, false);
138 // Post a task to delete the next child.
139 base::MessageLoop::current()->PostTask(
140 FROM_HERE, base::Bind(&ChildrenDeleter::DeleteChildren, this));
143 // -----------------------------------------------------------------------
145 // Returns the NetLog event type corresponding to a SparseOperation.
146 net::NetLog::EventType GetSparseEventType(
147 disk_cache::SparseControl::SparseOperation operation) {
149 case disk_cache::SparseControl::kReadOperation:
150 return net::NetLog::TYPE_SPARSE_READ;
151 case disk_cache::SparseControl::kWriteOperation:
152 return net::NetLog::TYPE_SPARSE_WRITE;
153 case disk_cache::SparseControl::kGetRangeOperation:
154 return net::NetLog::TYPE_SPARSE_GET_RANGE;
157 return net::NetLog::TYPE_CANCELLED;
161 // Logs the end event for |operation| on a child entry. Range operations log
162 // no events for each child they search through.
163 void LogChildOperationEnd(const net::BoundNetLog& net_log,
164 disk_cache::SparseControl::SparseOperation operation,
166 if (net_log.IsLogging()) {
167 net::NetLog::EventType event_type;
169 case disk_cache::SparseControl::kReadOperation:
170 event_type = net::NetLog::TYPE_SPARSE_READ_CHILD_DATA;
172 case disk_cache::SparseControl::kWriteOperation:
173 event_type = net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA;
175 case disk_cache::SparseControl::kGetRangeOperation:
181 net_log.EndEventWithNetErrorCode(event_type, result);
187 namespace disk_cache {
189 SparseControl::SparseControl(EntryImpl* entry)
192 operation_(kNoOperation),
198 child_map_(child_data_.bitmap, kNumSparseBits, kNumSparseBits / 32),
204 memset(&sparse_header_, 0, sizeof(sparse_header_));
205 memset(&child_data_, 0, sizeof(child_data_));
208 SparseControl::~SparseControl() {
215 bool SparseControl::CouldBeSparse() const {
218 if (entry_->GetDataSize(kSparseData))
221 // We don't verify the data, just see if it could be there.
222 return (entry_->GetDataSize(kSparseIndex) != 0);
225 int SparseControl::StartIO(SparseOperation op, int64 offset, net::IOBuffer* buf,
226 int buf_len, const CompletionCallback& callback) {
228 // We don't support simultaneous IO for sparse data.
229 if (operation_ != kNoOperation)
230 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
232 if (offset < 0 || buf_len < 0)
233 return net::ERR_INVALID_ARGUMENT;
235 // We only support up to 64 GB.
236 if (offset + buf_len >= 0x1000000000LL || offset + buf_len < 0)
237 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
240 DCHECK(user_callback_.is_null());
242 if (!buf && (op == kReadOperation || op == kWriteOperation))
245 // Copy the operation parameters.
248 user_buf_ = buf ? new net::DrainableIOBuffer(buf, buf_len) : NULL;
250 user_callback_ = callback;
257 if (entry_->net_log().IsLogging()) {
258 entry_->net_log().BeginEvent(
259 GetSparseEventType(operation_),
260 CreateNetLogSparseOperationCallback(offset_, buf_len_));
265 // Everything was done synchronously.
266 operation_ = kNoOperation;
268 user_callback_.Reset();
272 return net::ERR_IO_PENDING;
275 int SparseControl::GetAvailableRange(int64 offset, int len, int64* start) {
277 // We don't support simultaneous IO for sparse data.
278 if (operation_ != kNoOperation)
279 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
283 range_found_ = false;
284 int result = StartIO(
285 kGetRangeOperation, offset, NULL, len, CompletionCallback());
291 // This is a failure. We want to return a valid start value in any case.
293 return result < 0 ? result : 0; // Don't mask error codes to the caller.
296 void SparseControl::CancelIO() {
297 if (operation_ == kNoOperation)
302 int SparseControl::ReadyToUse(const CompletionCallback& callback) {
306 // We'll grab another reference to keep this object alive because we just have
307 // one extra reference due to the pending IO operation itself, but we'll
308 // release that one before invoking user_callback_.
309 entry_->AddRef(); // Balanced in DoAbortCallbacks.
310 abort_callbacks_.push_back(callback);
311 return net::ERR_IO_PENDING;
315 void SparseControl::DeleteChildren(EntryImpl* entry) {
316 DCHECK(entry->GetEntryFlags() & PARENT_ENTRY);
317 int data_len = entry->GetDataSize(kSparseIndex);
318 if (data_len < static_cast<int>(sizeof(SparseData)) ||
319 entry->GetDataSize(kSparseData))
322 int map_len = data_len - sizeof(SparseHeader);
323 if (map_len > kMaxMapSize || map_len % 4)
328 entry->GetData(kSparseIndex, &buffer, &address);
329 if (!buffer && !address.is_initialized())
332 entry->net_log().AddEvent(net::NetLog::TYPE_SPARSE_DELETE_CHILDREN);
334 DCHECK(entry->backend_);
335 ChildrenDeleter* deleter = new ChildrenDeleter(entry->backend_.get(),
337 // The object will self destruct when finished.
341 base::MessageLoop::current()->PostTask(
343 base::Bind(&ChildrenDeleter::Start, deleter, buffer, data_len));
345 base::MessageLoop::current()->PostTask(
347 base::Bind(&ChildrenDeleter::ReadData, deleter, address, data_len));
351 // -----------------------------------------------------------------------
353 int SparseControl::Init() {
356 // We should not have sparse data for the exposed entry.
357 if (entry_->GetDataSize(kSparseData))
358 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
360 // Now see if there is something where we store our data.
362 int data_len = entry_->GetDataSize(kSparseIndex);
364 rv = CreateSparseEntry();
366 rv = OpenSparseEntry(data_len);
374 // We are going to start using this entry to store sparse data, so we have to
375 // initialize our control info.
376 int SparseControl::CreateSparseEntry() {
377 if (CHILD_ENTRY & entry_->GetEntryFlags())
378 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
380 memset(&sparse_header_, 0, sizeof(sparse_header_));
381 sparse_header_.signature = Time::Now().ToInternalValue();
382 sparse_header_.magic = kIndexMagic;
383 sparse_header_.parent_key_len = entry_->GetKey().size();
384 children_map_.Resize(kNumSparseBits, true);
386 // Save the header. The bitmap is saved in the destructor.
387 scoped_refptr<net::IOBuffer> buf(
388 new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_)));
390 int rv = entry_->WriteData(kSparseIndex, 0, buf.get(), sizeof(sparse_header_),
391 CompletionCallback(), false);
392 if (rv != sizeof(sparse_header_)) {
393 DLOG(ERROR) << "Unable to save sparse_header_";
394 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
397 entry_->SetEntryFlags(PARENT_ENTRY);
401 // We are opening an entry from disk. Make sure that our control data is there.
402 int SparseControl::OpenSparseEntry(int data_len) {
403 if (data_len < static_cast<int>(sizeof(SparseData)))
404 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
406 if (entry_->GetDataSize(kSparseData))
407 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
409 if (!(PARENT_ENTRY & entry_->GetEntryFlags()))
410 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
412 // Dont't go over board with the bitmap. 8 KB gives us offsets up to 64 GB.
413 int map_len = data_len - sizeof(sparse_header_);
414 if (map_len > kMaxMapSize || map_len % 4)
415 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
417 scoped_refptr<net::IOBuffer> buf(
418 new net::WrappedIOBuffer(reinterpret_cast<char*>(&sparse_header_)));
421 int rv = entry_->ReadData(kSparseIndex, 0, buf.get(), sizeof(sparse_header_),
422 CompletionCallback());
423 if (rv != static_cast<int>(sizeof(sparse_header_)))
424 return net::ERR_CACHE_READ_FAILURE;
426 // The real validation should be performed by the caller. This is just to
428 if (sparse_header_.magic != kIndexMagic ||
429 sparse_header_.parent_key_len !=
430 static_cast<int>(entry_->GetKey().size()))
431 return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
433 // Read the actual bitmap.
434 buf = new net::IOBuffer(map_len);
435 rv = entry_->ReadData(kSparseIndex, sizeof(sparse_header_), buf.get(),
436 map_len, CompletionCallback());
438 return net::ERR_CACHE_READ_FAILURE;
440 // Grow the bitmap to the current size and copy the bits.
441 children_map_.Resize(map_len * 8, false);
442 children_map_.SetMap(reinterpret_cast<uint32*>(buf->data()), map_len);
446 bool SparseControl::OpenChild() {
447 DCHECK_GE(result_, 0);
449 std::string key = GenerateChildKey();
451 // Keep using the same child or open another one?.
452 if (key == child_->GetKey())
457 // See if we are tracking this child.
459 return ContinueWithoutChild(key);
461 if (!entry_->backend_)
464 child_ = entry_->backend_->OpenEntryImpl(key);
466 return ContinueWithoutChild(key);
468 EntryImpl* child = static_cast<EntryImpl*>(child_);
469 if (!(CHILD_ENTRY & child->GetEntryFlags()) ||
470 child->GetDataSize(kSparseIndex) <
471 static_cast<int>(sizeof(child_data_)))
472 return KillChildAndContinue(key, false);
474 scoped_refptr<net::WrappedIOBuffer> buf(
475 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
478 int rv = child_->ReadData(kSparseIndex, 0, buf.get(), sizeof(child_data_),
479 CompletionCallback());
480 if (rv != sizeof(child_data_))
481 return KillChildAndContinue(key, true); // This is a fatal failure.
483 if (child_data_.header.signature != sparse_header_.signature ||
484 child_data_.header.magic != kIndexMagic)
485 return KillChildAndContinue(key, false);
487 if (child_data_.header.last_block_len < 0 ||
488 child_data_.header.last_block_len > kBlockSize) {
489 // Make sure these values are always within range.
490 child_data_.header.last_block_len = 0;
491 child_data_.header.last_block = -1;
497 void SparseControl::CloseChild() {
498 scoped_refptr<net::WrappedIOBuffer> buf(
499 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
501 // Save the allocation bitmap before closing the child entry.
502 int rv = child_->WriteData(kSparseIndex, 0, buf.get(), sizeof(child_data_),
503 CompletionCallback(),
505 if (rv != sizeof(child_data_))
506 DLOG(ERROR) << "Failed to save child data";
511 // We were not able to open this child; see what we can do.
512 bool SparseControl::ContinueWithoutChild(const std::string& key) {
513 if (kReadOperation == operation_)
515 if (kGetRangeOperation == operation_)
518 if (!entry_->backend_)
521 child_ = entry_->backend_->CreateEntryImpl(key);
524 result_ = net::ERR_CACHE_READ_FAILURE;
532 void SparseControl::WriteSparseData() {
533 scoped_refptr<net::IOBuffer> buf(new net::WrappedIOBuffer(
534 reinterpret_cast<const char*>(children_map_.GetMap())));
536 int len = children_map_.ArraySize() * 4;
537 int rv = entry_->WriteData(kSparseIndex, sizeof(sparse_header_), buf.get(),
538 len, CompletionCallback(), false);
540 DLOG(ERROR) << "Unable to save sparse map";
544 bool SparseControl::DoChildIO() {
546 if (!buf_len_ || result_ < 0)
555 // We have more work to do. Let's not trigger a callback to the caller.
557 CompletionCallback callback;
558 if (!user_callback_.is_null()) {
560 base::Bind(&SparseControl::OnChildIOCompleted, base::Unretained(this));
564 switch (operation_) {
566 if (entry_->net_log().IsLogging()) {
567 entry_->net_log().BeginEvent(
568 net::NetLog::TYPE_SPARSE_READ_CHILD_DATA,
569 CreateNetLogSparseReadWriteCallback(child_->net_log().source(),
572 rv = child_->ReadDataImpl(kSparseData, child_offset_, user_buf_.get(),
573 child_len_, callback);
575 case kWriteOperation:
576 if (entry_->net_log().IsLogging()) {
577 entry_->net_log().BeginEvent(
578 net::NetLog::TYPE_SPARSE_WRITE_CHILD_DATA,
579 CreateNetLogSparseReadWriteCallback(child_->net_log().source(),
582 rv = child_->WriteDataImpl(kSparseData, child_offset_, user_buf_.get(),
583 child_len_, callback, false);
585 case kGetRangeOperation:
586 rv = DoGetAvailableRange();
592 if (rv == net::ERR_IO_PENDING) {
595 // The child will protect himself against closing the entry while IO is in
596 // progress. However, this entry can still be closed, and that would not
597 // be a good thing for us, so we increase the refcount until we're
598 // finished doing sparse stuff.
599 entry_->AddRef(); // Balanced in DoUserCallback.
606 DoChildIOCompleted(rv);
610 void SparseControl::DoChildIOCompleted(int result) {
611 LogChildOperationEnd(entry_->net_log(), operation_, result);
613 // We fail the whole operation if we encounter an error.
624 // We'll be reusing the user provided buffer for the next chunk.
625 if (buf_len_ && user_buf_)
626 user_buf_->DidConsume(result);
629 std::string SparseControl::GenerateChildKey() {
630 return GenerateChildName(entry_->GetKey(), sparse_header_.signature,
634 // We are deleting the child because something went wrong.
635 bool SparseControl::KillChildAndContinue(const std::string& key, bool fatal) {
641 result_ = net::ERR_CACHE_READ_FAILURE;
644 return ContinueWithoutChild(key);
647 bool SparseControl::ChildPresent() {
648 int child_bit = static_cast<int>(offset_ >> 20);
649 if (children_map_.Size() <= child_bit)
652 return children_map_.Get(child_bit);
655 void SparseControl::SetChildBit(bool value) {
656 int child_bit = static_cast<int>(offset_ >> 20);
658 // We may have to increase the bitmap of child entries.
659 if (children_map_.Size() <= child_bit)
660 children_map_.Resize(Bitmap::RequiredArraySize(child_bit + 1) * 32, true);
662 children_map_.Set(child_bit, value);
665 bool SparseControl::VerifyRange() {
666 DCHECK_GE(result_, 0);
668 child_offset_ = static_cast<int>(offset_) & (kMaxEntrySize - 1);
669 child_len_ = std::min(buf_len_, kMaxEntrySize - child_offset_);
671 // We can write to (or get info from) anywhere in this child.
672 if (operation_ != kReadOperation)
675 // Check that there are no holes in this range.
676 int last_bit = (child_offset_ + child_len_ + 1023) >> 10;
677 int start = child_offset_ >> 10;
678 if (child_map_.FindNextBit(&start, last_bit, false)) {
679 // Something is not here.
680 DCHECK_GE(child_data_.header.last_block_len, 0);
681 DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize);
682 int partial_block_len = PartialBlockLength(start);
683 if (start == child_offset_ >> 10) {
684 // It looks like we don't have anything.
685 if (partial_block_len <= (child_offset_ & (kBlockSize - 1)))
689 // We have the first part.
690 child_len_ = (start << 10) - child_offset_;
691 if (partial_block_len) {
692 // We may have a few extra bytes.
693 child_len_ = std::min(child_len_ + partial_block_len, buf_len_);
695 // There is no need to read more after this one.
696 buf_len_ = child_len_;
701 void SparseControl::UpdateRange(int result) {
702 if (result <= 0 || operation_ != kWriteOperation)
705 DCHECK_GE(child_data_.header.last_block_len, 0);
706 DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize);
709 int first_bit = child_offset_ >> 10;
710 int block_offset = child_offset_ & (kBlockSize - 1);
711 if (block_offset && (child_data_.header.last_block != first_bit ||
712 child_data_.header.last_block_len < block_offset)) {
713 // The first block is not completely filled; ignore it.
717 int last_bit = (child_offset_ + result) >> 10;
718 block_offset = (child_offset_ + result) & (kBlockSize - 1);
720 // This condition will hit with the following criteria:
721 // 1. The first byte doesn't follow the last write.
722 // 2. The first byte is in the middle of a block.
723 // 3. The first byte and the last byte are in the same block.
724 if (first_bit > last_bit)
727 if (block_offset && !child_map_.Get(last_bit)) {
728 // The last block is not completely filled; save it for later.
729 child_data_.header.last_block = last_bit;
730 child_data_.header.last_block_len = block_offset;
732 child_data_.header.last_block = -1;
735 child_map_.SetRange(first_bit, last_bit, true);
738 int SparseControl::PartialBlockLength(int block_index) const {
739 if (block_index == child_data_.header.last_block)
740 return child_data_.header.last_block_len;
742 // This may be the last stored index.
743 int entry_len = child_->GetDataSize(kSparseData);
744 if (block_index == entry_len >> 10)
745 return entry_len & (kBlockSize - 1);
747 // This is really empty.
751 void SparseControl::InitChildData() {
752 // We know the real type of child_.
753 EntryImpl* child = static_cast<EntryImpl*>(child_);
754 child->SetEntryFlags(CHILD_ENTRY);
756 memset(&child_data_, 0, sizeof(child_data_));
757 child_data_.header = sparse_header_;
759 scoped_refptr<net::WrappedIOBuffer> buf(
760 new net::WrappedIOBuffer(reinterpret_cast<char*>(&child_data_)));
762 int rv = child_->WriteData(kSparseIndex, 0, buf.get(), sizeof(child_data_),
763 CompletionCallback(), false);
764 if (rv != sizeof(child_data_))
765 DLOG(ERROR) << "Failed to save child data";
769 int SparseControl::DoGetAvailableRange() {
771 return child_len_; // Move on to the next child.
773 // Check that there are no holes in this range.
774 int last_bit = (child_offset_ + child_len_ + 1023) >> 10;
775 int start = child_offset_ >> 10;
776 int partial_start_bytes = PartialBlockLength(start);
778 int bits_found = child_map_.FindBits(&found, last_bit, true);
780 // We don't care if there is a partial block in the middle of the range.
781 int block_offset = child_offset_ & (kBlockSize - 1);
782 if (!bits_found && partial_start_bytes <= block_offset)
785 // We are done. Just break the loop and reset result_ to our real result.
788 // found now points to the first 1. Lets see if we have zeros before it.
789 int empty_start = std::max((found << 10) - child_offset_, 0);
791 int bytes_found = bits_found << 10;
792 bytes_found += PartialBlockLength(found + bits_found);
795 bytes_found -= block_offset;
797 // If the user is searching past the end of this child, bits_found is the
798 // right result; otherwise, we have some empty space at the start of this
799 // query that we have to subtract from the range that we searched.
800 result_ = std::min(bytes_found, child_len_ - empty_start);
803 result_ = std::min(partial_start_bytes - block_offset, child_len_);
807 // Only update offset_ when this query found zeros at the start.
809 offset_ += empty_start;
811 // This will actually break the loop.
816 void SparseControl::DoUserCallback() {
817 DCHECK(!user_callback_.is_null());
818 CompletionCallback cb = user_callback_;
819 user_callback_.Reset();
822 operation_ = kNoOperation;
824 entry_->Release(); // Don't touch object after this line.
828 void SparseControl::DoAbortCallbacks() {
829 for (size_t i = 0; i < abort_callbacks_.size(); i++) {
830 // Releasing all references to entry_ may result in the destruction of this
831 // object so we should not be touching it after the last Release().
832 CompletionCallback cb = abort_callbacks_[i];
833 if (i == abort_callbacks_.size() - 1)
834 abort_callbacks_.clear();
836 entry_->Release(); // Don't touch object after this line.
841 void SparseControl::OnChildIOCompleted(int result) {
842 DCHECK_NE(net::ERR_IO_PENDING, result);
843 DoChildIOCompleted(result);
846 // We'll return the current result of the operation, which may be less than
847 // the bytes to read or write, but the user cancelled the operation.
849 if (entry_->net_log().IsLogging()) {
850 entry_->net_log().AddEvent(net::NetLog::TYPE_CANCELLED);
851 entry_->net_log().EndEvent(GetSparseEventType(operation_));
853 // We have an indirect reference to this object for every callback so if
854 // there is only one callback, we may delete this object before reaching
856 bool has_abort_callbacks = !abort_callbacks_.empty();
858 if (has_abort_callbacks)
863 // We are running a callback from the message loop. It's time to restart what
864 // we were doing before.
868 } // namespace disk_cache