Skip to content

Commit

Permalink
Prefetch buffer may not contain all of requested data if EOF is hit (#…
Browse files Browse the repository at this point in the history
…13376)

Summary:
There was a stress test that failed at the assertion check for `IsDataBlockInBuffer`.

`IsDataBlockInBuffer` is too strict of a condition if we are trying to read past the end of the file.

This seems to be a bug from the original 2019 commit siying@3737d06: https://github.com/siying/rocksdb/blob/4eb51130917c260f5637731cd77baaa45dfdc5ec/file/file_prefetch_buffer.cc#L130

If the caller tries requesting more bytes than are available, then we still return `n` bytes, even if the buffer really only contains `m < n` bytes.

Pull Request resolved: #13376

Test Plan: I added a unit test which caused the original `IsDataBlockInBuffer ` assertion to fail. I also updated the unit test to check for the result size, which triggered the bug (without this fix) where we return a size of `n` even if less than `n` bytes exist.

Reviewed By: anand1976

Differential Revision: D69269608

Pulled By: archang19

fbshipit-source-id: 1dc0d5930e2b73089850f6e996afbd6192cd5ac8
  • Loading branch information
archang19 authored and facebook-github-bot committed Feb 7, 2025
1 parent 302254d commit c1fb33e
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
8 changes: 5 additions & 3 deletions file/file_prefetch_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -865,10 +865,12 @@ bool FilePrefetchBuffer::TryReadFromCacheUntracked(
if (copy_to_overlap_buffer) {
buf = overlap_buf_;
}
assert(buf->offset_ <= offset);
assert(buf->IsDataBlockInBuffer(offset, n));
assert(buf->IsOffsetInBuffer(offset));
uint64_t offset_in_buffer = offset - buf->offset_;
*result = Slice(buf->buffer_.BufferStart() + offset_in_buffer, n);
assert(offset_in_buffer < buf->CurrentSize());
*result = Slice(
buf->buffer_.BufferStart() + offset_in_buffer,
std::min(n, buf->CurrentSize() - static_cast<size_t>(offset_in_buffer)));
if (prefetched) {
readahead_size_ = std::min(max_readahead_size_, readahead_size_ * 2);
}
Expand Down
16 changes: 16 additions & 0 deletions file/prefetch_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3317,25 +3317,39 @@ TEST_F(FilePrefetchBufferTest, ForCompaction) {
ASSERT_TRUE(fpb.TryReadFromCache(IOOptions(), r.get(), 0 /* offset */,
3000 /* n */, &result, &s, true));
ASSERT_EQ(s, Status::OK());
ASSERT_EQ(result.size(), 3000);
ASSERT_EQ(strncmp(result.data(), content.substr(0, 3000).c_str(), 3000), 0);

ASSERT_TRUE(fpb.TryReadFromCache(IOOptions(), r.get(), 3000 /* offset */,
10000 /* n */, &result, &s, true));
ASSERT_EQ(s, Status::OK());
ASSERT_EQ(result.size(), 10000);
ASSERT_EQ(strncmp(result.data(), content.substr(3000, 10000).c_str(), 10000),
0);

ASSERT_TRUE(fpb.TryReadFromCache(IOOptions(), r.get(), 15000 /* offset */,
4096 /* n */, &result, &s, true));
ASSERT_EQ(s, Status::OK());
ASSERT_EQ(result.size(), 4096);
ASSERT_EQ(strncmp(result.data(), content.substr(15000, 4096).c_str(), 4096),
0);

ASSERT_TRUE(fpb.TryReadFromCache(IOOptions(), r.get(), 40000 /* offset */,
20000 /* n */, &result, &s, true));
ASSERT_EQ(s, Status::OK());
ASSERT_EQ(result.size(), 20000);
ASSERT_EQ(strncmp(result.data(), content.substr(40000, 20000).c_str(), 20000),
0);

// Try reading past end of file
ASSERT_TRUE(fpb.TryReadFromCache(IOOptions(), r.get(), 60000 /* offset */,
10000 /* n */, &result, &s, true));
ASSERT_EQ(s, Status::OK());
ASSERT_EQ(result.size(), 64 * 1024 - 60000);
ASSERT_EQ(
strncmp(result.data(), content.substr(60000, 64 * 1024 - 60000).c_str(),
64 * 1024 - 60000),
0);
}

class FSBufferPrefetchTest
Expand Down Expand Up @@ -3858,6 +3872,8 @@ TEST_P(FSBufferPrefetchTest, FSBufferPrefetchRandomized) {
}
ASSERT_TRUE(could_read_from_cache);
ASSERT_EQ(s, Status::OK());
ASSERT_EQ(result.size(),
std::min(len, content.size() - static_cast<size_t>(offset)));
ASSERT_EQ(strncmp(result.data(),
content.substr(offset, offset + len).c_str(), len),
0);
Expand Down

0 comments on commit c1fb33e

Please sign in to comment.