From 41fc293cb8c92e1c9d00174b4c7a1b8000183c80 Mon Sep 17 00:00:00 2001
From: hofmockel <dreagonfly@gmx.de>
Date: Sun, 26 Jan 2014 10:45:06 +0100
Subject: [PATCH] Better error reporting for a python prefix extractor

---
 rocksdb/_rocksdb.pyx                    | 61 ++++++++++++++-------
 rocksdb/cpp/slice_transform_wrapper.hpp | 70 ++++++++++++++++++++++---
 rocksdb/slice_transform.pxd             | 23 ++++++--
 3 files changed, 125 insertions(+), 29 deletions(-)

diff --git a/rocksdb/_rocksdb.pyx b/rocksdb/_rocksdb.pyx
index 0e72cb7..49b8bc7 100644
--- a/rocksdb/_rocksdb.pyx
+++ b/rocksdb/_rocksdb.pyx
@@ -458,7 +458,7 @@ LRUCache = PyLRUCache
 ### Here comes the stuff for SliceTransform
 @cython.internal
 cdef class PySliceTransform(object):
-    cdef slice_transform.SliceTransform* transfomer
+    cdef slice_transform.SliceTransformWrapper* transfomer
     cdef object ob
 
     def __cinit__(self, object ob):
@@ -467,13 +467,12 @@ cdef class PySliceTransform(object):
             raise TypeError("%s is not of type %s" % (ob, ISliceTransform))
 
         self.ob = ob
-        self.transfomer = <slice_transform.SliceTransform*>(
-            new slice_transform.SliceTransformWrapper(
+        self.transfomer = new slice_transform.SliceTransformWrapper(
                 bytes_to_string(ob.name()),
                 <void*>ob,
                 slice_transform_callback,
                 slice_in_domain_callback,
-                slice_in_range_callback))
+                slice_in_range_callback)
 
     def __dealloc__(self):
         if not self.transfomer == NULL:
@@ -483,9 +482,18 @@ cdef class PySliceTransform(object):
         return self.ob
 
     cdef slice_transform.SliceTransform* get_transformer(self):
-        return self.transfomer
+        return <slice_transform.SliceTransform*> self.transfomer
+
+    cdef set_info_log(self, shared_ptr[logger.Logger] info_log):
+        self.transfomer.set_info_log(info_log)
+
+
+cdef Slice slice_transform_callback(
+    void* ctx,
+    logger.Logger* log,
+    string& error_msg,
+    const Slice& src) with gil:
 
-cdef Slice slice_transform_callback(void* ctx, const Slice& src) with gil:
     cdef size_t offset
     cdef size_t size
 
@@ -498,26 +506,36 @@ cdef Slice slice_transform_callback(void* ctx, const Slice& src) with gil:
             raise Exception(msg  % (offset, size, src.size()))
 
         return Slice(src.data() + offset, size)
-    except Exception as error:
-        print error
-        # TODO: Use the rocksdb logger
-        return src
+    except BaseException as error:
+        tb = traceback.format_exc()
+        logger.Log(log, "Error in slice transfrom callback: %s", <bytes>tb)
+        error_msg.assign(<bytes>str(error))
+
+cdef cpp_bool slice_in_domain_callback(
+    void* ctx,
+    logger.Logger* log,
+    string& error_msg,
+    const Slice& src) with gil:
 
-cdef cpp_bool slice_in_domain_callback(void* ctx, const Slice& src) with gil:
     try:
         return (<object>ctx).in_domain(slice_to_bytes(src))
-    except Exception as error:
-        print error
-        # TODO: Use the rocksdb logger
-        return False
+    except BaseException as error:
+        tb = traceback.format_exc()
+        logger.Log(log, "Error in slice transfrom callback: %s", <bytes>tb)
+        error_msg.assign(<bytes>str(error))
+
+cdef cpp_bool slice_in_range_callback(
+    void* ctx,
+    logger.Logger* log,
+    string& error_msg,
+    const Slice& src) with gil:
 
-cdef cpp_bool slice_in_range_callback(void* ctx, const Slice& src) with gil:
     try:
         return (<object>ctx).in_range(slice_to_bytes(src))
-    except Exception as error:
-        print error
-        # TODO: Use rocksdb logger
-        return False
+    except BaseException as error:
+        tb = traceback.format_exc()
+        logger.Log(log, "Error in slice transfrom callback: %s", <bytes>tb)
+        error_msg.assign(<bytes>str(error))
 
 ###########################################
 cdef class CompressionType(object):
@@ -1120,6 +1138,9 @@ cdef class DB(object):
         if opts.py_filter_policy is not None:
             opts.py_filter_policy.set_info_log(info_log)
 
+        if opts.prefix_extractor is not None:
+            opts.py_prefix_extractor.set_info_log(info_log)
+
         self.opts = opts
         self.opts.in_use = True
 
