|
4 | 4 | // (found in the LICENSE.Apache file in the root directory).
|
5 | 5 |
|
6 | 6 | #include "db/db_test_util.h"
|
| 7 | +#include "file/file_prefetch_buffer.h" |
| 8 | +#include "file/file_util.h" |
| 9 | +#include "rocksdb/file_system.h" |
7 | 10 | #include "test_util/sync_point.h"
|
8 | 11 | #ifdef GFLAGS
|
9 | 12 | #include "tools/io_tracer_parser_tool.h"
|
10 | 13 | #endif
|
| 14 | +#include "util/random.h" |
11 | 15 |
|
12 | 16 | namespace ROCKSDB_NAMESPACE {
|
13 | 17 |
|
@@ -2023,6 +2027,77 @@ TEST_P(PrefetchTest, TraceReadAsyncWithCallbackWrapper) {
|
2023 | 2027 | Close();
|
2024 | 2028 | }
|
2025 | 2029 | #endif // GFLAGS
|
| 2030 | + |
| 2031 | +class FilePrefetchBufferTest : public testing::Test { |
| 2032 | + public: |
| 2033 | + void SetUp() override { |
| 2034 | + SetupSyncPointsToMockDirectIO(); |
| 2035 | + env_ = Env::Default(); |
| 2036 | + fs_ = FileSystem::Default(); |
| 2037 | + test_dir_ = test::PerThreadDBPath("file_prefetch_buffer_test"); |
| 2038 | + ASSERT_OK(fs_->CreateDir(test_dir_, IOOptions(), nullptr)); |
| 2039 | + } |
| 2040 | + |
| 2041 | + void TearDown() override { EXPECT_OK(DestroyDir(env_, test_dir_)); } |
| 2042 | + |
| 2043 | + void Write(const std::string& fname, const std::string& content) { |
| 2044 | + std::unique_ptr<FSWritableFile> f; |
| 2045 | + ASSERT_OK(fs_->NewWritableFile(Path(fname), FileOptions(), &f, nullptr)); |
| 2046 | + ASSERT_OK(f->Append(content, IOOptions(), nullptr)); |
| 2047 | + ASSERT_OK(f->Close(IOOptions(), nullptr)); |
| 2048 | + } |
| 2049 | + |
| 2050 | + void Read(const std::string& fname, const FileOptions& opts, |
| 2051 | + std::unique_ptr<RandomAccessFileReader>* reader) { |
| 2052 | + std::string fpath = Path(fname); |
| 2053 | + std::unique_ptr<FSRandomAccessFile> f; |
| 2054 | + ASSERT_OK(fs_->NewRandomAccessFile(fpath, opts, &f, nullptr)); |
| 2055 | + reader->reset(new RandomAccessFileReader(std::move(f), fpath, |
| 2056 | + env_->GetSystemClock().get())); |
| 2057 | + } |
| 2058 | + |
| 2059 | + void AssertResult(const std::string& content, |
| 2060 | + const std::vector<FSReadRequest>& reqs) { |
| 2061 | + for (const auto& r : reqs) { |
| 2062 | + ASSERT_OK(r.status); |
| 2063 | + ASSERT_EQ(r.len, r.result.size()); |
| 2064 | + ASSERT_EQ(content.substr(r.offset, r.len), r.result.ToString()); |
| 2065 | + } |
| 2066 | + } |
| 2067 | + |
| 2068 | + FileSystem* fs() { return fs_.get(); } |
| 2069 | + |
| 2070 | + private: |
| 2071 | + Env* env_; |
| 2072 | + std::shared_ptr<FileSystem> fs_; |
| 2073 | + std::string test_dir_; |
| 2074 | + |
| 2075 | + std::string Path(const std::string& fname) { return test_dir_ + "/" + fname; } |
| 2076 | +}; |
| 2077 | + |
| 2078 | +TEST_F(FilePrefetchBufferTest, SeekWithBlockCacheHit) { |
| 2079 | + std::string fname = "seek-with-block-cache-hit"; |
| 2080 | + Random rand(0); |
| 2081 | + std::string content = rand.RandomString(32768); |
| 2082 | + Write(fname, content); |
| 2083 | + |
| 2084 | + FileOptions opts; |
| 2085 | + std::unique_ptr<RandomAccessFileReader> r; |
| 2086 | + Read(fname, opts, &r); |
| 2087 | + |
| 2088 | + FilePrefetchBuffer fpb(16384, 16384, true, false, false, 0, 0, fs()); |
| 2089 | + Slice result; |
| 2090 | + // Simulate a seek of 4096 bytes at offset 0. Due to the readahead settings, |
| 2091 | + // it will do two reads of 4096+8192 and 8192 |
| 2092 | + Status s = fpb.PrefetchAsync(IOOptions(), r.get(), 0, 4096, &result); |
| 2093 | + ASSERT_EQ(s, Status::TryAgain()); |
| 2094 | + // Simulate a block cache hit |
| 2095 | + fpb.UpdateReadPattern(0, 4096, false); |
| 2096 | + // Now read some data that straddles the two prefetch buffers - offset 8192 to |
| 2097 | + // 16384 |
| 2098 | + ASSERT_TRUE(fpb.TryReadFromCacheAsync(IOOptions(), r.get(), 8192, 8192, |
| 2099 | + &result, &s, Env::IOPriority::IO_LOW)); |
| 2100 | +} |
2026 | 2101 | #endif // ROCKSDB_LITE
|
2027 | 2102 | } // namespace ROCKSDB_NAMESPACE
|
2028 | 2103 |
|
|
0 commit comments