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 #include "rocksdb/table_properties.h"
7 
8 #include "port/port.h"
9 #include "rocksdb/env.h"
10 #include "rocksdb/iterator.h"
11 #include "table/block_based/block.h"
12 #include "table/internal_iterator.h"
13 #include "table/table_properties_internal.h"
14 #include "util/string_util.h"
15 
16 namespace ROCKSDB_NAMESPACE {
17 
18 const uint32_t TablePropertiesCollectorFactory::Context::kUnknownColumnFamily =
19     port::kMaxInt32;
20 
21 namespace {
AppendProperty(std::string & props,const std::string & key,const std::string & value,const std::string & prop_delim,const std::string & kv_delim)22   void AppendProperty(
23       std::string& props,
24       const std::string& key,
25       const std::string& value,
26       const std::string& prop_delim,
27       const std::string& kv_delim) {
28     props.append(key);
29     props.append(kv_delim);
30     props.append(value);
31     props.append(prop_delim);
32   }
33 
34   template <class TValue>
AppendProperty(std::string & props,const std::string & key,const TValue & value,const std::string & prop_delim,const std::string & kv_delim)35   void AppendProperty(
36       std::string& props,
37       const std::string& key,
38       const TValue& value,
39       const std::string& prop_delim,
40       const std::string& kv_delim) {
41     AppendProperty(
42         props, key, ToString(value), prop_delim, kv_delim
43     );
44   }
45 
46   // Seek to the specified meta block.
47   // Return true if it successfully seeks to that block.
SeekToMetaBlock(InternalIterator * meta_iter,const std::string & block_name,bool * is_found,BlockHandle * block_handle=nullptr)48   Status SeekToMetaBlock(InternalIterator* meta_iter,
49                          const std::string& block_name, bool* is_found,
50                          BlockHandle* block_handle = nullptr) {
51     if (block_handle != nullptr) {
52       *block_handle = BlockHandle::NullBlockHandle();
53     }
54     *is_found = true;
55     meta_iter->Seek(block_name);
56     if (meta_iter->status().ok()) {
57       if (meta_iter->Valid() && meta_iter->key() == block_name) {
58         *is_found = true;
59         if (block_handle) {
60           Slice v = meta_iter->value();
61           return block_handle->DecodeFrom(&v);
62         }
63       } else {
64         *is_found = false;
65         return Status::OK();
66       }
67     }
68     return meta_iter->status();
69   }
70 }
71 
ToString(const std::string & prop_delim,const std::string & kv_delim) const72 std::string TableProperties::ToString(
73     const std::string& prop_delim,
74     const std::string& kv_delim) const {
75   std::string result;
76   result.reserve(1024);
77 
78   // Basic Info
79   AppendProperty(result, "# data blocks", num_data_blocks, prop_delim,
80                  kv_delim);
81   AppendProperty(result, "# entries", num_entries, prop_delim, kv_delim);
82   AppendProperty(result, "# deletions", num_deletions, prop_delim, kv_delim);
83   AppendProperty(result, "# merge operands", num_merge_operands, prop_delim,
84                  kv_delim);
85   AppendProperty(result, "# range deletions", num_range_deletions, prop_delim,
86                  kv_delim);
87 
88   AppendProperty(result, "raw key size", raw_key_size, prop_delim, kv_delim);
89   AppendProperty(result, "raw average key size",
90                  num_entries != 0 ? 1.0 * raw_key_size / num_entries : 0.0,
91                  prop_delim, kv_delim);
92   AppendProperty(result, "raw value size", raw_value_size, prop_delim,
93                  kv_delim);
94   AppendProperty(result, "raw average value size",
95                  num_entries != 0 ? 1.0 * raw_value_size / num_entries : 0.0,
96                  prop_delim, kv_delim);
97 
98   AppendProperty(result, "data block size", data_size, prop_delim, kv_delim);
99   char index_block_size_str[80];
100   snprintf(index_block_size_str, sizeof(index_block_size_str),
101            "index block size (user-key? %d, delta-value? %d)",
102            static_cast<int>(index_key_is_user_key),
103            static_cast<int>(index_value_is_delta_encoded));
104   AppendProperty(result, index_block_size_str, index_size, prop_delim,
105                  kv_delim);
106   if (index_partitions != 0) {
107     AppendProperty(result, "# index partitions", index_partitions, prop_delim,
108                    kv_delim);
109     AppendProperty(result, "top-level index size", top_level_index_size, prop_delim,
110                    kv_delim);
111   }
112   AppendProperty(result, "filter block size", filter_size, prop_delim,
113                  kv_delim);
114   AppendProperty(result, "(estimated) table size",
115                  data_size + index_size + filter_size, prop_delim, kv_delim);
116 
117   AppendProperty(
118       result, "filter policy name",
119       filter_policy_name.empty() ? std::string("N/A") : filter_policy_name,
120       prop_delim, kv_delim);
121 
122   AppendProperty(result, "prefix extractor name",
123                  prefix_extractor_name.empty() ? std::string("N/A")
124                                                : prefix_extractor_name,
125                  prop_delim, kv_delim);
126 
127   AppendProperty(result, "column family ID",
128                  column_family_id ==
129                          ROCKSDB_NAMESPACE::TablePropertiesCollectorFactory::
130                              Context::kUnknownColumnFamily
131                      ? std::string("N/A")
132                      : ROCKSDB_NAMESPACE::ToString(column_family_id),
133                  prop_delim, kv_delim);
134   AppendProperty(
135       result, "column family name",
136       column_family_name.empty() ? std::string("N/A") : column_family_name,
137       prop_delim, kv_delim);
138 
139   AppendProperty(result, "comparator name",
140                  comparator_name.empty() ? std::string("N/A") : comparator_name,
141                  prop_delim, kv_delim);
142 
143   AppendProperty(
144       result, "merge operator name",
145       merge_operator_name.empty() ? std::string("N/A") : merge_operator_name,
146       prop_delim, kv_delim);
147 
148   AppendProperty(result, "property collectors names",
149                  property_collectors_names.empty() ? std::string("N/A")
150                                                    : property_collectors_names,
151                  prop_delim, kv_delim);
152 
153   AppendProperty(
154       result, "SST file compression algo",
155       compression_name.empty() ? std::string("N/A") : compression_name,
156       prop_delim, kv_delim);
157 
158   AppendProperty(
159       result, "SST file compression options",
160       compression_options.empty() ? std::string("N/A") : compression_options,
161       prop_delim, kv_delim);
162 
163   AppendProperty(result, "creation time", creation_time, prop_delim, kv_delim);
164 
165   AppendProperty(result, "time stamp of earliest key", oldest_key_time,
166                  prop_delim, kv_delim);
167 
168   AppendProperty(result, "file creation time", file_creation_time, prop_delim,
169                  kv_delim);
170 
171   return result;
172 }
173 
Add(const TableProperties & tp)174 void TableProperties::Add(const TableProperties& tp) {
175   data_size += tp.data_size;
176   index_size += tp.index_size;
177   index_partitions += tp.index_partitions;
178   top_level_index_size += tp.top_level_index_size;
179   index_key_is_user_key += tp.index_key_is_user_key;
180   index_value_is_delta_encoded += tp.index_value_is_delta_encoded;
181   filter_size += tp.filter_size;
182   raw_key_size += tp.raw_key_size;
183   raw_value_size += tp.raw_value_size;
184   num_data_blocks += tp.num_data_blocks;
185   num_entries += tp.num_entries;
186   num_deletions += tp.num_deletions;
187   num_merge_operands += tp.num_merge_operands;
188   num_range_deletions += tp.num_range_deletions;
189 }
190 
191 const std::string TablePropertiesNames::kDataSize  =
192     "rocksdb.data.size";
193 const std::string TablePropertiesNames::kIndexSize =
194     "rocksdb.index.size";
195 const std::string TablePropertiesNames::kIndexPartitions =
196     "rocksdb.index.partitions";
197 const std::string TablePropertiesNames::kTopLevelIndexSize =
198     "rocksdb.top-level.index.size";
199 const std::string TablePropertiesNames::kIndexKeyIsUserKey =
200     "rocksdb.index.key.is.user.key";
201 const std::string TablePropertiesNames::kIndexValueIsDeltaEncoded =
202     "rocksdb.index.value.is.delta.encoded";
203 const std::string TablePropertiesNames::kFilterSize =
204     "rocksdb.filter.size";
205 const std::string TablePropertiesNames::kRawKeySize =
206     "rocksdb.raw.key.size";
207 const std::string TablePropertiesNames::kRawValueSize =
208     "rocksdb.raw.value.size";
209 const std::string TablePropertiesNames::kNumDataBlocks =
210     "rocksdb.num.data.blocks";
211 const std::string TablePropertiesNames::kNumEntries =
212     "rocksdb.num.entries";
213 const std::string TablePropertiesNames::kDeletedKeys = "rocksdb.deleted.keys";
214 const std::string TablePropertiesNames::kMergeOperands =
215     "rocksdb.merge.operands";
216 const std::string TablePropertiesNames::kNumRangeDeletions =
217     "rocksdb.num.range-deletions";
218 const std::string TablePropertiesNames::kFilterPolicy =
219     "rocksdb.filter.policy";
220 const std::string TablePropertiesNames::kFormatVersion =
221     "rocksdb.format.version";
222 const std::string TablePropertiesNames::kFixedKeyLen =
223     "rocksdb.fixed.key.length";
224 const std::string TablePropertiesNames::kColumnFamilyId =
225     "rocksdb.column.family.id";
226 const std::string TablePropertiesNames::kColumnFamilyName =
227     "rocksdb.column.family.name";
228 const std::string TablePropertiesNames::kComparator = "rocksdb.comparator";
229 const std::string TablePropertiesNames::kMergeOperator =
230     "rocksdb.merge.operator";
231 const std::string TablePropertiesNames::kPrefixExtractorName =
232     "rocksdb.prefix.extractor.name";
233 const std::string TablePropertiesNames::kPropertyCollectors =
234     "rocksdb.property.collectors";
235 const std::string TablePropertiesNames::kCompression = "rocksdb.compression";
236 const std::string TablePropertiesNames::kCompressionOptions =
237     "rocksdb.compression_options";
238 const std::string TablePropertiesNames::kCreationTime = "rocksdb.creation.time";
239 const std::string TablePropertiesNames::kOldestKeyTime =
240     "rocksdb.oldest.key.time";
241 const std::string TablePropertiesNames::kFileCreationTime =
242     "rocksdb.file.creation.time";
243 
244 extern const std::string kPropertiesBlock = "rocksdb.properties";
245 // Old property block name for backward compatibility
246 extern const std::string kPropertiesBlockOldName = "rocksdb.stats";
247 extern const std::string kCompressionDictBlock = "rocksdb.compression_dict";
248 extern const std::string kRangeDelBlock = "rocksdb.range_del";
249 
250 // Seek to the properties block.
251 // Return true if it successfully seeks to the properties block.
SeekToPropertiesBlock(InternalIterator * meta_iter,bool * is_found)252 Status SeekToPropertiesBlock(InternalIterator* meta_iter, bool* is_found) {
253   Status status = SeekToMetaBlock(meta_iter, kPropertiesBlock, is_found);
254   if (!*is_found && status.ok()) {
255     status = SeekToMetaBlock(meta_iter, kPropertiesBlockOldName, is_found);
256   }
257   return status;
258 }
259 
260 // Seek to the compression dictionary block.
261 // Return true if it successfully seeks to that block.
SeekToCompressionDictBlock(InternalIterator * meta_iter,bool * is_found,BlockHandle * block_handle)262 Status SeekToCompressionDictBlock(InternalIterator* meta_iter, bool* is_found,
263                                   BlockHandle* block_handle) {
264   return SeekToMetaBlock(meta_iter, kCompressionDictBlock, is_found, block_handle);
265 }
266 
SeekToRangeDelBlock(InternalIterator * meta_iter,bool * is_found,BlockHandle * block_handle=nullptr)267 Status SeekToRangeDelBlock(InternalIterator* meta_iter, bool* is_found,
268                            BlockHandle* block_handle = nullptr) {
269   return SeekToMetaBlock(meta_iter, kRangeDelBlock, is_found, block_handle);
270 }
271 
272 }  // namespace ROCKSDB_NAMESPACE
273