diff --git a/rocksdb/cpp/slice_transform_wrapper.hpp b/rocksdb/cpp/slice_transform_wrapper.hpp
index 0bc310f..4e618ee 100644
--- a/rocksdb/cpp/slice_transform_wrapper.hpp
+++ b/rocksdb/cpp/slice_transform_wrapper.hpp
@@ -1,16 +1,33 @@
 #include <string>
 #include "rocksdb/slice_transform.h"
+#include "rocksdb/env.h"
+#include <stdexcept>
 
 using std::string;
 using rocksdb::SliceTransform;
 using rocksdb::Slice;
+using rocksdb::Logger;
 
 namespace py_rocks {
     class SliceTransformWrapper: public SliceTransform {
         public:
-            typedef Slice (*transform_func)(void*, const Slice&);
-            typedef bool (*in_domain_func)(void*, const Slice&);
-            typedef bool (*in_range_func)(void*, const Slice&);
+            typedef Slice (*transform_func)(
+                void*,
+                Logger*,
+                string&,
+                const Slice&);
+
+            typedef bool (*in_domain_func)(
+                void*,
+                Logger*,
+                string&,
+                const Slice&);
+
+            typedef bool (*in_range_func)(
+                void*,
+                Logger*,
+                string&,
+                const Slice&);
 
             SliceTransformWrapper(
                 string name,
@@ -30,15 +47,55 @@ namespace py_rocks {
             }
 
             Slice Transform(const Slice& src) const {
-                return this->transfrom_callback(this->ctx, src);
+                string error_msg;
+                Slice val;
+
+                val = this->transfrom_callback(
+                    this->ctx,
+                    this->info_log.get(),
+                    error_msg,
+                    src);
+
+                if (error_msg.size()) {
+                    throw std::runtime_error(error_msg.c_str());
+                }
+                return val;
             }
 
             bool InDomain(const Slice& src) const {
-                return this->in_domain_callback(this->ctx, src);
+                string error_msg;
+                bool val;
+
+                val = this->in_domain_callback(
+                    this->ctx,
+                    this->info_log.get(),
+                    error_msg,
+                    src);
+
+                if (error_msg.size()) {
+                    throw std::runtime_error(error_msg.c_str());
+                }
+                return val;
             }
 
             bool InRange(const Slice& dst) const {
-                return this->in_range_callback(this->ctx, dst);
+                string error_msg;
+                bool val;
+
+                val = this->in_range_callback(
+                    this->ctx,
+                    this->info_log.get(),
+                    error_msg,
+                    dst);
+
+                if (error_msg.size()) {
+                    throw std::runtime_error(error_msg.c_str());
+                }
+                return val;
+            }
+
+            void set_info_log(std::shared_ptr<Logger> info_log) {
+                this->info_log = info_log;
             }
 
         private:
@@ -47,5 +104,6 @@ namespace py_rocks {
             transform_func transfrom_callback;
             in_domain_func in_domain_callback;
             in_range_func in_range_callback;
+            std::shared_ptr<Logger> info_log;
     };
 }
diff --git a/rocksdb/slice_transform.pxd b/rocksdb/slice_transform.pxd
index 7a26a84..34a61f0 100644
--- a/rocksdb/slice_transform.pxd
+++ b/rocksdb/slice_transform.pxd
@@ -1,14 +1,30 @@
 from slice_ cimport Slice
 from libcpp.string cimport string
 from libcpp cimport bool as cpp_bool
+from logger cimport Logger
+from std_memory cimport shared_ptr
 
 cdef extern from "rocksdb/slice_transform.h" namespace "rocksdb":
     cdef cppclass SliceTransform:
         pass
 
-ctypedef Slice (*transform_func)(void*, const Slice&)
-ctypedef cpp_bool (*in_domain_func)(void*, const Slice&)
-ctypedef cpp_bool (*in_range_func)(void*, const Slice&)
+ctypedef Slice (*transform_func)(
+    void*,
+    Logger*,
+    string&,
+    const Slice&)
+
+ctypedef cpp_bool (*in_domain_func)(
+    void*,
+    Logger*,
+    string&,
+    const Slice&)
+
+ctypedef cpp_bool (*in_range_func)(
+    void*,
+    Logger*,
+    string&,
+    const Slice&)
 
 cdef extern from "cpp/slice_transform_wrapper.hpp" namespace "py_rocks":
     cdef cppclass SliceTransformWrapper:
@@ -18,3 +34,4 @@ cdef extern from "cpp/slice_transform_wrapper.hpp" namespace "py_rocks":
                 transform_func,
                 in_domain_func,
                 in_range_func) nogil except+
+        void set_info_log(shared_ptr[Logger]) nogil except+
-- 
GitLab