CompactionFilterFactory-As-SidePlugin

背景

在稍微复杂点的 RocksDB 应用中,都少不了使用 CompactionFilter,虽然可以直接在 Options 中设置 CompactionFilter 对象,但我们还是更多地使用 CompactionFilterFactory,因为 CompactionFilter 经常是有状态的,而不是一个纯函数,所以需要动态创建并且在单个 subcompact 中维护其状态。

因为 C++ 没有语言级反射,要通过 ToplingDB 的 SidePlugin 来管理和配置 CompactionFilterFactory,我们就需要修改一点代码,主要是将我们自定义的 CompactionFilterFactory 注册到 SidePlugin 体系。

除了 CompactionFilterFactory,还有很多其它对象需要用相似的方式将它纳入 SidePlugin 体系,例如 Comparator, MergeOperator, EventHandler …,因为 CompactionFilterFactory 相比其它对象更加常用,所以我们在此以 CompactionFilterFactory 为例来展开。

迁移到 ToplingDB,主要是将插件注册到 SidePlugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 文件 my_filter.cc
//
#include <topling/side_plugin_factory.h> // 注册插件,需要该头文件

// MySimpleCompactionFilterFactory 是现有代码,不需要任何改动
class MySimpleCompactionFilterFactory : public CompactionFilterFactory {
public:
// implementation details
};

// 增加这一行,注册插件,MySimpleCompactionFilterFactory 必须有默认构造函数
ROCKSDB_REG_DEFAULT_CONS(MySimpleCompactionFilterFactory, CompactionFilterFactory);

// MyComplexCompactionFilterFactory 是现有代码,不需要任何改动
class MyComplexCompactionFilterFactory : public CompactionFilterFactory {
std::string str_conf_option;
int int_conf_option = 0; // 0 is default
public:
// implementation details

// 原本需要在用户代码中创建并配置这个复杂的 MyComplexCompactionFilterFactory,
// 现在可以在 json/yaml 中配置 str_conf_option 和 int_conf_option
MyComplexCompactionFilterFactory(const json& js, const SidePluginRepo& repo) {
ROCKSDB_JSON_OPT_PROP(js, str_conf_option);
ROCKSDB_JSON_OPT_PROP(js, int_conf_option);
}
};

// 增加这一行,注册插件,必须有构造函数(const json&, const SidePluginRepo&)
ROCKSDB_REG_JSON_REPO_CONS(MyComplexCompactionFilterFactory, CompactionFilterFactory);

注意:注册插件之后,该文件(my_filter.cc)中的所有符号可能都不会被其它文件中的代码引用,在这种情况下,如果将 my_filter.o 编译为静态链接库,再把该静态链接库链接到可执行文件时,my_filter.o 将会被链接器删除,所以,插件必须以 .o 的形式或动态库(.so)的形式被链接,不能以静态库的形式被链接!

然后,在 yaml 配置文件中(如果需要,您可尝试自己将此 yaml 转化为 json):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
CompactionFilterFactory:
simple_filter1: MySimpleCompactionFilterFactory
simple_filter2:
class: MySimpleCompactionFilterFactory
params: # defining params is not required here
complex_filter:
class: MyComplexCompactionFilterFactory
params:
str_conf_option: some string
int_conf_option: 123
DBOptions:
dbo:
create_if_missing: true
CFOptions:
simple_cf:
compaction_filter_factory: "$simple_filter1"
complex_cf:
compaction_filter_factory: "$complex_filter"
databases:
mydb1:
method: DB::Open
params:
db_options: "$dbo"
column_families:
default: "$simple_cf"
complex: "$complex_cf"
path: /path/to/mydb1
mydb2:
method: DB::Open
params:
db_options: "$dbo"
column_families:
default: "$simple_cf"
complex: "$complex_cf"
path: /path/to/mydb2

最后,按照文档 101,导入该配置,打开 db。