Skip to content

Commit 1369c7b

Browse files
anand1976facebook-github-bot
authored andcommitted
Allow a user defined index to be configured from a string (facebook#13880)
Summary: Allow a user defined index to be configured from a string Pull Request resolved: facebook#13880 Test Plan: Add a unit test in table_test.cc Reviewed By: bikash-c Differential Revision: D80237701 Pulled By: anand1976 fbshipit-source-id: 8b3d0bcdfbb4bb76803916ea1b1f940a4d985dfd
1 parent 7e9c960 commit 1369c7b

4 files changed

Lines changed: 108 additions & 0 deletions

File tree

include/rocksdb/user_defined_index.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ class UserDefinedIndexFactory : public Customizable {
150150
public:
151151
virtual ~UserDefinedIndexFactory() = default;
152152

153+
static const char* Type() { return "UserDefinedIndexFactory"; }
154+
155+
static Status CreateFromString(
156+
const ConfigOptions& config_options, const std::string& value,
157+
std::shared_ptr<UserDefinedIndexFactory>* factory);
158+
153159
// Create a new builder for user-defined index.
154160
virtual UserDefinedIndexBuilder* NewBuilder() const = 0;
155161

table/block_based/block_based_table_factory.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "rocksdb/flush_block_policy.h"
2626
#include "rocksdb/rocksdb_namespace.h"
2727
#include "rocksdb/table.h"
28+
#include "rocksdb/user_defined_index.h"
29+
#include "rocksdb/utilities/customizable_util.h"
2830
#include "rocksdb/utilities/options_type.h"
2931
#include "table/block_based/block_based_table_builder.h"
3032
#include "table/block_based/block_based_table_reader.h"
@@ -312,6 +314,11 @@ static struct BlockBasedTableTypeInfo {
312314
OptionTypeInfo::AsCustomSharedPtr<const FilterPolicy>(
313315
offsetof(struct BlockBasedTableOptions, filter_policy),
314316
OptionVerificationType::kByNameAllowFromNull)},
317+
{"user_defined_index_factory",
318+
OptionTypeInfo::AsCustomSharedPtr<UserDefinedIndexFactory>(
319+
offsetof(struct BlockBasedTableOptions,
320+
user_defined_index_factory),
321+
OptionVerificationType::kByNameAllowFromNull)},
315322
{"whole_key_filtering",
316323
{offsetof(struct BlockBasedTableOptions, whole_key_filtering),
317324
OptionType::kBoolean, OptionVerificationType::kNormal}},
@@ -1011,6 +1018,13 @@ TableFactory* NewBlockBasedTableFactory(
10111018
return new BlockBasedTableFactory(_table_options);
10121019
}
10131020

1021+
Status UserDefinedIndexFactory::CreateFromString(
1022+
const ConfigOptions& config_options, const std::string& value,
1023+
std::shared_ptr<UserDefinedIndexFactory>* factory) {
1024+
return LoadSharedObject<UserDefinedIndexFactory>(config_options, value,
1025+
factory);
1026+
}
1027+
10141028
const std::string BlockBasedTablePropertyNames::kIndexType =
10151029
"rocksdb.block.based.table.index.type";
10161030
const std::string BlockBasedTablePropertyNames::kWholeKeyFiltering =

table/table_test.cc

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "rocksdb/trace_record.h"
5454
#include "rocksdb/unique_id.h"
5555
#include "rocksdb/user_defined_index.h"
56+
#include "rocksdb/utilities/object_registry.h"
5657
#include "rocksdb/write_buffer_manager.h"
5758
#include "table/block_based/block.h"
5859
#include "table/block_based/block_based_table_builder.h"
@@ -8068,6 +8069,92 @@ TEST_F(UserDefinedIndexTest, IngestFailTest) {
80688069
ASSERT_OK(db->Close());
80698070
ASSERT_OK(DestroyDB(dbname, options));
80708071
}
8072+
8073+
TEST_F(UserDefinedIndexTest, ConfigTest) {
8074+
Options options;
8075+
BlockBasedTableOptions table_options;
8076+
std::string dbname = test::PerThreadDBPath("user_defined_index_test");
8077+
std::string ingest_file = dbname + "test.sst";
8078+
8079+
// Set up the user-defined index factory
8080+
auto user_defined_index_factory =
8081+
std::make_shared<TestUserDefinedIndexFactory>();
8082+
table_options.user_defined_index_factory = user_defined_index_factory;
8083+
8084+
// Set up custom flush block policy that flushes every 3 keys
8085+
table_options.flush_block_policy_factory =
8086+
std::make_shared<CustomFlushBlockPolicyFactory>();
8087+
8088+
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
8089+
8090+
std::unique_ptr<SstFileWriter> writer;
8091+
writer.reset(new SstFileWriter(EnvOptions(), options));
8092+
ASSERT_OK(writer->Open(ingest_file));
8093+
8094+
// Add 100 keys instead of just 5
8095+
for (int i = 0; i < 100; i++) {
8096+
std::stringstream ss;
8097+
ss << std::setw(2) << std::setfill('0') << i;
8098+
std::string key = "key" + ss.str();
8099+
std::string value = "value" + ss.str();
8100+
ASSERT_OK(writer->Put(key, value));
8101+
}
8102+
ASSERT_OK(writer->Finish());
8103+
writer.reset();
8104+
8105+
table_options.user_defined_index_factory.reset();
8106+
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
8107+
// Set up the user-defined index factory
8108+
ObjectLibrary::Default().get()->AddFactory<UserDefinedIndexFactory>(
8109+
"test_index", [](const std::string& /* uri */,
8110+
std::unique_ptr<UserDefinedIndexFactory>* guard,
8111+
std::string* /* errmsg */) {
8112+
auto factory = new TestUserDefinedIndexFactory();
8113+
guard->reset(factory);
8114+
return guard->get();
8115+
});
8116+
ASSERT_OK(GetColumnFamilyOptionsFromString(
8117+
ConfigOptions(), options,
8118+
"block_based_table_factory={user_defined_index_factory=test_index;}",
8119+
&options));
8120+
8121+
std::unique_ptr<DB> db;
8122+
options.create_if_missing = true;
8123+
Status s = DB::Open(options, dbname, &db);
8124+
ASSERT_OK(s);
8125+
ASSERT_TRUE(db != nullptr);
8126+
ColumnFamilyHandle* cfh = nullptr;
8127+
ASSERT_OK(db->CreateColumnFamily(options, "new_cf", &cfh));
8128+
8129+
IngestExternalFileOptions ifo;
8130+
s = db->IngestExternalFile(cfh, {ingest_file}, ifo);
8131+
ASSERT_OK(s);
8132+
8133+
ReadOptions ro;
8134+
ro.table_index_factory = user_defined_index_factory.get();
8135+
std::unique_ptr<Iterator> iter(db->NewIterator(ro, cfh));
8136+
ASSERT_NE(iter, nullptr);
8137+
MultiScanArgs scan_opts;
8138+
std::unordered_map<std::string, std::string> property_bag;
8139+
property_bag["count"] = std::to_string(25);
8140+
scan_opts.insert(Slice("key20"), std::optional(property_bag));
8141+
iter->Prepare(scan_opts);
8142+
// Test that we can read all the keys
8143+
int key_count = 0;
8144+
for (iter->Seek(scan_opts.GetScanRanges()[0].range.start.value());
8145+
iter->Valid(); iter->Next()) {
8146+
key_count++;
8147+
}
8148+
ASSERT_GE(key_count, 25);
8149+
// The index may undercount by 2 blocks
8150+
ASSERT_LE(key_count, 30);
8151+
ASSERT_OK(iter->status());
8152+
iter.reset();
8153+
8154+
ASSERT_OK(db->DestroyColumnFamilyHandle(cfh));
8155+
ASSERT_OK(db->Close());
8156+
ASSERT_OK(DestroyDB(dbname, options));
8157+
}
80718158
} // namespace ROCKSDB_NAMESPACE
80728159

80738160
int main(int argc, char** argv) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow a user defined index to be configured from a string.

0 commit comments

Comments
 (0)