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 12 #include "db/range_tombstone_fragmenter.h" 13 #include "file/filename.h" 14 #include "table/block_based/block_based_table_factory.h" 15 #include "table/block_based/block_type.h" 16 #include "table/block_based/cachable_entry.h" 17 #include "table/block_based/filter_block.h" 18 #include "table/block_based/uncompression_dict_reader.h" 19 #include "table/table_properties_internal.h" 20 #include "table/table_reader.h" 21 #include "table/two_level_iterator.h" 22 23 #include "trace_replay/block_cache_tracer.h" 24 25 namespace ROCKSDB_NAMESPACE { 26 27 class Cache; 28 class FilterBlockReader; 29 class BlockBasedFilterBlockReader; 30 class FullFilterBlockReader; 31 class Footer; 32 class InternalKeyComparator; 33 class Iterator; 34 class FSRandomAccessFile; 35 class TableCache; 36 class TableReader; 37 class WritableFile; 38 struct BlockBasedTableOptions; 39 struct EnvOptions; 40 struct ReadOptions; 41 class GetContext; 42 43 typedef std::vector<std::pair<std::string, std::string>> KVPairBlock; 44 45 // Reader class for BlockBasedTable format. 46 // For the format of BlockBasedTable refer to 47 // https://github.com/facebook/rocksdb/wiki/Rocksdb-BlockBasedTable-Format. 48 // This is the default table type. Data is chucked into fixed size blocks and 49 // each block in-turn stores entries. When storing data, we can compress and/or 50 // encode data efficiently within a block, which often results in a much smaller 51 // data size compared with the raw data size. As for the record retrieval, we'll 52 // first locate the block where target record may reside, then read the block to 53 // memory, and finally search that record within the block. Of course, to avoid 54 // frequent reads of the same block, we introduced the block cache to keep the 55 // loaded blocks in the memory. 56 class BlockBasedTable : public TableReader { 57 public: 58 static const std::string kFilterBlockPrefix; 59 static const std::string kFullFilterBlockPrefix; 60 static const std::string kPartitionedFilterBlockPrefix; 61 // The longest prefix of the cache key used to identify blocks. 62 // For Posix files the unique ID is three varints. 63 static const size_t kMaxCacheKeyPrefixSize = kMaxVarint64Length * 3 + 1; 64 65 // All the below fields control iterator readahead 66 static const size_t kInitAutoReadaheadSize = 8 * 1024; 67 // Found that 256 KB readahead size provides the best performance, based on 68 // experiments, for auto readahead. Experiment data is in PR #3282. 69 static const size_t kMaxAutoReadaheadSize; 70 static const int kMinNumFileReadsToStartAutoReadahead = 2; 71 72 // Attempt to open the table that is stored in bytes [0..file_size) 73 // of "file", and read the metadata entries necessary to allow 74 // retrieving data from the table. 75 // 76 // If successful, returns ok and sets "*table_reader" to the newly opened 77 // table. The client should delete "*table_reader" when no longer needed. 78 // If there was an error while initializing the table, sets "*table_reader" 79 // to nullptr and returns a non-ok status. 80 // 81 // @param file must remain live while this Table is in use. 82 // @param prefetch_index_and_filter_in_cache can be used to disable 83 // prefetching of 84 // index and filter blocks into block cache at startup 85 // @param skip_filters Disables loading/accessing the filter block. Overrides 86 // prefetch_index_and_filter_in_cache, so filter will be skipped if both 87 // are set. 88 static Status Open(const ImmutableCFOptions& ioptions, 89 const EnvOptions& env_options, 90 const BlockBasedTableOptions& table_options, 91 const InternalKeyComparator& internal_key_comparator, 92 std::unique_ptr<RandomAccessFileReader>&& file, 93 uint64_t file_size, 94 std::unique_ptr<TableReader>* table_reader, 95 const SliceTransform* prefix_extractor = nullptr, 96 bool prefetch_index_and_filter_in_cache = true, 97 bool skip_filters = false, int level = -1, 98 const bool immortal_table = false, 99 const SequenceNumber largest_seqno = 0, 100 TailPrefetchStats* tail_prefetch_stats = nullptr, 101 BlockCacheTracer* const block_cache_tracer = nullptr); 102 103 bool PrefixMayMatch(const Slice& internal_key, 104 const ReadOptions& read_options, 105 const SliceTransform* options_prefix_extractor, 106 const bool need_upper_bound_check, 107 BlockCacheLookupContext* lookup_context) const; 108 109 // Returns a new iterator over the table contents. 110 // The result of NewIterator() is initially invalid (caller must 111 // call one of the Seek methods on the iterator before using it). 112 // @param skip_filters Disables loading/accessing the filter block 113 // compaction_readahead_size: its value will only be used if caller = 114 // kCompaction. 115 InternalIterator* NewIterator(const ReadOptions&, 116 const SliceTransform* prefix_extractor, 117 Arena* arena, bool skip_filters, 118 TableReaderCaller caller, 119 size_t compaction_readahead_size = 0) override; 120 121 FragmentedRangeTombstoneIterator* NewRangeTombstoneIterator( 122 const ReadOptions& read_options) override; 123 124 // @param skip_filters Disables loading/accessing the filter block 125 Status Get(const ReadOptions& readOptions, const Slice& key, 126 GetContext* get_context, const SliceTransform* prefix_extractor, 127 bool skip_filters = false) override; 128 129 void MultiGet(const ReadOptions& readOptions, 130 const MultiGetContext::Range* mget_range, 131 const SliceTransform* prefix_extractor, 132 bool skip_filters = false) override; 133 134 // Pre-fetch the disk blocks that correspond to the key range specified by 135 // (kbegin, kend). The call will return error status in the event of 136 // IO or iteration error. 137 Status Prefetch(const Slice* begin, const Slice* end) override; 138 139 // Given a key, return an approximate byte offset in the file where 140 // the data for that key begins (or would begin if the key were 141 // present in the file). The returned value is in terms of file 142 // bytes, and so includes effects like compression of the underlying data. 143 // E.g., the approximate offset of the last key in the table will 144 // be close to the file length. 145 uint64_t ApproximateOffsetOf(const Slice& key, 146 TableReaderCaller caller) override; 147 148 // Given start and end keys, return the approximate data size in the file 149 // between the keys. The returned value is in terms of file bytes, and so 150 // includes effects like compression of the underlying data. 151 // The start key must not be greater than the end key. 152 uint64_t ApproximateSize(const Slice& start, const Slice& end, 153 TableReaderCaller caller) override; 154 155 bool TEST_BlockInCache(const BlockHandle& handle) const; 156 157 // Returns true if the block for the specified key is in cache. 158 // REQUIRES: key is in this table && block cache enabled 159 bool TEST_KeyInCache(const ReadOptions& options, const Slice& key); 160 161 // Set up the table for Compaction. Might change some parameters with 162 // posix_fadvise 163 void SetupForCompaction() override; 164 165 std::shared_ptr<const TableProperties> GetTableProperties() const override; 166 167 size_t ApproximateMemoryUsage() const override; 168 169 // convert SST file to a human readable form 170 Status DumpTable(WritableFile* out_file) override; 171 172 Status VerifyChecksum(const ReadOptions& readOptions, 173 TableReaderCaller caller) override; 174 175 ~BlockBasedTable(); 176 177 bool TEST_FilterBlockInCache() const; 178 bool TEST_IndexBlockInCache() const; 179 180 // IndexReader is the interface that provides the functionality for index 181 // access. 182 class IndexReader { 183 public: 184 virtual ~IndexReader() = default; 185 186 // Create an iterator for index access. If iter is null, then a new object 187 // is created on the heap, and the callee will have the ownership. 188 // If a non-null iter is passed in, it will be used, and the returned value 189 // is either the same as iter or a new on-heap object that 190 // wraps the passed iter. In the latter case the return value points 191 // to a different object then iter, and the callee has the ownership of the 192 // returned object. 193 virtual InternalIteratorBase<IndexValue>* NewIterator( 194 const ReadOptions& read_options, bool disable_prefix_seek, 195 IndexBlockIter* iter, GetContext* get_context, 196 BlockCacheLookupContext* lookup_context) = 0; 197 198 // Report an approximation of how much memory has been used other than 199 // memory that was allocated in block cache. 200 virtual size_t ApproximateMemoryUsage() const = 0; 201 // Cache the dependencies of the index reader (e.g. the partitions 202 // of a partitioned index). CacheDependencies(bool)203 virtual void CacheDependencies(bool /* pin */) {} 204 }; 205 206 class IndexReaderCommon; 207 208 static Slice GetCacheKey(const char* cache_key_prefix, 209 size_t cache_key_prefix_size, 210 const BlockHandle& handle, char* cache_key); 211 212 // Retrieve all key value pairs from data blocks in the table. 213 // The key retrieved are internal keys. 214 Status GetKVPairsFromDataBlocks(std::vector<KVPairBlock>* kv_pair_blocks); 215 216 struct Rep; 217 get_rep()218 Rep* get_rep() { return rep_; } get_rep()219 const Rep* get_rep() const { return rep_; } 220 221 // input_iter: if it is not null, update this one and return it as Iterator 222 template <typename TBlockIter> 223 TBlockIter* NewDataBlockIterator( 224 const ReadOptions& ro, const BlockHandle& block_handle, 225 TBlockIter* input_iter, BlockType block_type, GetContext* get_context, 226 BlockCacheLookupContext* lookup_context, Status s, 227 FilePrefetchBuffer* prefetch_buffer, bool for_compaction = false) const; 228 229 // input_iter: if it is not null, update this one and return it as Iterator 230 template <typename TBlockIter> 231 TBlockIter* NewDataBlockIterator(const ReadOptions& ro, 232 CachableEntry<Block>& block, 233 TBlockIter* input_iter, Status s) const; 234 235 class PartitionedIndexIteratorState; 236 237 template <typename TBlocklike> 238 friend class FilterBlockReaderCommon; 239 240 friend class PartitionIndexReader; 241 242 friend class UncompressionDictReader; 243 244 protected: 245 Rep* rep_; BlockBasedTable(Rep * rep,BlockCacheTracer * const block_cache_tracer)246 explicit BlockBasedTable(Rep* rep, BlockCacheTracer* const block_cache_tracer) 247 : rep_(rep), block_cache_tracer_(block_cache_tracer) {} 248 // No copying allowed 249 explicit BlockBasedTable(const TableReader&) = delete; 250 void operator=(const TableReader&) = delete; 251 252 private: 253 friend class MockedBlockBasedTable; 254 static std::atomic<uint64_t> next_cache_key_id_; 255 BlockCacheTracer* const block_cache_tracer_; 256 257 void UpdateCacheHitMetrics(BlockType block_type, GetContext* get_context, 258 size_t usage) const; 259 void UpdateCacheMissMetrics(BlockType block_type, 260 GetContext* get_context) const; 261 void UpdateCacheInsertionMetrics(BlockType block_type, 262 GetContext* get_context, size_t usage) const; 263 Cache::Handle* GetEntryFromCache(Cache* block_cache, const Slice& key, 264 BlockType block_type, 265 GetContext* get_context) const; 266 267 // Either Block::NewDataIterator() or Block::NewIndexIterator(). 268 template <typename TBlockIter> 269 static TBlockIter* InitBlockIterator(const Rep* rep, Block* block, 270 BlockType block_type, 271 TBlockIter* input_iter, 272 bool block_contents_pinned); 273 274 // If block cache enabled (compressed or uncompressed), looks for the block 275 // identified by handle in (1) uncompressed cache, (2) compressed cache, and 276 // then (3) file. If found, inserts into the cache(s) that were searched 277 // unsuccessfully (e.g., if found in file, will add to both uncompressed and 278 // compressed caches if they're enabled). 279 // 280 // @param block_entry value is set to the uncompressed block if found. If 281 // in uncompressed block cache, also sets cache_handle to reference that 282 // block. 283 template <typename TBlocklike> 284 Status MaybeReadBlockAndLoadToCache( 285 FilePrefetchBuffer* prefetch_buffer, const ReadOptions& ro, 286 const BlockHandle& handle, const UncompressionDict& uncompression_dict, 287 CachableEntry<TBlocklike>* block_entry, BlockType block_type, 288 GetContext* get_context, BlockCacheLookupContext* lookup_context, 289 BlockContents* contents) const; 290 291 // Similar to the above, with one crucial difference: it will retrieve the 292 // block from the file even if there are no caches configured (assuming the 293 // read options allow I/O). 294 template <typename TBlocklike> 295 Status RetrieveBlock(FilePrefetchBuffer* prefetch_buffer, 296 const ReadOptions& ro, const BlockHandle& handle, 297 const UncompressionDict& uncompression_dict, 298 CachableEntry<TBlocklike>* block_entry, 299 BlockType block_type, GetContext* get_context, 300 BlockCacheLookupContext* lookup_context, 301 bool for_compaction, bool use_cache) const; 302 303 void RetrieveMultipleBlocks( 304 const ReadOptions& options, const MultiGetRange* batch, 305 const autovector<BlockHandle, MultiGetContext::MAX_BATCH_SIZE>* handles, 306 autovector<Status, MultiGetContext::MAX_BATCH_SIZE>* statuses, 307 autovector<CachableEntry<Block>, MultiGetContext::MAX_BATCH_SIZE>* 308 results, 309 char* scratch, const UncompressionDict& uncompression_dict) const; 310 311 // Get the iterator from the index reader. 312 // 313 // If input_iter is not set, return a new Iterator. 314 // If input_iter is set, try to update it and return it as Iterator. 315 // However note that in some cases the returned iterator may be different 316 // from input_iter. In such case the returned iterator should be freed. 317 // 318 // Note: ErrorIterator with Status::Incomplete shall be returned if all the 319 // following conditions are met: 320 // 1. We enabled table_options.cache_index_and_filter_blocks. 321 // 2. index is not present in block cache. 322 // 3. We disallowed any io to be performed, that is, read_options == 323 // kBlockCacheTier 324 InternalIteratorBase<IndexValue>* NewIndexIterator( 325 const ReadOptions& read_options, bool need_upper_bound_check, 326 IndexBlockIter* input_iter, GetContext* get_context, 327 BlockCacheLookupContext* lookup_context) const; 328 329 // Read block cache from block caches (if set): block_cache and 330 // block_cache_compressed. 331 // On success, Status::OK with be returned and @block will be populated with 332 // pointer to the block as well as its block handle. 333 // @param uncompression_dict Data for presetting the compression library's 334 // dictionary. 335 template <typename TBlocklike> 336 Status GetDataBlockFromCache( 337 const Slice& block_cache_key, const Slice& compressed_block_cache_key, 338 Cache* block_cache, Cache* block_cache_compressed, 339 const ReadOptions& read_options, CachableEntry<TBlocklike>* block, 340 const UncompressionDict& uncompression_dict, BlockType block_type, 341 GetContext* get_context) const; 342 343 // Put a raw block (maybe compressed) to the corresponding block caches. 344 // This method will perform decompression against raw_block if needed and then 345 // populate the block caches. 346 // On success, Status::OK will be returned; also @block will be populated with 347 // uncompressed block and its cache handle. 348 // 349 // Allocated memory managed by raw_block_contents will be transferred to 350 // PutDataBlockToCache(). After the call, the object will be invalid. 351 // @param uncompression_dict Data for presetting the compression library's 352 // dictionary. 353 template <typename TBlocklike> 354 Status PutDataBlockToCache(const Slice& block_cache_key, 355 const Slice& compressed_block_cache_key, 356 Cache* block_cache, Cache* block_cache_compressed, 357 CachableEntry<TBlocklike>* cached_block, 358 BlockContents* raw_block_contents, 359 CompressionType raw_block_comp_type, 360 const UncompressionDict& uncompression_dict, 361 MemoryAllocator* memory_allocator, 362 BlockType block_type, 363 GetContext* get_context) const; 364 365 // Calls (*handle_result)(arg, ...) repeatedly, starting with the entry found 366 // after a call to Seek(key), until handle_result returns false. 367 // May not make such a call if filter policy says that key is not present. 368 friend class TableCache; 369 friend class BlockBasedTableBuilder; 370 371 // Create a index reader based on the index type stored in the table. 372 // Optionally, user can pass a preloaded meta_index_iter for the index that 373 // need to access extra meta blocks for index construction. This parameter 374 // helps avoid re-reading meta index block if caller already created one. 375 Status CreateIndexReader(FilePrefetchBuffer* prefetch_buffer, 376 InternalIterator* preloaded_meta_index_iter, 377 bool use_cache, bool prefetch, bool pin, 378 BlockCacheLookupContext* lookup_context, 379 std::unique_ptr<IndexReader>* index_reader); 380 381 bool FullFilterKeyMayMatch(const ReadOptions& read_options, 382 FilterBlockReader* filter, const Slice& user_key, 383 const bool no_io, 384 const SliceTransform* prefix_extractor, 385 GetContext* get_context, 386 BlockCacheLookupContext* lookup_context) const; 387 388 void FullFilterKeysMayMatch(const ReadOptions& read_options, 389 FilterBlockReader* filter, MultiGetRange* range, 390 const bool no_io, 391 const SliceTransform* prefix_extractor, 392 BlockCacheLookupContext* lookup_context) const; 393 394 static Status PrefetchTail( 395 RandomAccessFileReader* file, uint64_t file_size, 396 TailPrefetchStats* tail_prefetch_stats, const bool prefetch_all, 397 const bool preload_all, 398 std::unique_ptr<FilePrefetchBuffer>* prefetch_buffer); 399 Status ReadMetaIndexBlock(FilePrefetchBuffer* prefetch_buffer, 400 std::unique_ptr<Block>* metaindex_block, 401 std::unique_ptr<InternalIterator>* iter); 402 Status TryReadPropertiesWithGlobalSeqno(FilePrefetchBuffer* prefetch_buffer, 403 const Slice& handle_value, 404 TableProperties** table_properties); 405 Status ReadPropertiesBlock(FilePrefetchBuffer* prefetch_buffer, 406 InternalIterator* meta_iter, 407 const SequenceNumber largest_seqno); 408 Status ReadRangeDelBlock(FilePrefetchBuffer* prefetch_buffer, 409 InternalIterator* meta_iter, 410 const InternalKeyComparator& internal_comparator, 411 BlockCacheLookupContext* lookup_context); 412 Status PrefetchIndexAndFilterBlocks( 413 FilePrefetchBuffer* prefetch_buffer, InternalIterator* meta_iter, 414 BlockBasedTable* new_table, bool prefetch_all, 415 const BlockBasedTableOptions& table_options, const int level, 416 BlockCacheLookupContext* lookup_context); 417 418 static BlockType GetBlockTypeForMetaBlockByName(const Slice& meta_block_name); 419 420 Status VerifyChecksumInMetaBlocks(InternalIteratorBase<Slice>* index_iter); 421 Status VerifyChecksumInBlocks(const ReadOptions& read_options, 422 InternalIteratorBase<IndexValue>* index_iter); 423 424 // Create the filter from the filter block. 425 std::unique_ptr<FilterBlockReader> CreateFilterBlockReader( 426 FilePrefetchBuffer* prefetch_buffer, bool use_cache, bool prefetch, 427 bool pin, BlockCacheLookupContext* lookup_context); 428 429 static void SetupCacheKeyPrefix(Rep* rep); 430 431 // Generate a cache key prefix from the file 432 static void GenerateCachePrefix(Cache* cc, FSRandomAccessFile* file, 433 char* buffer, size_t* size); 434 static void GenerateCachePrefix(Cache* cc, FSWritableFile* file, char* buffer, 435 size_t* size); 436 437 // Given an iterator return its offset in file. 438 uint64_t ApproximateOffsetOf( 439 const InternalIteratorBase<IndexValue>& index_iter) const; 440 441 // Helper functions for DumpTable() 442 Status DumpIndexBlock(WritableFile* out_file); 443 Status DumpDataBlocks(WritableFile* out_file); 444 void DumpKeyValue(const Slice& key, const Slice& value, 445 WritableFile* out_file); 446 447 // A cumulative data block file read in MultiGet lower than this size will 448 // use a stack buffer 449 static constexpr size_t kMultiGetReadStackBufSize = 8192; 450 451 friend class PartitionedFilterBlockReader; 452 friend class PartitionedFilterBlockTest; 453 friend class DBBasicTest_MultiGetIOBufferOverrun_Test; 454 }; 455 456 // Maitaning state of a two-level iteration on a partitioned index structure. 457 class BlockBasedTable::PartitionedIndexIteratorState 458 : public TwoLevelIteratorState { 459 public: 460 PartitionedIndexIteratorState( 461 const BlockBasedTable* table, 462 std::unordered_map<uint64_t, CachableEntry<Block>>* block_map); 463 InternalIteratorBase<IndexValue>* NewSecondaryIterator( 464 const BlockHandle& index_value) override; 465 466 private: 467 // Don't own table_ 468 const BlockBasedTable* table_; 469 std::unordered_map<uint64_t, CachableEntry<Block>>* block_map_; 470 }; 471 472 // Stores all the properties associated with a BlockBasedTable. 473 // These are immutable. 474 struct BlockBasedTable::Rep { RepRep475 Rep(const ImmutableCFOptions& _ioptions, const EnvOptions& _env_options, 476 const BlockBasedTableOptions& _table_opt, 477 const InternalKeyComparator& _internal_comparator, bool skip_filters, 478 int _level, const bool _immortal_table) 479 : ioptions(_ioptions), 480 env_options(_env_options), 481 table_options(_table_opt), 482 filter_policy(skip_filters ? nullptr : _table_opt.filter_policy.get()), 483 internal_comparator(_internal_comparator), 484 filter_type(FilterType::kNoFilter), 485 index_type(BlockBasedTableOptions::IndexType::kBinarySearch), 486 hash_index_allow_collision(false), 487 whole_key_filtering(_table_opt.whole_key_filtering), 488 prefix_filtering(true), 489 global_seqno(kDisableGlobalSequenceNumber), 490 level(_level), 491 immortal_table(_immortal_table) {} 492 493 const ImmutableCFOptions& ioptions; 494 const EnvOptions& env_options; 495 const BlockBasedTableOptions table_options; 496 const FilterPolicy* const filter_policy; 497 const InternalKeyComparator& internal_comparator; 498 Status status; 499 std::unique_ptr<RandomAccessFileReader> file; 500 char cache_key_prefix[kMaxCacheKeyPrefixSize]; 501 size_t cache_key_prefix_size = 0; 502 char persistent_cache_key_prefix[kMaxCacheKeyPrefixSize]; 503 size_t persistent_cache_key_prefix_size = 0; 504 char compressed_cache_key_prefix[kMaxCacheKeyPrefixSize]; 505 size_t compressed_cache_key_prefix_size = 0; 506 PersistentCacheOptions persistent_cache_options; 507 508 // Footer contains the fixed table information 509 Footer footer; 510 511 std::unique_ptr<IndexReader> index_reader; 512 std::unique_ptr<FilterBlockReader> filter; 513 std::unique_ptr<UncompressionDictReader> uncompression_dict_reader; 514 515 enum class FilterType { 516 kNoFilter, 517 kFullFilter, 518 kBlockFilter, 519 kPartitionedFilter, 520 }; 521 FilterType filter_type; 522 BlockHandle filter_handle; 523 BlockHandle compression_dict_handle; 524 525 std::shared_ptr<const TableProperties> table_properties; 526 BlockBasedTableOptions::IndexType index_type; 527 bool hash_index_allow_collision; 528 bool whole_key_filtering; 529 bool prefix_filtering; 530 // TODO(kailiu) It is very ugly to use internal key in table, since table 531 // module should not be relying on db module. However to make things easier 532 // and compatible with existing code, we introduce a wrapper that allows 533 // block to extract prefix without knowing if a key is internal or not. 534 // null if no prefix_extractor is passed in when opening the table reader. 535 std::unique_ptr<SliceTransform> internal_prefix_transform; 536 std::shared_ptr<const SliceTransform> table_prefix_extractor; 537 538 std::shared_ptr<const FragmentedRangeTombstoneList> fragmented_range_dels; 539 540 // If global_seqno is used, all Keys in this file will have the same 541 // seqno with value `global_seqno`. 542 // 543 // A value of kDisableGlobalSequenceNumber means that this feature is disabled 544 // and every key have it's own seqno. 545 SequenceNumber global_seqno; 546 547 // the level when the table is opened, could potentially change when trivial 548 // move is involved 549 int level; 550 551 // If false, blocks in this file are definitely all uncompressed. Knowing this 552 // before reading individual blocks enables certain optimizations. 553 bool blocks_maybe_compressed = true; 554 555 // If true, data blocks in this file are definitely ZSTD compressed. If false 556 // they might not be. When false we skip creating a ZSTD digested 557 // uncompression dictionary. Even if we get a false negative, things should 558 // still work, just not as quickly. 559 bool blocks_definitely_zstd_compressed = false; 560 561 // These describe how index is encoded. 562 bool index_has_first_key = false; 563 bool index_key_includes_seq = true; 564 bool index_value_is_full = true; 565 566 const bool immortal_table; 567 get_global_seqnoRep568 SequenceNumber get_global_seqno(BlockType block_type) const { 569 return (block_type == BlockType::kFilter || 570 block_type == BlockType::kCompressionDictionary) 571 ? kDisableGlobalSequenceNumber 572 : global_seqno; 573 } 574 cf_id_for_tracingRep575 uint64_t cf_id_for_tracing() const { 576 return table_properties 577 ? table_properties->column_family_id 578 : ROCKSDB_NAMESPACE::TablePropertiesCollectorFactory::Context:: 579 kUnknownColumnFamily; 580 } 581 cf_name_for_tracingRep582 Slice cf_name_for_tracing() const { 583 return table_properties ? table_properties->column_family_name 584 : BlockCacheTraceHelper::kUnknownColumnFamilyName; 585 } 586 level_for_tracingRep587 uint32_t level_for_tracing() const { return level >= 0 ? level : UINT32_MAX; } 588 sst_number_for_tracingRep589 uint64_t sst_number_for_tracing() const { 590 return file ? TableFileNameToNumber(file->file_name()) : UINT64_MAX; 591 } CreateFilePrefetchBufferRep592 void CreateFilePrefetchBuffer( 593 size_t readahead_size, size_t max_readahead_size, 594 std::unique_ptr<FilePrefetchBuffer>* fpb) const { 595 fpb->reset(new FilePrefetchBuffer(file.get(), readahead_size, 596 max_readahead_size, 597 !ioptions.allow_mmap_reads /* enable */)); 598 } 599 }; 600 } // namespace ROCKSDB_NAMESPACE 601