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 
7 #include "table/block_based/uncompression_dict_reader.h"
8 #include "monitoring/perf_context_imp.h"
9 #include "table/block_based/block_based_table_reader.h"
10 #include "util/compression.h"
11 
12 namespace ROCKSDB_NAMESPACE {
13 
Create(const BlockBasedTable * table,FilePrefetchBuffer * prefetch_buffer,bool use_cache,bool prefetch,bool pin,BlockCacheLookupContext * lookup_context,std::unique_ptr<UncompressionDictReader> * uncompression_dict_reader)14 Status UncompressionDictReader::Create(
15     const BlockBasedTable* table, FilePrefetchBuffer* prefetch_buffer,
16     bool use_cache, bool prefetch, bool pin,
17     BlockCacheLookupContext* lookup_context,
18     std::unique_ptr<UncompressionDictReader>* uncompression_dict_reader) {
19   assert(table);
20   assert(table->get_rep());
21   assert(!pin || prefetch);
22   assert(uncompression_dict_reader);
23 
24   CachableEntry<UncompressionDict> uncompression_dict;
25   if (prefetch || !use_cache) {
26     const Status s = ReadUncompressionDictionary(
27         table, prefetch_buffer, ReadOptions(), use_cache,
28         nullptr /* get_context */, lookup_context, &uncompression_dict);
29     if (!s.ok()) {
30       return s;
31     }
32 
33     if (use_cache && !pin) {
34       uncompression_dict.Reset();
35     }
36   }
37 
38   uncompression_dict_reader->reset(
39       new UncompressionDictReader(table, std::move(uncompression_dict)));
40 
41   return Status::OK();
42 }
43 
ReadUncompressionDictionary(const BlockBasedTable * table,FilePrefetchBuffer * prefetch_buffer,const ReadOptions & read_options,bool use_cache,GetContext * get_context,BlockCacheLookupContext * lookup_context,CachableEntry<UncompressionDict> * uncompression_dict)44 Status UncompressionDictReader::ReadUncompressionDictionary(
45     const BlockBasedTable* table, FilePrefetchBuffer* prefetch_buffer,
46     const ReadOptions& read_options, bool use_cache, GetContext* get_context,
47     BlockCacheLookupContext* lookup_context,
48     CachableEntry<UncompressionDict>* uncompression_dict) {
49   // TODO: add perf counter for compression dictionary read time
50 
51   assert(table);
52   assert(uncompression_dict);
53   assert(uncompression_dict->IsEmpty());
54 
55   const BlockBasedTable::Rep* const rep = table->get_rep();
56   assert(rep);
57   assert(!rep->compression_dict_handle.IsNull());
58 
59   const Status s = table->RetrieveBlock(
60       prefetch_buffer, read_options, rep->compression_dict_handle,
61       UncompressionDict::GetEmptyDict(), uncompression_dict,
62       BlockType::kCompressionDictionary, get_context, lookup_context,
63       /* for_compaction */ false, use_cache);
64 
65   if (!s.ok()) {
66     ROCKS_LOG_WARN(
67         rep->ioptions.info_log,
68         "Encountered error while reading data from compression dictionary "
69         "block %s",
70         s.ToString().c_str());
71   }
72 
73   return s;
74 }
75 
GetOrReadUncompressionDictionary(FilePrefetchBuffer * prefetch_buffer,bool no_io,GetContext * get_context,BlockCacheLookupContext * lookup_context,CachableEntry<UncompressionDict> * uncompression_dict) const76 Status UncompressionDictReader::GetOrReadUncompressionDictionary(
77     FilePrefetchBuffer* prefetch_buffer, bool no_io, GetContext* get_context,
78     BlockCacheLookupContext* lookup_context,
79     CachableEntry<UncompressionDict>* uncompression_dict) const {
80   assert(uncompression_dict);
81 
82   if (!uncompression_dict_.IsEmpty()) {
83     uncompression_dict->SetUnownedValue(uncompression_dict_.GetValue());
84     return Status::OK();
85   }
86 
87   ReadOptions read_options;
88   if (no_io) {
89     read_options.read_tier = kBlockCacheTier;
90   }
91 
92   return ReadUncompressionDictionary(table_, prefetch_buffer, read_options,
93                                      cache_dictionary_blocks(), get_context,
94                                      lookup_context, uncompression_dict);
95 }
96 
ApproximateMemoryUsage() const97 size_t UncompressionDictReader::ApproximateMemoryUsage() const {
98   assert(!uncompression_dict_.GetOwnValue() ||
99          uncompression_dict_.GetValue() != nullptr);
100   size_t usage = uncompression_dict_.GetOwnValue()
101                      ? uncompression_dict_.GetValue()->ApproximateMemoryUsage()
102                      : 0;
103 
104 #ifdef ROCKSDB_MALLOC_USABLE_SIZE
105   usage += malloc_usable_size(const_cast<UncompressionDictReader*>(this));
106 #else
107   usage += sizeof(*this);
108 #endif  // ROCKSDB_MALLOC_USABLE_SIZE
109 
110   return usage;
111 }
112 
cache_dictionary_blocks() const113 bool UncompressionDictReader::cache_dictionary_blocks() const {
114   assert(table_);
115   assert(table_->get_rep());
116 
117   return table_->get_rep()->table_options.cache_index_and_filter_blocks;
118 }
119 
120 }  // namespace ROCKSDB_NAMESPACE
121