| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/disk_cache/entry_impl.h" | 5 #include "net/disk_cache/entry_impl.h" |
| 6 | 6 |
| 7 #include "base/histogram.h" | 7 #include "base/histogram.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "net/base/net_errors.h" | 10 #include "net/base/net_errors.h" |
| 11 #include "net/disk_cache/backend_impl.h" | 11 #include "net/disk_cache/backend_impl.h" |
| 12 #include "net/disk_cache/cache_util.h" | 12 #include "net/disk_cache/cache_util.h" |
| 13 | 13 |
| 14 using base::Time; | 14 using base::Time; |
| 15 using base::TimeDelta; | 15 using base::TimeDelta; |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 // This is a simple Task to execute the callback (from the message loop instead | 19 // This class implements FileIOCallback to buffer the callback from a file IO |
| 20 // of the APC). | 20 // operation from the actual net class. |
| 21 class InvokeCallback : public Task { | |
| 22 public: | |
| 23 InvokeCallback(net::CompletionCallback* callback, int argument) | |
| 24 : callback_(callback), argument_(argument) {} | |
| 25 | |
| 26 virtual void Run() { | |
| 27 callback_->Run(argument_); | |
| 28 } | |
| 29 | |
| 30 private: | |
| 31 net::CompletionCallback* callback_; | |
| 32 int argument_; | |
| 33 DISALLOW_EVIL_CONSTRUCTORS(InvokeCallback); | |
| 34 }; | |
| 35 | |
| 36 // This class implements FileIOCallback to buffer the callback from an IO | |
| 37 // operation from the actual IO class. | |
| 38 class SyncCallback: public disk_cache::FileIOCallback { | 21 class SyncCallback: public disk_cache::FileIOCallback { |
| 39 public: | 22 public: |
| 40 SyncCallback(disk_cache::EntryImpl* entry, | 23 SyncCallback(disk_cache::EntryImpl* entry, |
| 41 net::CompletionCallback* callback ) | 24 net::CompletionCallback* callback ) |
| 42 : entry_(entry), callback_(callback) { | 25 : entry_(entry), callback_(callback) { |
| 43 entry->AddRef(); | 26 entry->AddRef(); |
| 44 entry->IncrementIoCount(); | 27 entry->IncrementIoCount(); |
| 45 } | 28 } |
| 46 ~SyncCallback() {} | 29 ~SyncCallback() {} |
| 47 | 30 |
| 48 virtual void OnFileIOComplete(int bytes_copied); | 31 virtual void OnFileIOComplete(int bytes_copied); |
| 49 void Discard(); | 32 void Discard(); |
| 50 private: | 33 private: |
| 51 disk_cache::EntryImpl* entry_; | 34 disk_cache::EntryImpl* entry_; |
| 52 net::CompletionCallback* callback_; | 35 net::CompletionCallback* callback_; |
| 53 | 36 |
| 54 DISALLOW_EVIL_CONSTRUCTORS(SyncCallback); | 37 DISALLOW_EVIL_CONSTRUCTORS(SyncCallback); |
| 55 }; | 38 }; |
| 56 | 39 |
| 57 void SyncCallback::OnFileIOComplete(int bytes_copied) { | 40 void SyncCallback::OnFileIOComplete(int bytes_copied) { |
| 58 entry_->DecrementIoCount(); | 41 entry_->DecrementIoCount(); |
| 59 entry_->Release(); | 42 entry_->Release(); |
| 60 if (callback_) { | 43 if (callback_) |
| 61 InvokeCallback* task = new InvokeCallback(callback_, bytes_copied); | 44 callback_->Run(bytes_copied); |
| 62 MessageLoop::current()->PostTask(FROM_HERE, task); | |
| 63 } | |
| 64 delete this; | 45 delete this; |
| 65 } | 46 } |
| 66 | 47 |
| 67 void SyncCallback::Discard() { | 48 void SyncCallback::Discard() { |
| 68 callback_ = NULL; | 49 callback_ = NULL; |
| 69 OnFileIOComplete(0); | 50 OnFileIOComplete(0); |
| 70 } | 51 } |
| 71 | 52 |
| 72 // Clears buffer before offset and after valid_len, knowing that the size of | 53 // Clears buffer before offset and after valid_len, knowing that the size of |
| 73 // buffer is kMaxBlockSize. | 54 // buffer is kMaxBlockSize. |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 return true; | 530 return true; |
| 550 } | 531 } |
| 551 | 532 |
| 552 void EntryImpl::DeleteData(Addr address, int index) { | 533 void EntryImpl::DeleteData(Addr address, int index) { |
| 553 if (!address.is_initialized()) | 534 if (!address.is_initialized()) |
| 554 return; | 535 return; |
| 555 if (address.is_separate_file()) { | 536 if (address.is_separate_file()) { |
| 556 if (files_[index]) | 537 if (files_[index]) |
| 557 files_[index] = NULL; // Releases the object. | 538 files_[index] = NULL; // Releases the object. |
| 558 | 539 |
| 559 if (!DeleteCacheFile(backend_->GetFileName(address))) | 540 if (!DeleteCacheFile(backend_->GetFileName(address))) { |
| 541 UMA_HISTOGRAM_COUNTS(L"DiskCache.DeleteFailed", 1); |
| 560 LOG(ERROR) << "Failed to delete " << backend_->GetFileName(address) << | 542 LOG(ERROR) << "Failed to delete " << backend_->GetFileName(address) << |
| 561 " from the cache."; | 543 " from the cache."; |
| 544 } |
| 562 } else { | 545 } else { |
| 563 backend_->DeleteBlock(address, true); | 546 backend_->DeleteBlock(address, true); |
| 564 } | 547 } |
| 565 } | 548 } |
| 566 | 549 |
| 567 void EntryImpl::UpdateRank(bool modified) { | 550 void EntryImpl::UpdateRank(bool modified) { |
| 568 if (!doomed_) { | 551 if (!doomed_) { |
| 569 // Everything is handled by the backend. | 552 // Everything is handled by the backend. |
| 570 backend_->UpdateRank(&node_, true); | 553 backend_->UpdateRank(&node_, true); |
| 571 return; | 554 return; |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 } | 687 } |
| 705 | 688 |
| 706 if (!MoveToLocalBuffer(index)) | 689 if (!MoveToLocalBuffer(index)) |
| 707 return false; | 690 return false; |
| 708 | 691 |
| 709 // Clear the end of the buffer. | 692 // Clear the end of the buffer. |
| 710 ClearInvalidData(user_buffers_[index].get(), 0, offset + buf_len); | 693 ClearInvalidData(user_buffers_[index].get(), 0, offset + buf_len); |
| 711 return true; | 694 return true; |
| 712 } | 695 } |
| 713 | 696 |
| 714 | |
| 715 // The common scenario is that this is called from the destructor of the entry, | 697 // The common scenario is that this is called from the destructor of the entry, |
| 716 // to write to disk what we have buffered. We don't want to hold the destructor | 698 // to write to disk what we have buffered. We don't want to hold the destructor |
| 717 // until the actual IO finishes, so we'll send an asynchronous write that will | 699 // until the actual IO finishes, so we'll send an asynchronous write that will |
| 718 // free up the memory containing the data. To be consistent, this method always | 700 // free up the memory containing the data. To be consistent, this method always |
| 719 // returns with the buffer freed up (on success). | 701 // returns with the buffer freed up (on success). |
| 720 bool EntryImpl::Flush(int index, int size, bool async) { | 702 bool EntryImpl::Flush(int index, int size, bool async) { |
| 721 Addr address(entry_.Data()->data_addr[index]); | 703 Addr address(entry_.Data()->data_addr[index]); |
| 722 DCHECK(user_buffers_[index].get()); | 704 DCHECK(user_buffers_[index].get()); |
| 723 DCHECK(!address.is_initialized()); | 705 DCHECK(!address.is_initialized()); |
| 724 | 706 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 737 offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; | 719 offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; |
| 738 | 720 |
| 739 // We just told the backend to store len bytes for real. | 721 // We just told the backend to store len bytes for real. |
| 740 DCHECK(len == static_cast<size_t>(unreported_size_[index])); | 722 DCHECK(len == static_cast<size_t>(unreported_size_[index])); |
| 741 backend_->ModifyStorageSize(0, static_cast<int>(len)); | 723 backend_->ModifyStorageSize(0, static_cast<int>(len)); |
| 742 unreported_size_[index] = 0; | 724 unreported_size_[index] = 0; |
| 743 | 725 |
| 744 if (!file) | 726 if (!file) |
| 745 return false; | 727 return false; |
| 746 | 728 |
| 729 // TODO(rvargas): figure out if it's worth to re-enable posting operations. |
| 730 // Right now it is only used from GrowUserBuffer, not the destructor, and |
| 731 // it is not accounted for from the point of view of the total number of |
| 732 // pending operations of the cache. It is also racing with the actual write |
| 733 // on the GrowUserBuffer path because there is no code to exclude the range |
| 734 // that is going to be written. |
| 735 async = false; |
| 747 if (async) { | 736 if (async) { |
| 748 if (!file->PostWrite(user_buffers_[index].get(), len, offset)) | 737 if (!file->PostWrite(user_buffers_[index].get(), len, offset)) |
| 749 return false; | 738 return false; |
| 750 } else { | 739 } else { |
| 751 if (!file->Write(user_buffers_[index].get(), len, offset, NULL, NULL)) | 740 if (!file->Write(user_buffers_[index].get(), len, offset, NULL, NULL)) |
| 752 return false; | 741 return false; |
| 753 user_buffers_[index].reset(NULL); | 742 user_buffers_[index].reset(NULL); |
| 754 } | 743 } |
| 755 | 744 |
| 756 // The buffer is deleted from the PostWrite operation. | 745 // The buffer is deleted from the PostWrite operation. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 771 entry_.address().value(), node_.address().value()); | 760 entry_.address().value(), node_.address().value()); |
| 772 | 761 |
| 773 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], | 762 Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], |
| 774 entry_.Data()->data_addr[1], entry_.Data()->long_key); | 763 entry_.Data()->data_addr[1], entry_.Data()->long_key); |
| 775 | 764 |
| 776 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); | 765 Trace(" doomed: %d 0x%p 0x%x", doomed_, pointer, dirty); |
| 777 } | 766 } |
| 778 | 767 |
| 779 } // namespace disk_cache | 768 } // namespace disk_cache |
| 780 | 769 |
| OLD | NEW |