diff --git a/rocksdb/_rocksdb.pyx b/rocksdb/_rocksdb.pyx index e7915e4e13ae08ad2598810e5c12fc9daac6b45d..478f59c0ee1362d5018d43a5343b883f4136f737 100644 --- a/rocksdb/_rocksdb.pyx +++ b/rocksdb/_rocksdb.pyx @@ -191,10 +191,12 @@ cdef class PyFilterPolicy(object): cdef const filter_policy.FilterPolicy* get_policy(self): return NULL + cdef set_info_log(self, shared_ptr[logger.Logger] info_log): + pass @cython.internal cdef class PyGenericFilterPolicy(PyFilterPolicy): - cdef filter_policy.FilterPolicy* policy + cdef filter_policy.FilterPolicyWrapper* policy cdef object ob def __cinit__(self, object ob): @@ -203,7 +205,7 @@ cdef class PyGenericFilterPolicy(PyFilterPolicy): raise TypeError("Cannot set filter policy: %s" % ob) self.ob = ob - self.policy = <filter_policy.FilterPolicy*> new filter_policy.FilterPolicyWrapper( + self.policy = new filter_policy.FilterPolicyWrapper( bytes_to_string(ob.name()), <void*>ob, create_filter_callback, @@ -217,26 +219,44 @@ cdef class PyGenericFilterPolicy(PyFilterPolicy): return self.ob cdef const filter_policy.FilterPolicy* get_policy(self): - return self.policy + return <filter_policy.FilterPolicy*> self.policy + + cdef set_info_log(self, shared_ptr[logger.Logger] info_log): + self.policy.set_info_log(info_log) + cdef void create_filter_callback( void* ctx, + logger.Logger* log, + string& error_msg, const Slice* keys, int n, string* dst) with gil: - ret = (<object>ctx).create_filter( - [slice_to_bytes(keys[i]) for i in range(n)]) - dst.append(bytes_to_string(ret)) + try: + ret = (<object>ctx).create_filter( + [slice_to_bytes(keys[i]) for i in range(n)]) + dst.append(bytes_to_string(ret)) + except BaseException as error: + tb = traceback.format_exc() + logger.Log(log, "Error in create filter callback: %s", <bytes>tb) + error_msg.assign(<bytes>str(error)) cdef cpp_bool key_may_match_callback( void* ctx, + logger.Logger* log, + string& error_msg, const Slice& key, const Slice& filt) with gil: - return (<object>ctx).key_may_match( - slice_to_bytes(key), - slice_to_bytes(filt)) + try: + return (<object>ctx).key_may_match( + slice_to_bytes(key), + slice_to_bytes(filt)) + except BaseException as error: + tb = traceback.format_exc() + logger.Log(log, "Error in key_mach_match callback: %s", <bytes>tb) + error_msg.assign(<bytes>str(error)) @cython.internal cdef class PyBloomFilterPolicy(PyFilterPolicy): @@ -1107,6 +1127,9 @@ cdef class DB(object): if opts.py_comparator is not None: opts.py_comparator.set_info_log(info_log) + if opts.py_filter_policy is not None: + opts.py_filter_policy.set_info_log(info_log) + self.opts = opts self.opts.in_use = True diff --git a/rocksdb/cpp/filter_policy_wrapper.hpp b/rocksdb/cpp/filter_policy_wrapper.hpp index 6b88f1d65f58a1e07189233f2fdf351183ba1592..45be214a3c234b8ab42152eb07f9192408d05773 100644 --- a/rocksdb/cpp/filter_policy_wrapper.hpp +++ b/rocksdb/cpp/filter_policy_wrapper.hpp @@ -1,20 +1,27 @@ #include "rocksdb/filter_policy.h" +#include "rocksdb/env.h" +#include <stdexcept> using std::string; using rocksdb::FilterPolicy; using rocksdb::Slice; +using rocksdb::Logger; namespace py_rocks { class FilterPolicyWrapper: public FilterPolicy { public: typedef void (*create_filter_func)( void* ctx, + Logger*, + string&, const Slice* keys, int n, string* dst); typedef bool (*key_may_match_func)( void* ctx, + Logger*, + string&, const Slice& key, const Slice& filter); @@ -31,29 +38,52 @@ namespace py_rocks { void CreateFilter(const Slice* keys, int n, std::string* dst) const { + string error_msg; + this->create_filter_callback( this->ctx, + this->info_log.get(), + error_msg, keys, n, dst); + + if (error_msg.size()) { + throw std::runtime_error(error_msg.c_str()); + } } bool KeyMayMatch(const Slice& key, const Slice& filter) const { - return this->key_may_match_callback( + string error_msg; + bool val; + + val = this->key_may_match_callback( this->ctx, + this->info_log.get(), + error_msg, key, filter); + + if (error_msg.size()) { + throw std::runtime_error(error_msg.c_str()); + } + return val; } const char* Name() const { return this->name.c_str(); } + void set_info_log(std::shared_ptr<Logger> info_log) { + this->info_log = info_log; + } + private: string name; void* ctx; create_filter_func create_filter_callback; key_may_match_func key_may_match_callback; + std::shared_ptr<Logger> info_log; }; } diff --git a/rocksdb/filter_policy.pxd b/rocksdb/filter_policy.pxd index 52e0636b2e8e3f55ceb0d2095b39b46a1ebb6295..03face53abe5b46862b2c89e964f0ccec9cf95e1 100644 --- a/rocksdb/filter_policy.pxd +++ b/rocksdb/filter_policy.pxd @@ -2,6 +2,8 @@ from libcpp cimport bool as cpp_bool from libcpp.string cimport string from libc.string cimport const_char from slice_ cimport Slice +from std_memory cimport shared_ptr +from logger cimport Logger cdef extern from "rocksdb/filter_policy.h" namespace "rocksdb": cdef cppclass FilterPolicy: @@ -11,8 +13,20 @@ cdef extern from "rocksdb/filter_policy.h" namespace "rocksdb": cdef extern const FilterPolicy* NewBloomFilterPolicy(int) nogil except+ -ctypedef void (*create_filter_func)(void*, const Slice*, int, string*) -ctypedef cpp_bool (*key_may_match_func)(void*, const Slice&, const Slice&) +ctypedef void (*create_filter_func)( + void*, + Logger*, + string&, + const Slice*, + int, + string*) + +ctypedef cpp_bool (*key_may_match_func)( + void*, + Logger*, + string&, + const Slice&, + const Slice&) cdef extern from "cpp/filter_policy_wrapper.hpp" namespace "py_rocks": cdef cppclass FilterPolicyWrapper: @@ -21,3 +35,5 @@ cdef extern from "cpp/filter_policy_wrapper.hpp" namespace "py_rocks": void*, create_filter_func, key_may_match_func) nogil except+ + + void set_info_log(shared_ptr[Logger]) nogil except+