1 // Copyright (c) 2016, 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).
8 #if defined(LUA) && !defined(ROCKSDB_LITE)
20 #include "rocksdb/compaction_filter.h"
21 #include "rocksdb/env.h"
22 #include "rocksdb/slice.h"
23 #include "rocksdb/utilities/lua/rocks_lua_custom_library.h"
24 #include "rocksdb/utilities/lua/rocks_lua_util.h"
29 struct RocksLuaCompactionFilterOptions
{
30 // The lua script in string that implements all necessary CompactionFilter
31 // virtual functions. The specified lua_script must implement the following
32 // functions, which are Name and Filter, as described below.
34 // 0. The Name function simply returns a string representing the name of
35 // the lua script. If there's any erorr in the Name function, an
36 // empty string will be used.
39 // return "DefaultLuaCompactionFilter"
43 // 1. The script must contains a function called Filter, which implements
44 // CompactionFilter::Filter() , takes three input arguments, and returns
45 // three values as the following API:
47 // function Filter(level, key, existing_value)
49 // return is_filtered, is_changed, new_value
52 // Note that if ignore_value is set to true, then Filter should implement
55 // function Filter(level, key)
60 // If there're any error in the Filter() function, then it will keep
61 // the input key / value pair.
64 // The function must take three arguments (integer, string, string),
65 // which map to "level", "key", and "existing_value" passed from
69 // The function must return three values (boolean, boolean, string).
70 // - is_filtered: if the first return value is true, then it indicates
71 // the input key / value pair should be filtered.
72 // - is_changed: if the second return value is true, then it indicates
73 // the existing_value needs to be changed, and the resulting value
74 // is stored in the third return value.
75 // - new_value: if the second return value is true, then this third
76 // return value stores the new value of the input key / value pair.
79 // -- a filter that keeps all key-value pairs
80 // function Filter(level, key, existing_value)
81 // return false, false, ""
84 // -- a filter that keeps all keys and change their values to "Rocks"
85 // function Filter(level, key, existing_value)
86 // return false, true, "Rocks"
89 std::string lua_script
;
91 // If set to true, then existing_value will not be passed to the Filter
92 // function, and the Filter function only needs to return a single boolean
93 // flag indicating whether to filter out this key or not.
95 // function Filter(level, key)
99 bool ignore_value
= false;
101 // A boolean flag to determine whether to ignore snapshots.
102 bool ignore_snapshots
= false;
104 // When specified a non-null pointer, the first "error_limit_per_filter"
105 // errors of each CompactionFilter that is lua related will be included
107 std::shared_ptr
<Logger
> error_log
;
109 // The number of errors per CompactionFilter will be printed
111 int error_limit_per_filter
= 1;
113 // A string to luaL_reg array map that allows the Lua CompactionFilter
114 // to use custom C library. The string will be used as the library
116 std::vector
<std::shared_ptr
<RocksLuaCustomLibrary
>> libraries
;
118 ///////////////////////////////////////////////////////////////////////////
120 // The name of the Lua function in "lua_script" that implements
121 // CompactionFilter::FilterMergeOperand(). The function must take
122 // three input arguments (integer, string, string), which map to "level",
123 // "key", and "operand" passed from the RocksDB. In addition, the
124 // function must return a single boolean value, indicating whether
125 // to filter the input key / operand.
127 // DEFAULT: the default implementation always returns false.
128 // @see CompactionFilter::FilterMergeOperand
131 class RocksLuaCompactionFilterFactory
: public CompactionFilterFactory
{
133 explicit RocksLuaCompactionFilterFactory(
134 const RocksLuaCompactionFilterOptions opt
);
136 virtual ~RocksLuaCompactionFilterFactory() {}
138 std::unique_ptr
<CompactionFilter
> CreateCompactionFilter(
139 const CompactionFilter::Context
& context
) override
;
141 // Change the Lua script so that the next compaction after this
142 // function call will use the new Lua script.
143 void SetScript(const std::string
& new_script
);
145 // Obtain the current Lua script
146 std::string
GetScript();
148 const char* Name() const override
;
151 RocksLuaCompactionFilterOptions opt_
;
153 // A lock to protect "opt_" to make it dynamically changeable.
154 std::mutex opt_mutex_
;
157 // A wrapper class that invokes Lua script to perform CompactionFilter
159 class RocksLuaCompactionFilter
: public rocksdb::CompactionFilter
{
161 explicit RocksLuaCompactionFilter(const RocksLuaCompactionFilterOptions
& opt
)
163 lua_state_wrapper_(opt
.lua_script
, opt
.libraries
),
167 virtual bool Filter(int level
, const Slice
& key
, const Slice
& existing_value
,
168 std::string
* new_value
,
169 bool* value_changed
) const override
;
171 virtual bool FilterMergeOperand(int /*level*/, const Slice
& /*key*/,
172 const Slice
& /*operand*/) const override
{
175 virtual bool IgnoreSnapshots() const override
;
176 virtual const char* Name() const override
;
179 void LogLuaError(const char* format
, ...) const;
181 RocksLuaCompactionFilterOptions options_
;
182 LuaStateWrapper lua_state_wrapper_
;
183 mutable int error_count_
;
184 mutable std::string name_
;
188 } // namespace rocksdb
189 #endif // defined(LUA) && !defined(ROCKSDB_LITE)