/src/rocksdb/table/table_properties.cc
Line | Count | Source |
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 "db/seqno_to_time_mapping.h" |
9 | | #include "port/malloc.h" |
10 | | #include "port/port.h" |
11 | | #include "rocksdb/env.h" |
12 | | #include "rocksdb/unique_id.h" |
13 | | #include "rocksdb/utilities/options_type.h" |
14 | | #include "table/table_properties_internal.h" |
15 | | #include "table/unique_id_impl.h" |
16 | | #include "util/compression.h" |
17 | | #include "util/random.h" |
18 | | #include "util/string_util.h" |
19 | | |
20 | | namespace ROCKSDB_NAMESPACE { |
21 | | |
22 | | const uint32_t TablePropertiesCollectorFactory::Context::kUnknownColumnFamily = |
23 | | std::numeric_limits<int32_t>::max(); |
24 | | |
25 | | namespace { |
26 | | void AppendProperty(std::string& props, const std::string& key, |
27 | | const std::string& value, const std::string& prop_delim, |
28 | 0 | const std::string& kv_delim) { |
29 | 0 | props.append(key); |
30 | 0 | props.append(kv_delim); |
31 | 0 | props.append(value); |
32 | 0 | props.append(prop_delim); |
33 | 0 | } |
34 | | |
35 | | template <class TValue> |
36 | | void AppendProperty(std::string& props, const std::string& key, |
37 | | const TValue& value, const std::string& prop_delim, |
38 | 0 | const std::string& kv_delim) { |
39 | 0 | AppendProperty(props, key, std::to_string(value), prop_delim, kv_delim); |
40 | 0 | } Unexecuted instantiation: table_properties.cc:void rocksdb::(anonymous namespace)::AppendProperty<unsigned long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: table_properties.cc:void rocksdb::(anonymous namespace)::AppendProperty<double>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
41 | | |
42 | | std::shared_ptr<CompressionManager> ResolveCompressionManagerForDisplay( |
43 | | Slice compatibility_name, |
44 | 0 | const std::shared_ptr<CompressionManager>& compression_manager) { |
45 | 0 | std::shared_ptr<CompressionManager> mgr_to_use; |
46 | 0 | if (compression_manager) { |
47 | 0 | mgr_to_use = compression_manager->FindCompatibleCompressionManager( |
48 | 0 | compatibility_name); |
49 | 0 | } |
50 | 0 | if (mgr_to_use == nullptr) { |
51 | 0 | ConfigOptions strict; |
52 | 0 | strict.ignore_unknown_options = false; |
53 | 0 | strict.ignore_unsupported_options = false; |
54 | 0 | Status s = CompressionManager::CreateFromString( |
55 | 0 | strict, compatibility_name.ToString(), &mgr_to_use); |
56 | 0 | if (!s.ok()) { |
57 | 0 | mgr_to_use.reset(); |
58 | 0 | } |
59 | 0 | } |
60 | 0 | return mgr_to_use; |
61 | 0 | } |
62 | | |
63 | | std::string CompressionTypeDisplayName( |
64 | | CompressionType compression_type, |
65 | 0 | const std::shared_ptr<CompressionManager>& compression_manager) { |
66 | 0 | if (compression_manager) { |
67 | 0 | std::string name = |
68 | 0 | compression_manager->CompressionTypeToString(compression_type); |
69 | 0 | if (!name.empty()) { |
70 | 0 | return name; |
71 | 0 | } |
72 | 0 | } |
73 | 0 | return CompressionTypeToString(compression_type); |
74 | 0 | } |
75 | | } // namespace |
76 | | |
77 | | std::string TableProperties::ToString(const std::string& prop_delim, |
78 | 0 | const std::string& kv_delim) const { |
79 | 0 | std::string result; |
80 | 0 | result.reserve(1024); |
81 | | |
82 | | // Basic Info |
83 | 0 | AppendProperty(result, "# data blocks", num_data_blocks, prop_delim, |
84 | 0 | kv_delim); |
85 | 0 | AppendProperty(result, "# data blocks compression rejected", |
86 | 0 | num_data_blocks_compression_rejected, prop_delim, kv_delim); |
87 | 0 | AppendProperty(result, "# data blocks compression bypassed", |
88 | 0 | num_data_blocks_compression_bypassed, prop_delim, kv_delim); |
89 | 0 | AppendProperty(result, "# uniform blocks", num_uniform_blocks, prop_delim, |
90 | 0 | kv_delim); |
91 | 0 | AppendProperty(result, "# entries", num_entries, prop_delim, kv_delim); |
92 | 0 | AppendProperty(result, "# deletions", num_deletions, prop_delim, kv_delim); |
93 | 0 | AppendProperty(result, "# merge operands", num_merge_operands, prop_delim, |
94 | 0 | kv_delim); |
95 | 0 | AppendProperty(result, "# range deletions", num_range_deletions, prop_delim, |
96 | 0 | kv_delim); |
97 | |
|
98 | 0 | AppendProperty(result, "raw key size", raw_key_size, prop_delim, kv_delim); |
99 | 0 | AppendProperty(result, "raw average key size", |
100 | 0 | num_entries != 0 ? 1.0 * raw_key_size / num_entries : 0.0, |
101 | 0 | prop_delim, kv_delim); |
102 | 0 | AppendProperty(result, "raw value size", raw_value_size, prop_delim, |
103 | 0 | kv_delim); |
104 | 0 | AppendProperty(result, "raw average value size", |
105 | 0 | num_entries != 0 ? 1.0 * raw_value_size / num_entries : 0.0, |
106 | 0 | prop_delim, kv_delim); |
107 | |
|
108 | 0 | AppendProperty(result, "data block size", data_size, prop_delim, kv_delim); |
109 | 0 | AppendProperty(result, "data uncompressed size", uncompressed_data_size, |
110 | 0 | prop_delim, kv_delim); |
111 | 0 | char index_block_size_str[80]; |
112 | 0 | snprintf(index_block_size_str, sizeof(index_block_size_str), |
113 | 0 | "index block size (user-key? %d, delta-value? %d)", |
114 | 0 | static_cast<int>(index_key_is_user_key), |
115 | 0 | static_cast<int>(index_value_is_delta_encoded)); |
116 | 0 | AppendProperty(result, index_block_size_str, index_size, prop_delim, |
117 | 0 | kv_delim); |
118 | 0 | if (index_partitions != 0) { |
119 | 0 | AppendProperty(result, "# index partitions", index_partitions, prop_delim, |
120 | 0 | kv_delim); |
121 | 0 | AppendProperty(result, "top-level index size", top_level_index_size, |
122 | 0 | prop_delim, kv_delim); |
123 | 0 | } |
124 | 0 | AppendProperty(result, "filter block size", filter_size, prop_delim, |
125 | 0 | kv_delim); |
126 | 0 | AppendProperty(result, "# entries for filter", num_filter_entries, prop_delim, |
127 | 0 | kv_delim); |
128 | 0 | AppendProperty(result, "(estimated) table size", |
129 | 0 | data_size + index_size + filter_size, prop_delim, kv_delim); |
130 | |
|
131 | 0 | AppendProperty( |
132 | 0 | result, "filter policy name", |
133 | 0 | filter_policy_name.empty() ? std::string("N/A") : filter_policy_name, |
134 | 0 | prop_delim, kv_delim); |
135 | |
|
136 | 0 | AppendProperty(result, "prefix extractor name", |
137 | 0 | prefix_extractor_name.empty() ? std::string("N/A") |
138 | 0 | : prefix_extractor_name, |
139 | 0 | prop_delim, kv_delim); |
140 | |
|
141 | 0 | AppendProperty(result, "column family ID", |
142 | 0 | column_family_id == |
143 | 0 | ROCKSDB_NAMESPACE::TablePropertiesCollectorFactory:: |
144 | 0 | Context::kUnknownColumnFamily |
145 | 0 | ? std::string("N/A") |
146 | 0 | : std::to_string(column_family_id), |
147 | 0 | prop_delim, kv_delim); |
148 | 0 | AppendProperty( |
149 | 0 | result, "column family name", |
150 | 0 | column_family_name.empty() ? std::string("N/A") : column_family_name, |
151 | 0 | prop_delim, kv_delim); |
152 | |
|
153 | 0 | AppendProperty(result, "comparator name", |
154 | 0 | comparator_name.empty() ? std::string("N/A") : comparator_name, |
155 | 0 | prop_delim, kv_delim); |
156 | 0 | AppendProperty(result, "user defined timestamps persisted", |
157 | 0 | user_defined_timestamps_persisted ? std::string("true") |
158 | 0 | : std::string("false"), |
159 | 0 | prop_delim, kv_delim); |
160 | 0 | AppendProperty(result, "largest sequence number in file", key_largest_seqno, |
161 | 0 | prop_delim, kv_delim); |
162 | 0 | AppendProperty(result, "smallest sequence number in file", key_smallest_seqno, |
163 | 0 | prop_delim, kv_delim); |
164 | |
|
165 | 0 | AppendProperty( |
166 | 0 | result, "merge operator name", |
167 | 0 | merge_operator_name.empty() ? std::string("N/A") : merge_operator_name, |
168 | 0 | prop_delim, kv_delim); |
169 | |
|
170 | 0 | AppendProperty(result, "property collectors names", |
171 | 0 | property_collectors_names.empty() ? std::string("N/A") |
172 | 0 | : property_collectors_names, |
173 | 0 | prop_delim, kv_delim); |
174 | |
|
175 | 0 | AppendProperty( |
176 | 0 | result, "SST file compression algo", |
177 | 0 | compression_name.empty() ? std::string("N/A") : compression_name, |
178 | 0 | prop_delim, kv_delim); |
179 | |
|
180 | 0 | AppendProperty( |
181 | 0 | result, "SST file compression options", |
182 | 0 | compression_options.empty() ? std::string("N/A") : compression_options, |
183 | 0 | prop_delim, kv_delim); |
184 | |
|
185 | 0 | AppendProperty(result, "creation time", creation_time, prop_delim, kv_delim); |
186 | |
|
187 | 0 | AppendProperty(result, "time stamp of earliest key", oldest_key_time, |
188 | 0 | prop_delim, kv_delim); |
189 | 0 | AppendProperty(result, "time stamp of newest key", newest_key_time, |
190 | 0 | prop_delim, kv_delim); |
191 | |
|
192 | 0 | AppendProperty(result, "file creation time", file_creation_time, prop_delim, |
193 | 0 | kv_delim); |
194 | |
|
195 | 0 | AppendProperty(result, "slow compression estimated data size", |
196 | 0 | slow_compression_estimated_data_size, prop_delim, kv_delim); |
197 | 0 | AppendProperty(result, "fast compression estimated data size", |
198 | 0 | fast_compression_estimated_data_size, prop_delim, kv_delim); |
199 | | |
200 | | // DB identity and DB session ID |
201 | 0 | AppendProperty(result, "DB identity", db_id, prop_delim, kv_delim); |
202 | 0 | AppendProperty(result, "DB session identity", db_session_id, prop_delim, |
203 | 0 | kv_delim); |
204 | 0 | AppendProperty(result, "DB host id", db_host_id, prop_delim, kv_delim); |
205 | 0 | AppendProperty(result, "original file number", orig_file_number, prop_delim, |
206 | 0 | kv_delim); |
207 | | |
208 | | // Unique ID, when available |
209 | 0 | std::string id; |
210 | 0 | Status s = GetUniqueIdFromTableProperties(*this, &id); |
211 | 0 | AppendProperty(result, "unique ID", |
212 | 0 | s.ok() ? UniqueIdToHumanString(id) : "N/A", prop_delim, |
213 | 0 | kv_delim); |
214 | |
|
215 | 0 | SeqnoToTimeMapping seq_time_mapping; |
216 | 0 | s = seq_time_mapping.DecodeFrom(seqno_to_time_mapping); |
217 | 0 | AppendProperty(result, "Sequence number to time mapping", |
218 | 0 | s.ok() ? seq_time_mapping.ToHumanString() : "N/A", prop_delim, |
219 | 0 | kv_delim); |
220 | |
|
221 | 0 | return result; |
222 | 0 | } |
223 | | |
224 | 0 | void TableProperties::Add(const TableProperties& tp) { |
225 | 0 | data_size += tp.data_size; |
226 | 0 | uncompressed_data_size += tp.uncompressed_data_size; |
227 | 0 | index_size += tp.index_size; |
228 | 0 | index_partitions += tp.index_partitions; |
229 | 0 | top_level_index_size += tp.top_level_index_size; |
230 | 0 | index_key_is_user_key += tp.index_key_is_user_key; |
231 | 0 | index_value_is_delta_encoded += tp.index_value_is_delta_encoded; |
232 | 0 | filter_size += tp.filter_size; |
233 | 0 | raw_key_size += tp.raw_key_size; |
234 | 0 | raw_value_size += tp.raw_value_size; |
235 | 0 | num_data_blocks += tp.num_data_blocks; |
236 | 0 | num_data_blocks_compression_rejected += |
237 | 0 | tp.num_data_blocks_compression_rejected; |
238 | 0 | num_data_blocks_compression_bypassed += |
239 | 0 | tp.num_data_blocks_compression_bypassed; |
240 | 0 | num_uniform_blocks += tp.num_uniform_blocks; |
241 | 0 | num_entries += tp.num_entries; |
242 | 0 | num_filter_entries += tp.num_filter_entries; |
243 | 0 | num_deletions += tp.num_deletions; |
244 | 0 | num_merge_operands += tp.num_merge_operands; |
245 | 0 | num_range_deletions += tp.num_range_deletions; |
246 | 0 | slow_compression_estimated_data_size += |
247 | 0 | tp.slow_compression_estimated_data_size; |
248 | 0 | fast_compression_estimated_data_size += |
249 | 0 | tp.fast_compression_estimated_data_size; |
250 | 0 | } |
251 | | |
252 | | std::map<std::string, uint64_t> |
253 | 0 | TableProperties::GetAggregatablePropertiesAsMap() const { |
254 | 0 | std::map<std::string, uint64_t> rv; |
255 | 0 | rv["data_size"] = data_size; |
256 | 0 | rv["uncompressed_data_size"] = uncompressed_data_size; |
257 | 0 | rv["index_size"] = index_size; |
258 | 0 | rv["index_partitions"] = index_partitions; |
259 | 0 | rv["top_level_index_size"] = top_level_index_size; |
260 | 0 | rv["filter_size"] = filter_size; |
261 | 0 | rv["raw_key_size"] = raw_key_size; |
262 | 0 | rv["raw_value_size"] = raw_value_size; |
263 | 0 | rv["num_data_blocks"] = num_data_blocks; |
264 | 0 | rv["num_data_blocks_compression_rejected"] = |
265 | 0 | num_data_blocks_compression_rejected; |
266 | 0 | rv["num_data_blocks_compression_bypassed"] = |
267 | 0 | num_data_blocks_compression_bypassed; |
268 | 0 | rv["num_uniform_blocks"] = num_uniform_blocks; |
269 | 0 | rv["num_entries"] = num_entries; |
270 | 0 | rv["num_filter_entries"] = num_filter_entries; |
271 | 0 | rv["num_deletions"] = num_deletions; |
272 | 0 | rv["num_merge_operands"] = num_merge_operands; |
273 | 0 | rv["num_range_deletions"] = num_range_deletions; |
274 | 0 | rv["slow_compression_estimated_data_size"] = |
275 | 0 | slow_compression_estimated_data_size; |
276 | 0 | rv["fast_compression_estimated_data_size"] = |
277 | 0 | fast_compression_estimated_data_size; |
278 | 0 | return rv; |
279 | 0 | } |
280 | | |
281 | | // WARNING: manual update to this function is needed |
282 | | // whenever a new string property is added to TableProperties |
283 | | // to reduce approximation error. |
284 | | // |
285 | | // TODO: eliminate the need of manually updating this function |
286 | | // for new string properties |
287 | 0 | std::size_t TableProperties::ApproximateMemoryUsage() const { |
288 | 0 | std::size_t usage = 0; |
289 | 0 | #ifdef ROCKSDB_MALLOC_USABLE_SIZE |
290 | 0 | usage += malloc_usable_size((void*)this); |
291 | | #else |
292 | | usage += sizeof(*this); |
293 | | #endif // ROCKSDB_MALLOC_USABLE_SIZE |
294 | |
|
295 | 0 | std::size_t string_props_mem_usage = |
296 | 0 | db_id.size() + db_session_id.size() + db_host_id.size() + |
297 | 0 | column_family_name.size() + filter_policy_name.size() + |
298 | 0 | comparator_name.size() + merge_operator_name.size() + |
299 | 0 | prefix_extractor_name.size() + property_collectors_names.size() + |
300 | 0 | compression_name.size() + compression_options.size(); |
301 | 0 | usage += string_props_mem_usage; |
302 | |
|
303 | 0 | for (auto iter = user_collected_properties.begin(); |
304 | 0 | iter != user_collected_properties.end(); ++iter) { |
305 | 0 | usage += (iter->first.size() + iter->second.size()); |
306 | 0 | } |
307 | |
|
308 | 0 | return usage; |
309 | 0 | } |
310 | | |
311 | | const std::string TablePropertiesNames::kDbId = "rocksdb.creating.db.identity"; |
312 | | const std::string TablePropertiesNames::kDbSessionId = |
313 | | "rocksdb.creating.session.identity"; |
314 | | const std::string TablePropertiesNames::kDbHostId = |
315 | | "rocksdb.creating.host.identity"; |
316 | | const std::string TablePropertiesNames::kOriginalFileNumber = |
317 | | "rocksdb.original.file.number"; |
318 | | const std::string TablePropertiesNames::kDataSize = "rocksdb.data.size"; |
319 | | const std::string TablePropertiesNames::kIndexSize = "rocksdb.index.size"; |
320 | | const std::string TablePropertiesNames::kIndexPartitions = |
321 | | "rocksdb.index.partitions"; |
322 | | const std::string TablePropertiesNames::kTopLevelIndexSize = |
323 | | "rocksdb.top-level.index.size"; |
324 | | const std::string TablePropertiesNames::kIndexKeyIsUserKey = |
325 | | "rocksdb.index.key.is.user.key"; |
326 | | const std::string TablePropertiesNames::kIndexValueIsDeltaEncoded = |
327 | | "rocksdb.index.value.is.delta.encoded"; |
328 | | const std::string TablePropertiesNames::kUDIIsPrimaryIndex = |
329 | | "rocksdb.udi.is.primary.index"; |
330 | | const std::string TablePropertiesNames::kFilterSize = "rocksdb.filter.size"; |
331 | | const std::string TablePropertiesNames::kRawKeySize = "rocksdb.raw.key.size"; |
332 | | const std::string TablePropertiesNames::kRawValueSize = |
333 | | "rocksdb.raw.value.size"; |
334 | | const std::string TablePropertiesNames::kNumDataBlocks = |
335 | | "rocksdb.num.data.blocks"; |
336 | | const std::string TablePropertiesNames::kNumDataBlocksCompressionRejected = |
337 | | "rocksdb.num.data.blocks.compression.rejected"; |
338 | | const std::string TablePropertiesNames::kNumDataBlocksCompressionBypassed = |
339 | | "rocksdb.num.data.blocks.compression.bypassed"; |
340 | | const std::string TablePropertiesNames::kNumUniformBlocks = |
341 | | "rocksdb.num.uniform.blocks"; |
342 | | const std::string TablePropertiesNames::kNumEntries = "rocksdb.num.entries"; |
343 | | const std::string TablePropertiesNames::kNumFilterEntries = |
344 | | "rocksdb.num.filter_entries"; |
345 | | const std::string TablePropertiesNames::kDeletedKeys = "rocksdb.deleted.keys"; |
346 | | const std::string TablePropertiesNames::kMergeOperands = |
347 | | "rocksdb.merge.operands"; |
348 | | const std::string TablePropertiesNames::kNumRangeDeletions = |
349 | | "rocksdb.num.range-deletions"; |
350 | | const std::string TablePropertiesNames::kFilterPolicy = "rocksdb.filter.policy"; |
351 | | const std::string TablePropertiesNames::kFormatVersion = |
352 | | "rocksdb.format.version"; |
353 | | const std::string TablePropertiesNames::kFixedKeyLen = |
354 | | "rocksdb.fixed.key.length"; |
355 | | const std::string TablePropertiesNames::kColumnFamilyId = |
356 | | "rocksdb.column.family.id"; |
357 | | const std::string TablePropertiesNames::kColumnFamilyName = |
358 | | "rocksdb.column.family.name"; |
359 | | const std::string TablePropertiesNames::kComparator = "rocksdb.comparator"; |
360 | | const std::string TablePropertiesNames::kMergeOperator = |
361 | | "rocksdb.merge.operator"; |
362 | | const std::string TablePropertiesNames::kPrefixExtractorName = |
363 | | "rocksdb.prefix.extractor.name"; |
364 | | const std::string TablePropertiesNames::kPropertyCollectors = |
365 | | "rocksdb.property.collectors"; |
366 | | const std::string TablePropertiesNames::kCompression = "rocksdb.compression"; |
367 | | const std::string TablePropertiesNames::kCompressionOptions = |
368 | | "rocksdb.compression_options"; |
369 | | const std::string TablePropertiesNames::kCreationTime = "rocksdb.creation.time"; |
370 | | const std::string TablePropertiesNames::kOldestKeyTime = |
371 | | "rocksdb.oldest.key.time"; |
372 | | const std::string TablePropertiesNames::kNewestKeyTime = |
373 | | "rocksdb.newest.key.time"; |
374 | | const std::string TablePropertiesNames::kFileCreationTime = |
375 | | "rocksdb.file.creation.time"; |
376 | | const std::string TablePropertiesNames::kSlowCompressionEstimatedDataSize = |
377 | | "rocksdb.sample_for_compression.slow.data.size"; |
378 | | const std::string TablePropertiesNames::kFastCompressionEstimatedDataSize = |
379 | | "rocksdb.sample_for_compression.fast.data.size"; |
380 | | const std::string TablePropertiesNames::kSequenceNumberTimeMapping = |
381 | | "rocksdb.seqno.time.map"; |
382 | | const std::string TablePropertiesNames::kTailStartOffset = |
383 | | "rocksdb.tail.start.offset"; |
384 | | const std::string TablePropertiesNames::kUserDefinedTimestampsPersisted = |
385 | | "rocksdb.user.defined.timestamps.persisted"; |
386 | | const std::string TablePropertiesNames::kKeyLargestSeqno = |
387 | | "rocksdb.key.largest.seqno"; |
388 | | const std::string TablePropertiesNames::kKeySmallestSeqno = |
389 | | "rocksdb.key.smallest.seqno"; |
390 | | const std::string TablePropertiesNames::kDataBlockRestartInterval = |
391 | | "rocksdb.data.block.restart.interval"; |
392 | | const std::string TablePropertiesNames::kIndexBlockRestartInterval = |
393 | | "rocksdb.index.block.restart.interval"; |
394 | | const std::string TablePropertiesNames::kSeparateKeyValueInDataBlock = |
395 | | "rocksdb.separate.key.value.in.data.block"; |
396 | | |
397 | | static std::unordered_map<std::string, OptionTypeInfo> |
398 | | table_properties_type_info = { |
399 | | {"orig_file_number", |
400 | | {offsetof(struct TableProperties, orig_file_number), |
401 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
402 | | OptionTypeFlags::kNone}}, |
403 | | {"data_size", |
404 | | {offsetof(struct TableProperties, data_size), OptionType::kUInt64T, |
405 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, |
406 | | {"uncompressed_data_size", |
407 | | {offsetof(struct TableProperties, uncompressed_data_size), |
408 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
409 | | OptionTypeFlags::kNone}}, |
410 | | {"index_size", |
411 | | {offsetof(struct TableProperties, index_size), OptionType::kUInt64T, |
412 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, |
413 | | {"index_partitions", |
414 | | {offsetof(struct TableProperties, index_partitions), |
415 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
416 | | OptionTypeFlags::kNone}}, |
417 | | {"top_level_index_size", |
418 | | {offsetof(struct TableProperties, top_level_index_size), |
419 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
420 | | OptionTypeFlags::kNone}}, |
421 | | {"index_key_is_user_key", |
422 | | {offsetof(struct TableProperties, index_key_is_user_key), |
423 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
424 | | OptionTypeFlags::kNone}}, |
425 | | {"index_value_is_delta_encoded", |
426 | | {offsetof(struct TableProperties, index_value_is_delta_encoded), |
427 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
428 | | OptionTypeFlags::kNone}}, |
429 | | {"udi_is_primary_index", |
430 | | {offsetof(struct TableProperties, udi_is_primary_index), |
431 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
432 | | OptionTypeFlags::kNone}}, |
433 | | {"filter_size", |
434 | | {offsetof(struct TableProperties, filter_size), OptionType::kUInt64T, |
435 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, |
436 | | {"raw_key_size", |
437 | | {offsetof(struct TableProperties, raw_key_size), OptionType::kUInt64T, |
438 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, |
439 | | {"raw_value_size", |
440 | | {offsetof(struct TableProperties, raw_value_size), |
441 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
442 | | OptionTypeFlags::kNone}}, |
443 | | {"num_data_blocks", |
444 | | {offsetof(struct TableProperties, num_data_blocks), |
445 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
446 | | OptionTypeFlags::kNone}}, |
447 | | {"num_data_blocks_compression_rejected", |
448 | | {offsetof(struct TableProperties, |
449 | | num_data_blocks_compression_rejected), |
450 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
451 | | OptionTypeFlags::kNone}}, |
452 | | {"num_data_blocks_compression_bypassed", |
453 | | {offsetof(struct TableProperties, |
454 | | num_data_blocks_compression_bypassed), |
455 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
456 | | OptionTypeFlags::kNone}}, |
457 | | {"num_uniform_blocks", |
458 | | {offsetof(struct TableProperties, num_uniform_blocks), |
459 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
460 | | OptionTypeFlags::kNone}}, |
461 | | {"num_entries", |
462 | | {offsetof(struct TableProperties, num_entries), OptionType::kUInt64T, |
463 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, |
464 | | {"num_filter_entries", |
465 | | {offsetof(struct TableProperties, num_filter_entries), |
466 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
467 | | OptionTypeFlags::kNone}}, |
468 | | {"num_deletions", |
469 | | {offsetof(struct TableProperties, num_deletions), OptionType::kUInt64T, |
470 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, |
471 | | {"num_merge_operands", |
472 | | {offsetof(struct TableProperties, num_merge_operands), |
473 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
474 | | OptionTypeFlags::kNone}}, |
475 | | {"num_range_deletions", |
476 | | {offsetof(struct TableProperties, num_range_deletions), |
477 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
478 | | OptionTypeFlags::kNone}}, |
479 | | {"format_version", |
480 | | {offsetof(struct TableProperties, format_version), |
481 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
482 | | OptionTypeFlags::kNone}}, |
483 | | {"fixed_key_len", |
484 | | {offsetof(struct TableProperties, fixed_key_len), OptionType::kUInt64T, |
485 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, |
486 | | {"column_family_id", |
487 | | {offsetof(struct TableProperties, column_family_id), |
488 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
489 | | OptionTypeFlags::kNone}}, |
490 | | {"creation_time", |
491 | | {offsetof(struct TableProperties, creation_time), OptionType::kUInt64T, |
492 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, |
493 | | {"oldest_key_time", |
494 | | {offsetof(struct TableProperties, oldest_key_time), |
495 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
496 | | OptionTypeFlags::kNone}}, |
497 | | {"newest_key_time", |
498 | | {offsetof(struct TableProperties, newest_key_time), |
499 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
500 | | OptionTypeFlags::kNone}}, |
501 | | {"file_creation_time", |
502 | | {offsetof(struct TableProperties, file_creation_time), |
503 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
504 | | OptionTypeFlags::kNone}}, |
505 | | {"slow_compression_estimated_data_size", |
506 | | {offsetof(struct TableProperties, |
507 | | slow_compression_estimated_data_size), |
508 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
509 | | OptionTypeFlags::kNone}}, |
510 | | {"fast_compression_estimated_data_size", |
511 | | {offsetof(struct TableProperties, |
512 | | fast_compression_estimated_data_size), |
513 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
514 | | OptionTypeFlags::kNone}}, |
515 | | {"external_sst_file_global_seqno_offset", |
516 | | {offsetof(struct TableProperties, |
517 | | external_sst_file_global_seqno_offset), |
518 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
519 | | OptionTypeFlags::kNone}}, |
520 | | {"tail_start_offset", |
521 | | {offsetof(struct TableProperties, tail_start_offset), |
522 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
523 | | OptionTypeFlags::kNone}}, |
524 | | {"user_defined_timestamps_persisted", |
525 | | {offsetof(struct TableProperties, user_defined_timestamps_persisted), |
526 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
527 | | OptionTypeFlags::kNone}}, |
528 | | {"key_largest_seqno", |
529 | | {offsetof(struct TableProperties, key_largest_seqno), |
530 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
531 | | OptionTypeFlags::kNone}}, |
532 | | {"key_smallest_seqno", |
533 | | {offsetof(struct TableProperties, key_smallest_seqno), |
534 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
535 | | OptionTypeFlags::kNone}}, |
536 | | {"data_block_restart_interval", |
537 | | {offsetof(struct TableProperties, data_block_restart_interval), |
538 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
539 | | OptionTypeFlags::kNone}}, |
540 | | {"index_block_restart_interval", |
541 | | {offsetof(struct TableProperties, index_block_restart_interval), |
542 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
543 | | OptionTypeFlags::kNone}}, |
544 | | {"separate_key_value_in_data_block", |
545 | | {offsetof(struct TableProperties, separate_key_value_in_data_block), |
546 | | OptionType::kUInt64T, OptionVerificationType::kNormal, |
547 | | OptionTypeFlags::kNone}}, |
548 | | {"db_id", |
549 | | {offsetof(struct TableProperties, db_id), OptionType::kEncodedString}}, |
550 | | {"db_session_id", |
551 | | {offsetof(struct TableProperties, db_session_id), |
552 | | OptionType::kEncodedString}}, |
553 | | {"db_host_id", |
554 | | {offsetof(struct TableProperties, db_host_id), |
555 | | OptionType::kEncodedString}}, |
556 | | {"column_family_name", |
557 | | {offsetof(struct TableProperties, column_family_name), |
558 | | OptionType::kEncodedString}}, |
559 | | {"filter_policy_name", |
560 | | {offsetof(struct TableProperties, filter_policy_name), |
561 | | OptionType::kEncodedString}}, |
562 | | {"comparator_name", |
563 | | {offsetof(struct TableProperties, comparator_name), |
564 | | OptionType::kEncodedString}}, |
565 | | {"merge_operator_name", |
566 | | {offsetof(struct TableProperties, merge_operator_name), |
567 | | OptionType::kEncodedString}}, |
568 | | {"prefix_extractor_name", |
569 | | {offsetof(struct TableProperties, prefix_extractor_name), |
570 | | OptionType::kEncodedString}}, |
571 | | {"property_collectors_names", |
572 | | {offsetof(struct TableProperties, property_collectors_names), |
573 | | OptionType::kEncodedString}}, |
574 | | {"compression_name", |
575 | | {offsetof(struct TableProperties, compression_name), |
576 | | OptionType::kEncodedString}}, |
577 | | {"compression_options", |
578 | | {offsetof(struct TableProperties, compression_options), |
579 | | OptionType::kEncodedString}}, |
580 | | {"seqno_to_time_mapping", |
581 | | {offsetof(struct TableProperties, seqno_to_time_mapping), |
582 | | OptionType::kEncodedString}}, |
583 | | {"user_collected_properties", |
584 | | OptionTypeInfo::StringMap( |
585 | | offsetof(struct TableProperties, user_collected_properties), |
586 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone)}, |
587 | | {"readable_properties", |
588 | | OptionTypeInfo::StringMap( |
589 | | offsetof(struct TableProperties, readable_properties), |
590 | | OptionVerificationType::kNormal, OptionTypeFlags::kNone)}, |
591 | | }; |
592 | | |
593 | | Status TableProperties::Serialize(const ConfigOptions& opts, |
594 | 0 | std::string* output) const { |
595 | 0 | return OptionTypeInfo::SerializeType(opts, table_properties_type_info, this, |
596 | 0 | output); |
597 | 0 | } |
598 | | Status TableProperties::Parse(const ConfigOptions& opts, |
599 | | const std::string& serialized, |
600 | 0 | TableProperties* table_properties) { |
601 | 0 | return OptionTypeInfo::ParseType(opts, serialized, table_properties_type_info, |
602 | 0 | table_properties); |
603 | 0 | } |
604 | | bool TableProperties::AreEqual(const ConfigOptions& opts, |
605 | | const TableProperties* other_table_properties, |
606 | 0 | std::string* mismatch) const { |
607 | 0 | return OptionTypeInfo::TypesAreEqual(opts, table_properties_type_info, this, |
608 | 0 | other_table_properties, mismatch); |
609 | 0 | } |
610 | | |
611 | | #ifndef NDEBUG |
612 | | // WARNING: TEST_SetRandomTableProperties assumes the following layout of |
613 | | // TableProperties |
614 | | // |
615 | | // struct TableProperties { |
616 | | // int64_t orig_file_number = 0; |
617 | | // ... |
618 | | // ... int64_t properties only |
619 | | // ... |
620 | | // std::string db_id; |
621 | | // ... |
622 | | // ... std::string properties only |
623 | | // ... |
624 | | // std::string compression_options; |
625 | | // UserCollectedProperties user_collected_properties; |
626 | | // ... |
627 | | // ... Other extra properties: non-int64_t/non-std::string properties only |
628 | | // ... |
629 | | // } |
630 | | void TEST_SetRandomTableProperties(TableProperties* props) { |
631 | | Random* r = Random::GetTLSInstance(); |
632 | | uint64_t* pu = &props->orig_file_number; |
633 | | assert(static_cast<void*>(pu) == static_cast<void*>(props)); |
634 | | std::string* ps = &props->db_id; |
635 | | const uint64_t* const pu_end = reinterpret_cast<const uint64_t*>(ps); |
636 | | // Use the last string property's address instead of |
637 | | // the first extra property (e.g `user_collected_properties`)'s address |
638 | | // in the for-loop to avoid advancing pointer to pointing to |
639 | | // potential non-zero padding bytes between these two addresses due to |
640 | | // user_collected_properties's alignment requirement |
641 | | const std::string* const ps_end_inclusive = &props->compression_options; |
642 | | |
643 | | for (; pu < pu_end; ++pu) { |
644 | | *pu = r->Next64(); |
645 | | } |
646 | | assert(static_cast<void*>(pu) == static_cast<void*>(ps)); |
647 | | for (; ps <= ps_end_inclusive; ++ps) { |
648 | | *ps = r->RandomBinaryString(13); |
649 | | } |
650 | | } |
651 | | #endif |
652 | | |
653 | | std::string ParseCompressionNameForDisplay( |
654 | 0 | const std::string& compression_name) { |
655 | | // The single-argument overload intentionally consults globally registered |
656 | | // CompressionManagers, keyed by the encoded compatibility name, so custom |
657 | | // managers can contribute display names without an explicit manager handle. |
658 | 0 | return ParseCompressionNameForDisplay(compression_name, nullptr); |
659 | 0 | } |
660 | | |
661 | | std::string ParseCompressionNameForDisplay( |
662 | | const std::string& compression_name, |
663 | 0 | std::shared_ptr<CompressionManager> compression_manager) { |
664 | | // Empty = no compression |
665 | 0 | if (compression_name.empty()) { |
666 | 0 | return "NoCompression"; |
667 | 0 | } |
668 | | |
669 | | // Check for format_version 7 format (contains ';') |
670 | 0 | size_t first_semicolon = compression_name.find(';'); |
671 | 0 | if (first_semicolon == std::string::npos) { |
672 | | // Old format - return as-is |
673 | 0 | return compression_name; |
674 | 0 | } |
675 | | |
676 | | // New format: "<compatibility_name>;<hex_codes>;" |
677 | 0 | size_t second_semicolon = compression_name.find(';', first_semicolon + 1); |
678 | 0 | if (second_semicolon == std::string::npos) { |
679 | | // Malformed - missing second field |
680 | 0 | return "Unknown"; |
681 | 0 | } |
682 | | |
683 | 0 | Slice compatibility_name(compression_name.data(), first_semicolon); |
684 | 0 | auto mgr_to_use = ResolveCompressionManagerForDisplay(compatibility_name, |
685 | 0 | compression_manager); |
686 | | |
687 | | // Extract hex codes |
688 | 0 | std::string hex_codes = compression_name.substr( |
689 | 0 | first_semicolon + 1, second_semicolon - first_semicolon - 1); |
690 | | |
691 | | // Validate hex string length (must be even) |
692 | 0 | if (hex_codes.size() % 2 != 0) { |
693 | 0 | return "Unknown"; |
694 | 0 | } |
695 | | |
696 | | // Parse each 2-char hex code to CompressionType. |
697 | | // Note: This intentionally mirrors GetDecompressor()'s decoding shape but |
698 | | // differs in error semantics. GetDecompressor() treats kNoCompression |
699 | | // (0x00) and values >= kDisableCompressionOption (0xFF) as corruption. For |
700 | | // display purposes, we silently filter these out and return "NoCompression" |
701 | | // if no valid types remain. |
702 | 0 | std::vector<std::string> types; |
703 | 0 | for (size_t i = 0; i < hex_codes.size(); i += 2) { |
704 | 0 | const char* ptr = hex_codes.data() + i; |
705 | 0 | uint64_t val = 0; |
706 | 0 | if (!ParseBaseChars<16>(&ptr, 2, &val)) { |
707 | 0 | return "Unknown"; |
708 | 0 | } |
709 | 0 | auto ct = static_cast<CompressionType>(val); |
710 | 0 | if (ct != kNoCompression && ct != kDisableCompressionOption) { |
711 | 0 | types.push_back(CompressionTypeDisplayName(ct, mgr_to_use)); |
712 | 0 | } |
713 | 0 | } |
714 | | |
715 | 0 | if (types.empty()) { |
716 | 0 | return "NoCompression"; |
717 | 0 | } else if (types.size() == 1) { |
718 | 0 | return types[0]; |
719 | 0 | } else { |
720 | | // Multiple types - join with commas |
721 | 0 | std::string result = types[0]; |
722 | 0 | for (size_t i = 1; i < types.size(); ++i) { |
723 | 0 | result += "," + types[i]; |
724 | 0 | } |
725 | 0 | return result; |
726 | 0 | } |
727 | 0 | } |
728 | | |
729 | | } // namespace ROCKSDB_NAMESPACE |