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 |