Index: net/disk_cache/blockfile/sparse_control.cc |
diff --git a/net/disk_cache/blockfile/sparse_control.cc b/net/disk_cache/blockfile/sparse_control.cc |
index 30ea836fc7f9d1af45debec8dd245245bdb9e7de..e5096dc991d88d18da546b76cc41d2b4020c7dfc 100644 |
--- a/net/disk_cache/blockfile/sparse_control.cc |
+++ b/net/disk_cache/blockfile/sparse_control.cc |
@@ -483,7 +483,7 @@ bool SparseControl::OpenChild() { |
return KillChildAndContinue(key, false); |
if (child_data_.header.last_block_len < 0 || |
- child_data_.header.last_block_len > kBlockSize) { |
+ child_data_.header.last_block_len >= kBlockSize) { |
// Make sure these values are always within range. |
child_data_.header.last_block_len = 0; |
child_data_.header.last_block = -1; |
@@ -590,7 +590,7 @@ bool SparseControl::VerifyRange() { |
if (child_map_.FindNextBit(&start, last_bit, false)) { |
// Something is not here. |
DCHECK_GE(child_data_.header.last_block_len, 0); |
- DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize); |
+ DCHECK_LT(child_data_.header.last_block_len, kBlockSize); |
int partial_block_len = PartialBlockLength(start); |
if (start == child_offset_ >> 10) { |
// It looks like we don't have anything. |
@@ -615,7 +615,7 @@ void SparseControl::UpdateRange(int result) { |
return; |
DCHECK_GE(child_data_.header.last_block_len, 0); |
- DCHECK_LT(child_data_.header.last_block_len, kMaxEntrySize); |
+ DCHECK_LT(child_data_.header.last_block_len, kBlockSize); |
// Write the bitmap. |
int first_bit = child_offset_ >> 10; |
@@ -651,11 +651,6 @@ int SparseControl::PartialBlockLength(int block_index) const { |
if (block_index == child_data_.header.last_block) |
return child_data_.header.last_block_len; |
- // This may be the last stored index. |
- int entry_len = child_->GetDataSize(kSparseData); |
- if (block_index == entry_len >> 10) |
- return entry_len & (kBlockSize - 1); |
- |
// This is really empty. |
return 0; |
} |
@@ -769,27 +764,49 @@ int SparseControl::DoGetAvailableRange() { |
if (!child_) |
return child_len_; // Move on to the next child. |
- // Check that there are no holes in this range. |
- int last_bit = (child_offset_ + child_len_ + 1023) >> 10; |
+ // Bits on the bitmap should only be set when the corresponding block was |
+ // fully written (it's really being used). If a block is partially used, it |
+ // has to start with valid data, the length of the valid data is saved in |
+ // |header.last_block_len| and the block itself should match |
+ // |header.last_block|. |
+ // |
+ // In other words, (|header.last_block| + |header.last_block_len|) is the |
+ // offset where the last write ended, and data in that block (which is not |
+ // marked as used because it is not full) will only be reused if the next |
+ // write continues at that point. |
+ // |
+ // This code has to find if there is any data between child_offset_ and |
+ // child_offset_ + child_len_. |
+ int last_bit = (child_offset_ + child_len_ + kBlockSize - 1) >> 10; |
int start = child_offset_ >> 10; |
int partial_start_bytes = PartialBlockLength(start); |
int found = start; |
int bits_found = child_map_.FindBits(&found, last_bit, true); |
+ bool is_last_block_in_range = start < child_data_.header.last_block && |
+ child_data_.header.last_block < last_bit; |
- // We don't care if there is a partial block in the middle of the range. |
int block_offset = child_offset_ & (kBlockSize - 1); |
- if (!bits_found && partial_start_bytes <= block_offset) |
- return child_len_; |
+ if (!bits_found && partial_start_bytes <= block_offset) { |
+ if (!is_last_block_in_range) |
+ return child_len_; |
+ found = last_bit - 1; // There are some bytes here. |
+ } |
// We are done. Just break the loop and reset result_ to our real result. |
range_found_ = true; |
- // found now points to the first 1. Lets see if we have zeros before it. |
- int empty_start = std::max((found << 10) - child_offset_, 0); |
- |
int bytes_found = bits_found << 10; |
bytes_found += PartialBlockLength(found + bits_found); |
+ // found now points to the first bytes. Lets see if we have data before it. |
+ int empty_start = std::max((found << 10) - child_offset_, 0); |
+ if (empty_start >= child_len_) |
+ return child_len_; |
+ |
+ // At this point we have bytes_found stored after (found << 10), and we want |
+ // child_len_ bytes after child_offset_. The first empty_start bytes after |
+ // child_offset_ are invalid. |
+ |
if (start == found) |
bytes_found -= block_offset; |
@@ -798,7 +815,7 @@ int SparseControl::DoGetAvailableRange() { |
// query that we have to subtract from the range that we searched. |
result_ = std::min(bytes_found, child_len_ - empty_start); |
- if (!bits_found) { |
+ if (partial_start_bytes) { |
result_ = std::min(partial_start_bytes - block_offset, child_len_); |
empty_start = 0; |
} |