From 0dca8c379e123154dc1db95394f55177214d8350 Mon Sep 17 00:00:00 2001
From: hofmockel <dreagonfly@gmx.de>
Date: Sun, 26 Jan 2014 09:47:04 +0100
Subject: [PATCH] Better error reporting in python filter policy

---
 rocksdb/_rocksdb.pyx                  | 41 +++++++++++++++++++++------
 rocksdb/cpp/filter_policy_wrapper.hpp | 32 ++++++++++++++++++++-
 rocksdb/filter_policy.pxd             | 20 +++++++++++--
 3 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/rocksdb/_rocksdb.pyx b/rocksdb/_rocksdb.pyx
index e7915e4..478f59c 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 6b88f1d..45be214 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 52e0636..03face5 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+
-- 
GitLab