| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/blockfile/sparse_control.h" | 5 #include "net/disk_cache/blockfile/sparse_control.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/format_macros.h" | 8 #include "base/format_macros.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 int rv = child_->ReadData(kSparseIndex, 0, buf.get(), sizeof(child_data_), | 476 int rv = child_->ReadData(kSparseIndex, 0, buf.get(), sizeof(child_data_), |
| 477 CompletionCallback()); | 477 CompletionCallback()); |
| 478 if (rv != sizeof(child_data_)) | 478 if (rv != sizeof(child_data_)) |
| 479 return KillChildAndContinue(key, true); // This is a fatal failure. | 479 return KillChildAndContinue(key, true); // This is a fatal failure. |
| 480 | 480 |
| 481 if (child_data_.header.signature != sparse_header_.signature || | 481 if (child_data_.header.signature != sparse_header_.signature || |
| 482 child_data_.header.magic != kIndexMagic) | 482 child_data_.header.magic != kIndexMagic) |
| 483 return KillChildAndContinue(key, false); | 483 return KillChildAndContinue(key, false); |
| 484 | 484 |
| 485 if (child_data_.header.last_block_len < 0 || | 485 if (child_data_.header.last_block_len < 0 || |
| 486 child_data_.header.last_block_len > kBlockSize) { | 486 child_data_.header.last_block_len >= kBlockSize) { |
| 487 // Make sure these values are always within range. | 487 // Make sure these values are always within range. |
| 488 child_data_.header.last_block_len = 0; | 488 child_data_.header.last_block_len = 0; |
| 489 child_data_.header.last_block = -1; | 489 child_data_.header.last_block = -1; |
| 490 } | 490 } |
| 491 | 491 |
| 492 return true; | 492 return true; |
| 493 } | 493 } |
| 494 | 494 |
| 495 void SparseControl::CloseChild() { | 495 void SparseControl::CloseChild() { |
| 496 scoped_refptr<net::WrappedIOBuffer> buf( | 496 scoped_refptr<net::WrappedIOBuffer> buf( |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 // We can write to (or get info from) anywhere in this child. | 583 // We can write to (or get info from) anywhere in this child. |
| 584 if (operation_ != kReadOperation) | 584 if (operation_ != kReadOperation) |
| 585 return true; | 585 return true; |
| 586 | 586 |
| 587 // Check that there are no holes in this range. | 587 // Check that there are no holes in this range. |
| 588 int last_bit = (child_offset_ + child_len_ + 1023) >> 10; | 588 int last_bit = (child_offset_ + child_len_ + 1023) >> 10; |
| 589 int start = child_offset_ >> 10; | 589 int start = child_offset_ >> 10; |
| 590 if (child_map_.FindNextBit(&start, last_bit, false)) { | 590 if (child_map_.FindNextBit(&start, last_bit, false)) { |
| 591 // Something is not here. | 591 // Something is not here. |
| 592 DCHECK_GE(child_data_.header.last_block_len, 0); | 592 DCHECK_GE(child_data_.header.last_block_len, 0); |
| 593 DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize); | 593 DCHECK_LT(child_data_.header.last_block_len, kBlockSize); |
| 594 int partial_block_len = PartialBlockLength(start); | 594 int partial_block_len = PartialBlockLength(start); |
| 595 if (start == child_offset_ >> 10) { | 595 if (start == child_offset_ >> 10) { |
| 596 // It looks like we don't have anything. | 596 // It looks like we don't have anything. |
| 597 if (partial_block_len <= (child_offset_ & (kBlockSize - 1))) | 597 if (partial_block_len <= (child_offset_ & (kBlockSize - 1))) |
| 598 return false; | 598 return false; |
| 599 } | 599 } |
| 600 | 600 |
| 601 // We have the first part. | 601 // We have the first part. |
| 602 child_len_ = (start << 10) - child_offset_; | 602 child_len_ = (start << 10) - child_offset_; |
| 603 if (partial_block_len) { | 603 if (partial_block_len) { |
| 604 // We may have a few extra bytes. | 604 // We may have a few extra bytes. |
| 605 child_len_ = std::min(child_len_ + partial_block_len, buf_len_); | 605 child_len_ = std::min(child_len_ + partial_block_len, buf_len_); |
| 606 } | 606 } |
| 607 // There is no need to read more after this one. | 607 // There is no need to read more after this one. |
| 608 buf_len_ = child_len_; | 608 buf_len_ = child_len_; |
| 609 } | 609 } |
| 610 return true; | 610 return true; |
| 611 } | 611 } |
| 612 | 612 |
| 613 void SparseControl::UpdateRange(int result) { | 613 void SparseControl::UpdateRange(int result) { |
| 614 if (result <= 0 || operation_ != kWriteOperation) | 614 if (result <= 0 || operation_ != kWriteOperation) |
| 615 return; | 615 return; |
| 616 | 616 |
| 617 DCHECK_GE(child_data_.header.last_block_len, 0); | 617 DCHECK_GE(child_data_.header.last_block_len, 0); |
| 618 DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize); | 618 DCHECK_LT(child_data_.header.last_block_len, kBlockSize); |
| 619 | 619 |
| 620 // Write the bitmap. | 620 // Write the bitmap. |
| 621 int first_bit = child_offset_ >> 10; | 621 int first_bit = child_offset_ >> 10; |
| 622 int block_offset = child_offset_ & (kBlockSize - 1); | 622 int block_offset = child_offset_ & (kBlockSize - 1); |
| 623 if (block_offset && (child_data_.header.last_block != first_bit || | 623 if (block_offset && (child_data_.header.last_block != first_bit || |
| 624 child_data_.header.last_block_len < block_offset)) { | 624 child_data_.header.last_block_len < block_offset)) { |
| 625 // The first block is not completely filled; ignore it. | 625 // The first block is not completely filled; ignore it. |
| 626 first_bit++; | 626 first_bit++; |
| 627 } | 627 } |
| 628 | 628 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 644 child_data_.header.last_block = -1; | 644 child_data_.header.last_block = -1; |
| 645 } | 645 } |
| 646 | 646 |
| 647 child_map_.SetRange(first_bit, last_bit, true); | 647 child_map_.SetRange(first_bit, last_bit, true); |
| 648 } | 648 } |
| 649 | 649 |
| 650 int SparseControl::PartialBlockLength(int block_index) const { | 650 int SparseControl::PartialBlockLength(int block_index) const { |
| 651 if (block_index == child_data_.header.last_block) | 651 if (block_index == child_data_.header.last_block) |
| 652 return child_data_.header.last_block_len; | 652 return child_data_.header.last_block_len; |
| 653 | 653 |
| 654 // This may be the last stored index. | |
| 655 int entry_len = child_->GetDataSize(kSparseData); | |
| 656 if (block_index == entry_len >> 10) | |
| 657 return entry_len & (kBlockSize - 1); | |
| 658 | |
| 659 // This is really empty. | 654 // This is really empty. |
| 660 return 0; | 655 return 0; |
| 661 } | 656 } |
| 662 | 657 |
| 663 void SparseControl::InitChildData() { | 658 void SparseControl::InitChildData() { |
| 664 // We know the real type of child_. | 659 // We know the real type of child_. |
| 665 EntryImpl* child = static_cast<EntryImpl*>(child_); | 660 EntryImpl* child = static_cast<EntryImpl*>(child_); |
| 666 child->SetEntryFlags(CHILD_ENTRY); | 661 child->SetEntryFlags(CHILD_ENTRY); |
| 667 | 662 |
| 668 memset(&child_data_, 0, sizeof(child_data_)); | 663 memset(&child_data_, 0, sizeof(child_data_)); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 return false; | 757 return false; |
| 763 | 758 |
| 764 DoChildIOCompleted(rv); | 759 DoChildIOCompleted(rv); |
| 765 return true; | 760 return true; |
| 766 } | 761 } |
| 767 | 762 |
| 768 int SparseControl::DoGetAvailableRange() { | 763 int SparseControl::DoGetAvailableRange() { |
| 769 if (!child_) | 764 if (!child_) |
| 770 return child_len_; // Move on to the next child. | 765 return child_len_; // Move on to the next child. |
| 771 | 766 |
| 772 // Check that there are no holes in this range. | 767 // Bits on the bitmap should only be set when the corresponding block was |
| 773 int last_bit = (child_offset_ + child_len_ + 1023) >> 10; | 768 // fully written (it's really being used). If a block is partially used, it |
| 769 // has to start with valid data, the length of the valid data is saved in |
| 770 // |header.last_block_len| and the block itself should match |
| 771 // |header.last_block|. |
| 772 // |
| 773 // In other words, (|header.last_block| + |header.last_block_len|) is the |
| 774 // offset where the last write ended, and data in that block (which is not |
| 775 // marked as used because it is not full) will only be reused if the next |
| 776 // write continues at that point. |
| 777 // |
| 778 // This code has to find if there is any data between child_offset_ and |
| 779 // child_offset_ + child_len_. |
| 780 int last_bit = (child_offset_ + child_len_ + kBlockSize - 1) >> 10; |
| 774 int start = child_offset_ >> 10; | 781 int start = child_offset_ >> 10; |
| 775 int partial_start_bytes = PartialBlockLength(start); | 782 int partial_start_bytes = PartialBlockLength(start); |
| 776 int found = start; | 783 int found = start; |
| 777 int bits_found = child_map_.FindBits(&found, last_bit, true); | 784 int bits_found = child_map_.FindBits(&found, last_bit, true); |
| 785 bool is_last_block_in_range = start < child_data_.header.last_block && |
| 786 child_data_.header.last_block < last_bit; |
| 778 | 787 |
| 779 // We don't care if there is a partial block in the middle of the range. | |
| 780 int block_offset = child_offset_ & (kBlockSize - 1); | 788 int block_offset = child_offset_ & (kBlockSize - 1); |
| 781 if (!bits_found && partial_start_bytes <= block_offset) | 789 if (!bits_found && partial_start_bytes <= block_offset) { |
| 782 return child_len_; | 790 if (!is_last_block_in_range) |
| 791 return child_len_; |
| 792 found = last_bit - 1; // There are some bytes here. |
| 793 } |
| 783 | 794 |
| 784 // We are done. Just break the loop and reset result_ to our real result. | 795 // We are done. Just break the loop and reset result_ to our real result. |
| 785 range_found_ = true; | 796 range_found_ = true; |
| 786 | 797 |
| 787 // found now points to the first 1. Lets see if we have zeros before it. | |
| 788 int empty_start = std::max((found << 10) - child_offset_, 0); | |
| 789 | |
| 790 int bytes_found = bits_found << 10; | 798 int bytes_found = bits_found << 10; |
| 791 bytes_found += PartialBlockLength(found + bits_found); | 799 bytes_found += PartialBlockLength(found + bits_found); |
| 792 | 800 |
| 801 // found now points to the first bytes. Lets see if we have data before it. |
| 802 int empty_start = std::max((found << 10) - child_offset_, 0); |
| 803 if (empty_start >= child_len_) |
| 804 return child_len_; |
| 805 |
| 806 // At this point we have bytes_found stored after (found << 10), and we want |
| 807 // child_len_ bytes after child_offset_. The first empty_start bytes after |
| 808 // child_offset_ are invalid. |
| 809 |
| 793 if (start == found) | 810 if (start == found) |
| 794 bytes_found -= block_offset; | 811 bytes_found -= block_offset; |
| 795 | 812 |
| 796 // If the user is searching past the end of this child, bits_found is the | 813 // If the user is searching past the end of this child, bits_found is the |
| 797 // right result; otherwise, we have some empty space at the start of this | 814 // right result; otherwise, we have some empty space at the start of this |
| 798 // query that we have to subtract from the range that we searched. | 815 // query that we have to subtract from the range that we searched. |
| 799 result_ = std::min(bytes_found, child_len_ - empty_start); | 816 result_ = std::min(bytes_found, child_len_ - empty_start); |
| 800 | 817 |
| 801 if (!bits_found) { | 818 if (partial_start_bytes) { |
| 802 result_ = std::min(partial_start_bytes - block_offset, child_len_); | 819 result_ = std::min(partial_start_bytes - block_offset, child_len_); |
| 803 empty_start = 0; | 820 empty_start = 0; |
| 804 } | 821 } |
| 805 | 822 |
| 806 // Only update offset_ when this query found zeros at the start. | 823 // Only update offset_ when this query found zeros at the start. |
| 807 if (empty_start) | 824 if (empty_start) |
| 808 offset_ += empty_start; | 825 offset_ += empty_start; |
| 809 | 826 |
| 810 // This will actually break the loop. | 827 // This will actually break the loop. |
| 811 buf_len_ = 0; | 828 buf_len_ = 0; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 CompletionCallback cb = abort_callbacks_[i]; | 894 CompletionCallback cb = abort_callbacks_[i]; |
| 878 if (i == abort_callbacks_.size() - 1) | 895 if (i == abort_callbacks_.size() - 1) |
| 879 abort_callbacks_.clear(); | 896 abort_callbacks_.clear(); |
| 880 | 897 |
| 881 entry_->Release(); // Don't touch object after this line. | 898 entry_->Release(); // Don't touch object after this line. |
| 882 cb.Run(net::OK); | 899 cb.Run(net::OK); |
| 883 } | 900 } |
| 884 } | 901 } |
| 885 | 902 |
| 886 } // namespace disk_cache | 903 } // namespace disk_cache |
| OLD | NEW |