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 |