Bug Summary

File:home/bhubbard/working/src/ceph/src/rocksdb/table/block_based_table_factory.cc
Warning:line 586, column 26
Called C++ object pointer is null

Annotated Source Code

[?] Use j/k keys for keyboard navigation

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#include "table/block_based_table_factory.h"
11
12#ifndef __STDC_FORMAT_MACROS
13#define __STDC_FORMAT_MACROS
14#endif
15
16#include <inttypes.h>
17#include <stdint.h>
18
19#include <memory>
20#include <string>
21
22#include "options/options_helper.h"
23#include "port/port.h"
24#include "rocksdb/cache.h"
25#include "rocksdb/convenience.h"
26#include "rocksdb/flush_block_policy.h"
27#include "table/block_based_table_builder.h"
28#include "table/block_based_table_reader.h"
29#include "table/format.h"
30#include "util/mutexlock.h"
31#include "util/string_util.h"
32
33namespace rocksdb {
34
35void TailPrefetchStats::RecordEffectiveSize(size_t len) {
36 MutexLock l(&mutex_);
37 if (num_records_ < kNumTracked) {
38 num_records_++;
39 }
40 records_[next_++] = len;
41 if (next_ == kNumTracked) {
42 next_ = 0;
43 }
44}
45
46size_t TailPrefetchStats::GetSuggestedPrefetchSize() {
47 std::vector<size_t> sorted;
48 {
49 MutexLock l(&mutex_);
50
51 if (num_records_ == 0) {
52 return 0;
53 }
54 sorted.assign(records_, records_ + num_records_);
55 }
56
57 // Of the historic size, we find the maximum one that satisifis the condtiion
58 // that if prefetching all, less than 1/8 will be wasted.
59 std::sort(sorted.begin(), sorted.end());
60
61 // Assuming we have 5 data points, and after sorting it looks like this:
62 //
63 // +---+
64 // +---+ | |
65 // | | | |
66 // | | | |
67 // | | | |
68 // | | | |
69 // +---+ | | | |
70 // | | | | | |
71 // +---+ | | | | | |
72 // | | | | | | | |
73 // +---+ | | | | | | | |
74 // | | | | | | | | | |
75 // | | | | | | | | | |
76 // | | | | | | | | | |
77 // | | | | | | | | | |
78 // | | | | | | | | | |
79 // +---+ +---+ +---+ +---+ +---+
80 //
81 // and we use every of the value as a candidate, and estimate how much we
82 // wasted, compared to read. For example, when we use the 3rd record
83 // as candiate. This area is what we read:
84 // +---+
85 // +---+ | |
86 // | | | |
87 // | | | |
88 // | | | |
89 // | | | |
90 // *** *** *** ***+ *** *** *** *** **
91 // * | | | | | |
92 // +---+ | | | | | *
93 // * | | | | | | | |
94 // +---+ | | | | | | | *
95 // * | | | | X | | | | |
96 // | | | | | | | | | *
97 // * | | | | | | | | |
98 // | | | | | | | | | *
99 // * | | | | | | | | |
100 // *** *** ***-*** ***--*** ***--*** +****
101 // which is (size of the record) X (number of records).
102 //
103 // While wasted is this area:
104 // +---+
105 // +---+ | |
106 // | | | |
107 // | | | |
108 // | | | |
109 // | | | |
110 // *** *** *** ****---+ | | | |
111 // * * | | | | |
112 // * *-*** *** | | | | |
113 // * * | | | | | | |
114 // *--** *** | | | | | | |
115 // | | | | | X | | | | |
116 // | | | | | | | | | |
117 // | | | | | | | | | |
118 // | | | | | | | | | |
119 // | | | | | | | | | |
120 // +---+ +---+ +---+ +---+ +---+
121 //
122 // Which can be calculated iteratively.
123 // The difference between wasted using 4st and 3rd record, will
124 // be following area:
125 // +---+
126 // +--+ +-+ ++ +-+ +-+ +---+ | |
127 // + xxxxxxxxxxxxxxxxxxxxxxxx | | | |
128 // xxxxxxxxxxxxxxxxxxxxxxxx | | | |
129 // + xxxxxxxxxxxxxxxxxxxxxxxx | | | |
130 // | xxxxxxxxxxxxxxxxxxxxxxxx | | | |
131 // +-+ +-+ +-+ ++ +---+ +--+ | | |
132 // | | | | | | |
133 // +---+ ++ | | | | | |
134 // | | | | | | X | | |
135 // +---+ ++ | | | | | | | |
136 // | | | | | | | | | |
137 // | | | | | | | | | |
138 // | | | | | | | | | |
139 // | | | | | | | | | |
140 // | | | | | | | | | |
141 // +---+ +---+ +---+ +---+ +---+
142 //
143 // which will be the size difference between 4st and 3rd record,
144 // times 3, which is number of records before the 4st.
145 // Here we assume that all data within the prefetch range will be useful. In
146 // reality, it may not be the case when a partial block is inside the range,
147 // or there are data in the middle that is not read. We ignore those cases
148 // for simplicity.
149 assert(!sorted.empty())(static_cast<void> (0));
150 size_t prev_size = sorted[0];
151 size_t max_qualified_size = sorted[0];
152 size_t wasted = 0;
153 for (size_t i = 1; i < sorted.size(); i++) {
154 size_t read = sorted[i] * sorted.size();
155 wasted += (sorted[i] - prev_size) * i;
156 if (wasted <= read / 8) {
157 max_qualified_size = sorted[i];
158 }
159 prev_size = sorted[i];
160 }
161 const size_t kMaxPrefetchSize = 512 * 1024; // Never exceed 512KB
162 return std::min(kMaxPrefetchSize, max_qualified_size);
163}
164
165BlockBasedTableFactory::BlockBasedTableFactory(
166 const BlockBasedTableOptions& _table_options)
167 : table_options_(_table_options) {
168 if (table_options_.flush_block_policy_factory == nullptr) {
169 table_options_.flush_block_policy_factory.reset(
170 new FlushBlockBySizePolicyFactory());
171 }
172 if (table_options_.no_block_cache) {
173 table_options_.block_cache.reset();
174 } else if (table_options_.block_cache == nullptr) {
175 table_options_.block_cache = NewLRUCache(8 << 20);
176 }
177 if (table_options_.block_size_deviation < 0 ||
178 table_options_.block_size_deviation > 100) {
179 table_options_.block_size_deviation = 0;
180 }
181 if (table_options_.block_restart_interval < 1) {
182 table_options_.block_restart_interval = 1;
183 }
184 if (table_options_.index_block_restart_interval < 1) {
185 table_options_.index_block_restart_interval = 1;
186 }
187 if (table_options_.partition_filters &&
188 table_options_.index_type !=
189 BlockBasedTableOptions::kTwoLevelIndexSearch) {
190 // We do not support partitioned filters without partitioning indexes
191 table_options_.partition_filters = false;
192 }
193}
194
195Status BlockBasedTableFactory::NewTableReader(
196 const TableReaderOptions& table_reader_options,
197 std::unique_ptr<RandomAccessFileReader>&& file, uint64_t file_size,
198 std::unique_ptr<TableReader>* table_reader,
199 bool prefetch_index_and_filter_in_cache) const {
200 return BlockBasedTable::Open(
201 table_reader_options.ioptions, table_reader_options.env_options,
202 table_options_, table_reader_options.internal_comparator, std::move(file),
203 file_size, table_reader, table_reader_options.prefix_extractor,
204 prefetch_index_and_filter_in_cache, table_reader_options.skip_filters,
205 table_reader_options.level, table_reader_options.immortal,
206 table_reader_options.largest_seqno, &tail_prefetch_stats_);
207}
208
209TableBuilder* BlockBasedTableFactory::NewTableBuilder(
210 const TableBuilderOptions& table_builder_options, uint32_t column_family_id,
211 WritableFileWriter* file) const {
212 auto table_builder = new BlockBasedTableBuilder(
213 table_builder_options.ioptions, table_builder_options.moptions,
214 table_options_, table_builder_options.internal_comparator,
215 table_builder_options.int_tbl_prop_collector_factories, column_family_id,
216 file, table_builder_options.compression_type,
217 table_builder_options.sample_for_compression,
218 table_builder_options.compression_opts,
219 table_builder_options.skip_filters,
220 table_builder_options.column_family_name,
221 table_builder_options.creation_time,
222 table_builder_options.oldest_key_time,
223 table_builder_options.target_file_size);
224
225 return table_builder;
226}
227
228Status BlockBasedTableFactory::SanitizeOptions(
229 const DBOptions& /*db_opts*/, const ColumnFamilyOptions& cf_opts) const {
230 if (table_options_.index_type == BlockBasedTableOptions::kHashSearch &&
231 cf_opts.prefix_extractor == nullptr) {
232 return Status::InvalidArgument(
233 "Hash index is specified for block-based "
234 "table, but prefix_extractor is not given");
235 }
236 if (table_options_.cache_index_and_filter_blocks &&
237 table_options_.no_block_cache) {
238 return Status::InvalidArgument(
239 "Enable cache_index_and_filter_blocks, "
240 ", but block cache is disabled");
241 }
242 if (table_options_.pin_l0_filter_and_index_blocks_in_cache &&
243 table_options_.no_block_cache) {
244 return Status::InvalidArgument(
245 "Enable pin_l0_filter_and_index_blocks_in_cache, "
246 ", but block cache is disabled");
247 }
248 if (!BlockBasedTableSupportedVersion(table_options_.format_version)) {
249 return Status::InvalidArgument(
250 "Unsupported BlockBasedTable format_version. Please check "
251 "include/rocksdb/table.h for more info");
252 }
253 if (table_options_.block_align && (cf_opts.compression != kNoCompression)) {
254 return Status::InvalidArgument(
255 "Enable block_align, but compression "
256 "enabled");
257 }
258 if (table_options_.block_align &&
259 (table_options_.block_size & (table_options_.block_size - 1))) {
260 return Status::InvalidArgument(
261 "Block alignment requested but block size is not a power of 2");
262 }
263 if (table_options_.data_block_index_type ==
264 BlockBasedTableOptions::kDataBlockBinaryAndHash &&
265 table_options_.data_block_hash_table_util_ratio <= 0) {
266 return Status::InvalidArgument(
267 "data_block_hash_table_util_ratio should be greater than 0 when "
268 "data_block_index_type is set to kDataBlockBinaryAndHash");
269 }
270 return Status::OK();
271}
272
273std::string BlockBasedTableFactory::GetPrintableTableOptions() const {
274 std::string ret;
275 ret.reserve(20000);
276 const int kBufferSize = 200;
277 char buffer[kBufferSize];
278
279 snprintf(buffer, kBufferSize, " flush_block_policy_factory: %s (%p)\n",
280 table_options_.flush_block_policy_factory->Name(),
281 static_cast<void*>(table_options_.flush_block_policy_factory.get()));
282 ret.append(buffer);
283 snprintf(buffer, kBufferSize, " cache_index_and_filter_blocks: %d\n",
284 table_options_.cache_index_and_filter_blocks);
285 ret.append(buffer);
286 snprintf(buffer, kBufferSize,
287 " cache_index_and_filter_blocks_with_high_priority: %d\n",
288 table_options_.cache_index_and_filter_blocks_with_high_priority);
289 ret.append(buffer);
290 snprintf(buffer, kBufferSize,
291 " pin_l0_filter_and_index_blocks_in_cache: %d\n",
292 table_options_.pin_l0_filter_and_index_blocks_in_cache);
293 ret.append(buffer);
294 snprintf(buffer, kBufferSize, " pin_top_level_index_and_filter: %d\n",
295 table_options_.pin_top_level_index_and_filter);
296 ret.append(buffer);
297 snprintf(buffer, kBufferSize, " index_type: %d\n",
298 table_options_.index_type);
299 ret.append(buffer);
300 snprintf(buffer, kBufferSize, " data_block_index_type: %d\n",
301 table_options_.data_block_index_type);
302 ret.append(buffer);
303 snprintf(buffer, kBufferSize, " data_block_hash_table_util_ratio: %lf\n",
304 table_options_.data_block_hash_table_util_ratio);
305 ret.append(buffer);
306 snprintf(buffer, kBufferSize, " hash_index_allow_collision: %d\n",
307 table_options_.hash_index_allow_collision);
308 ret.append(buffer);
309 snprintf(buffer, kBufferSize, " checksum: %d\n", table_options_.checksum);
310 ret.append(buffer);
311 snprintf(buffer, kBufferSize, " no_block_cache: %d\n",
312 table_options_.no_block_cache);
313 ret.append(buffer);
314 snprintf(buffer, kBufferSize, " block_cache: %p\n",
315 static_cast<void*>(table_options_.block_cache.get()));
316 ret.append(buffer);
317 if (table_options_.block_cache) {
318 const char* block_cache_name = table_options_.block_cache->Name();
319 if (block_cache_name != nullptr) {
320 snprintf(buffer, kBufferSize, " block_cache_name: %s\n",
321 block_cache_name);
322 ret.append(buffer);
323 }
324 ret.append(" block_cache_options:\n");
325 ret.append(table_options_.block_cache->GetPrintableOptions());
326 }
327 snprintf(buffer, kBufferSize, " block_cache_compressed: %p\n",
328 static_cast<void*>(table_options_.block_cache_compressed.get()));
329 ret.append(buffer);
330 if (table_options_.block_cache_compressed) {
331 const char* block_cache_compressed_name =
332 table_options_.block_cache_compressed->Name();
333 if (block_cache_compressed_name != nullptr) {
334 snprintf(buffer, kBufferSize, " block_cache_name: %s\n",
335 block_cache_compressed_name);
336 ret.append(buffer);
337 }
338 ret.append(" block_cache_compressed_options:\n");
339 ret.append(table_options_.block_cache_compressed->GetPrintableOptions());
340 }
341 snprintf(buffer, kBufferSize, " persistent_cache: %p\n",
342 static_cast<void*>(table_options_.persistent_cache.get()));
343 ret.append(buffer);
344 if (table_options_.persistent_cache) {
345 snprintf(buffer, kBufferSize, " persistent_cache_options:\n");
346 ret.append(buffer);
347 ret.append(table_options_.persistent_cache->GetPrintableOptions());
348 }
349 snprintf(buffer, kBufferSize, " block_size: %" ROCKSDB_PRIszt"zu" "\n",
350 table_options_.block_size);
351 ret.append(buffer);
352 snprintf(buffer, kBufferSize, " block_size_deviation: %d\n",
353 table_options_.block_size_deviation);
354 ret.append(buffer);
355 snprintf(buffer, kBufferSize, " block_restart_interval: %d\n",
356 table_options_.block_restart_interval);
357 ret.append(buffer);
358 snprintf(buffer, kBufferSize, " index_block_restart_interval: %d\n",
359 table_options_.index_block_restart_interval);
360 ret.append(buffer);
361 snprintf(buffer, kBufferSize, " metadata_block_size: %" PRIu64"l" "u" "\n",
362 table_options_.metadata_block_size);
363 ret.append(buffer);
364 snprintf(buffer, kBufferSize, " partition_filters: %d\n",
365 table_options_.partition_filters);
366 ret.append(buffer);
367 snprintf(buffer, kBufferSize, " use_delta_encoding: %d\n",
368 table_options_.use_delta_encoding);
369 ret.append(buffer);
370 snprintf(buffer, kBufferSize, " filter_policy: %s\n",
371 table_options_.filter_policy == nullptr
372 ? "nullptr"
373 : table_options_.filter_policy->Name());
374 ret.append(buffer);
375 snprintf(buffer, kBufferSize, " whole_key_filtering: %d\n",
376 table_options_.whole_key_filtering);
377 ret.append(buffer);
378 snprintf(buffer, kBufferSize, " verify_compression: %d\n",
379 table_options_.verify_compression);
380 ret.append(buffer);
381 snprintf(buffer, kBufferSize, " read_amp_bytes_per_bit: %d\n",
382 table_options_.read_amp_bytes_per_bit);
383 ret.append(buffer);
384 snprintf(buffer, kBufferSize, " format_version: %d\n",
385 table_options_.format_version);
386 ret.append(buffer);
387 snprintf(buffer, kBufferSize, " enable_index_compression: %d\n",
388 table_options_.enable_index_compression);
389 ret.append(buffer);
390 snprintf(buffer, kBufferSize, " block_align: %d\n",
391 table_options_.block_align);
392 ret.append(buffer);
393 return ret;
394}
395
396#ifndef ROCKSDB_LITE
397namespace {
398bool SerializeSingleBlockBasedTableOption(
399 std::string* opt_string, const BlockBasedTableOptions& bbt_options,
400 const std::string& name, const std::string& delimiter) {
401 auto iter = block_based_table_type_info.find(name);
402 if (iter == block_based_table_type_info.end()) {
403 return false;
404 }
405 auto& opt_info = iter->second;
406 const char* opt_address =
407 reinterpret_cast<const char*>(&bbt_options) + opt_info.offset;
408 std::string value;
409 bool result = SerializeSingleOptionHelper(opt_address, opt_info.type, &value);
410 if (result) {
411 *opt_string = name + "=" + value + delimiter;
412 }
413 return result;
414}
415} // namespace
416
417Status BlockBasedTableFactory::GetOptionString(
418 std::string* opt_string, const std::string& delimiter) const {
419 assert(opt_string)(static_cast<void> (0));
420 opt_string->clear();
421 for (auto iter = block_based_table_type_info.begin();
422 iter != block_based_table_type_info.end(); ++iter) {
423 if (iter->second.verification == OptionVerificationType::kDeprecated) {
424 // If the option is no longer used in rocksdb and marked as deprecated,
425 // we skip it in the serialization.
426 continue;
427 }
428 std::string single_output;
429 bool result = SerializeSingleBlockBasedTableOption(
430 &single_output, table_options_, iter->first, delimiter);
431 assert(result)(static_cast<void> (0));
432 if (result) {
433 opt_string->append(single_output);
434 }
435 }
436 return Status::OK();
437}
438#else
439Status BlockBasedTableFactory::GetOptionString(
440 std::string* /*opt_string*/, const std::string& /*delimiter*/) const {
441 return Status::OK();
442}
443#endif // !ROCKSDB_LITE
444
445const BlockBasedTableOptions& BlockBasedTableFactory::table_options() const {
446 return table_options_;
447}
448
449#ifndef ROCKSDB_LITE
450namespace {
451std::string ParseBlockBasedTableOption(const std::string& name,
452 const std::string& org_value,
453 BlockBasedTableOptions* new_options,
454 bool input_strings_escaped = false,
455 bool ignore_unknown_options = false) {
456 const std::string& value =
457 input_strings_escaped ? UnescapeOptionString(org_value) : org_value;
458 if (!input_strings_escaped) {
459 // if the input string is not escaped, it means this function is
460 // invoked from SetOptions, which takes the old format.
461 if (name == "block_cache" || name == "block_cache_compressed") {
462 // cache options can be specified in the following format
463 // "block_cache={capacity=1M;num_shard_bits=4;
464 // strict_capacity_limit=true;high_pri_pool_ratio=0.5;}"
465 // To support backward compatibility, the following format
466 // is also supported.
467 // "block_cache=1M"
468 std::shared_ptr<Cache> cache;
469 // block_cache is specified in format block_cache=<cache_size>.
470 if (value.find('=') == std::string::npos) {
471 cache = NewLRUCache(ParseSizeT(value));
472 } else {
473 LRUCacheOptions cache_opts;
474 if (!ParseOptionHelper(reinterpret_cast<char*>(&cache_opts),
475 OptionType::kLRUCacheOptions, value)) {
476 return "Invalid cache options";
477 }
478 cache = NewLRUCache(cache_opts);
479 }
480
481 if (name == "block_cache") {
482 new_options->block_cache = cache;
483 } else {
484 new_options->block_cache_compressed = cache;
485 }
486 return "";
487 } else if (name == "filter_policy") {
488 // Expect the following format
489 // bloomfilter:int:bool
490 const std::string kName = "bloomfilter:";
491 if (value.compare(0, kName.size(), kName) != 0) {
492 return "Invalid filter policy name";
493 }
494 size_t pos = value.find(':', kName.size());
495 if (pos == std::string::npos) {
496 return "Invalid filter policy config, missing bits_per_key";
497 }
498 int bits_per_key =
499 ParseInt(trim(value.substr(kName.size(), pos - kName.size())));
500 bool use_block_based_builder =
501 ParseBoolean("use_block_based_builder", trim(value.substr(pos + 1)));
502 new_options->filter_policy.reset(
503 NewBloomFilterPolicy(bits_per_key, use_block_based_builder));
504 return "";
505 }
506 }
507 const auto iter = block_based_table_type_info.find(name);
508 if (iter == block_based_table_type_info.end()) {
509 if (ignore_unknown_options) {
510 return "";
511 } else {
512 return "Unrecognized option";
513 }
514 }
515 const auto& opt_info = iter->second;
516 if (opt_info.verification != OptionVerificationType::kDeprecated &&
517 !ParseOptionHelper(reinterpret_cast<char*>(new_options) + opt_info.offset,
518 opt_info.type, value)) {
519 return "Invalid value";
520 }
521 return "";
522}
523} // namespace
524
525Status GetBlockBasedTableOptionsFromString(
526 const BlockBasedTableOptions& table_options, const std::string& opts_str,
527 BlockBasedTableOptions* new_table_options) {
528 std::unordered_map<std::string, std::string> opts_map;
529 Status s = StringToMap(opts_str, &opts_map);
530 if (!s.ok()) {
531 return s;
532 }
533
534 return GetBlockBasedTableOptionsFromMap(table_options, opts_map,
535 new_table_options);
536}
537
538Status GetBlockBasedTableOptionsFromMap(
539 const BlockBasedTableOptions& table_options,
540 const std::unordered_map<std::string, std::string>& opts_map,
541 BlockBasedTableOptions* new_table_options, bool input_strings_escaped,
542 bool ignore_unknown_options) {
543 assert(new_table_options)(static_cast<void> (0));
544 *new_table_options = table_options;
545 for (const auto& o : opts_map) {
546 auto error_message = ParseBlockBasedTableOption(
547 o.first, o.second, new_table_options, input_strings_escaped,
548 ignore_unknown_options);
549 if (error_message != "") {
550 const auto iter = block_based_table_type_info.find(o.first);
551 if (iter == block_based_table_type_info.end() ||
552 !input_strings_escaped || // !input_strings_escaped indicates
553 // the old API, where everything is
554 // parsable.
555 (iter->second.verification != OptionVerificationType::kByName &&
556 iter->second.verification !=
557 OptionVerificationType::kByNameAllowNull &&
558 iter->second.verification !=
559 OptionVerificationType::kByNameAllowFromNull &&
560 iter->second.verification != OptionVerificationType::kDeprecated)) {
561 // Restore "new_options" to the default "base_options".
562 *new_table_options = table_options;
563 return Status::InvalidArgument("Can't parse BlockBasedTableOptions:",
564 o.first + " " + error_message);
565 }
566 }
567 }
568 return Status::OK();
569}
570
571Status VerifyBlockBasedTableFactory(
572 const BlockBasedTableFactory* base_tf,
573 const BlockBasedTableFactory* file_tf,
574 OptionsSanityCheckLevel sanity_check_level) {
575 if ((base_tf != nullptr) != (file_tf != nullptr) &&
1
Assuming the condition is true
2
Assuming pointer value is null
4
Taking false branch
576 sanity_check_level > kSanityLevelNone) {
3
Assuming 'sanity_check_level' is <= kSanityLevelNone
577 return Status::Corruption(
578 "[RocksDBOptionsParser]: Inconsistent TableFactory class type");
579 }
580 if (base_tf == nullptr) {
5
Taking false branch
581 return Status::OK();
582 }
583 assert(file_tf != nullptr)(static_cast<void> (0));
584
585 const auto& base_opt = base_tf->table_options();
586 const auto& file_opt = file_tf->table_options();
6
Called C++ object pointer is null
587
588 for (auto& pair : block_based_table_type_info) {
589 if (pair.second.verification == OptionVerificationType::kDeprecated) {
590 // We skip checking deprecated variables as they might
591 // contain random values since they might not be initialized
592 continue;
593 }
594 if (BBTOptionSanityCheckLevel(pair.first) <= sanity_check_level) {
595 if (!AreEqualOptions(reinterpret_cast<const char*>(&base_opt),
596 reinterpret_cast<const char*>(&file_opt),
597 pair.second, pair.first, nullptr)) {
598 return Status::Corruption(
599 "[RocksDBOptionsParser]: "
600 "failed the verification on BlockBasedTableOptions::",
601 pair.first);
602 }
603 }
604 }
605 return Status::OK();
606}
607#endif // !ROCKSDB_LITE
608
609TableFactory* NewBlockBasedTableFactory(
610 const BlockBasedTableOptions& _table_options) {
611 return new BlockBasedTableFactory(_table_options);
612}
613
614const std::string BlockBasedTableFactory::kName = "BlockBasedTable";
615const std::string BlockBasedTablePropertyNames::kIndexType =
616 "rocksdb.block.based.table.index.type";
617const std::string BlockBasedTablePropertyNames::kWholeKeyFiltering =
618 "rocksdb.block.based.table.whole.key.filtering";
619const std::string BlockBasedTablePropertyNames::kPrefixFiltering =
620 "rocksdb.block.based.table.prefix.filtering";
621const std::string kHashIndexPrefixesBlock = "rocksdb.hashindex.prefixes";
622const std::string kHashIndexPrefixesMetadataBlock =
623 "rocksdb.hashindex.metadata";
624const std::string kPropTrue = "1";
625const std::string kPropFalse = "0";
626
627} // namespace rocksdb