1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 // 6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 7 // Use of this source code is governed by a BSD-style license that can be 8 // found in the LICENSE file. See the AUTHORS file for names of contributors. 9 10 #pragma once 11 #include <atomic> 12 #include <sstream> 13 #include <string> 14 15 #include "file/random_access_file_reader.h" 16 #include "port/port.h" 17 #include "rocksdb/env.h" 18 #include "rocksdb/options.h" 19 #include "util/aligned_buffer.h" 20 21 namespace ROCKSDB_NAMESPACE { 22 23 // FilePrefetchBuffer is a smart buffer to store and read data from a file. 24 class FilePrefetchBuffer { 25 public: 26 static const int kMinNumFileReadsToStartAutoReadahead = 2; 27 // Constructor. 28 // 29 // All arguments are optional. 30 // file_reader : the file reader to use. Can be a nullptr. 31 // readahead_size : the initial readahead size. 32 // max_readahead_size : the maximum readahead size. 33 // If max_readahead_size > readahead_size, the readahead size will be 34 // doubled on every IO until max_readahead_size is hit. 35 // Typically this is set as a multiple of readahead_size. 36 // max_readahead_size should be greater than equal to readahead_size. 37 // enable : controls whether reading from the buffer is enabled. 38 // If false, TryReadFromCache() always return false, and we only take stats 39 // for the minimum offset if track_min_offset = true. 40 // track_min_offset : Track the minimum offset ever read and collect stats on 41 // it. Used for adaptable readahead of the file footer/metadata. 42 // implicit_auto_readahead : Readahead is enabled implicitly by rocksdb after 43 // doing sequential scans for two times. 44 // 45 // Automatic readhead is enabled for a file if file_reader, readahead_size, 46 // and max_readahead_size are passed in. 47 // If file_reader is a nullptr, setting readahead_size and max_readahead_size 48 // does not make any sense. So it does nothing. 49 // A user can construct a FilePrefetchBuffer without any arguments, but use 50 // `Prefetch` to load data into the buffer. 51 FilePrefetchBuffer(RandomAccessFileReader* file_reader = nullptr, 52 size_t readahead_size = 0, size_t max_readahead_size = 0, 53 bool enable = true, bool track_min_offset = false, 54 bool implicit_auto_readahead = false) 55 : buffer_offset_(0), 56 file_reader_(file_reader), 57 readahead_size_(readahead_size), 58 max_readahead_size_(max_readahead_size), 59 initial_readahead_size_(readahead_size), 60 min_offset_read_(port::kMaxSizet), 61 enable_(enable), 62 track_min_offset_(track_min_offset), 63 implicit_auto_readahead_(implicit_auto_readahead), 64 prev_offset_(0), 65 prev_len_(0), 66 num_file_reads_(kMinNumFileReadsToStartAutoReadahead + 1) {} 67 68 // Load data into the buffer from a file. 69 // reader : the file reader. 70 // offset : the file offset to start reading from. 71 // n : the number of bytes to read. 72 // for_compaction : if prefetch is done for compaction read. 73 Status Prefetch(const IOOptions& opts, RandomAccessFileReader* reader, 74 uint64_t offset, size_t n, bool for_compaction = false); 75 76 // Tries returning the data for a file raed from this buffer, if that data is 77 // in the buffer. 78 // It handles tracking the minimum read offset if track_min_offset = true. 79 // It also does the exponential readahead when readahead_size is set as part 80 // of the constructor. 81 // 82 // offset : the file offset. 83 // n : the number of bytes. 84 // result : output buffer to put the data into. 85 // for_compaction : if cache read is done for compaction read. 86 bool TryReadFromCache(const IOOptions& opts, uint64_t offset, size_t n, 87 Slice* result, Status* s, bool for_compaction = false); 88 89 // The minimum `offset` ever passed to TryReadFromCache(). This will nly be 90 // tracked if track_min_offset = true. min_offset_read()91 size_t min_offset_read() const { return min_offset_read_; } 92 UpdateReadPattern(const size_t & offset,const size_t & len)93 void UpdateReadPattern(const size_t& offset, const size_t& len) { 94 prev_offset_ = offset; 95 prev_len_ = len; 96 } 97 IsBlockSequential(const size_t & offset)98 bool IsBlockSequential(const size_t& offset) { 99 return (prev_len_ == 0 || (prev_offset_ + prev_len_ == offset)); 100 } 101 ResetValues()102 void ResetValues() { 103 num_file_reads_ = 1; 104 readahead_size_ = initial_readahead_size_; 105 } 106 107 private: 108 AlignedBuffer buffer_; 109 uint64_t buffer_offset_; 110 RandomAccessFileReader* file_reader_; 111 size_t readahead_size_; 112 size_t max_readahead_size_; 113 size_t initial_readahead_size_; 114 // The minimum `offset` ever passed to TryReadFromCache(). 115 size_t min_offset_read_; 116 // if false, TryReadFromCache() always return false, and we only take stats 117 // for track_min_offset_ if track_min_offset_ = true 118 bool enable_; 119 // If true, track minimum `offset` ever passed to TryReadFromCache(), which 120 // can be fetched from min_offset_read(). 121 bool track_min_offset_; 122 123 // implicit_auto_readahead is enabled by rocksdb internally after 2 sequential 124 // IOs. 125 bool implicit_auto_readahead_; 126 size_t prev_offset_; 127 size_t prev_len_; 128 int num_file_reads_; 129 }; 130 } // namespace ROCKSDB_NAMESPACE 131