Better error reporting in python comparators
* Written to the rocksdb log-file * raise an exception back to rocksdb
This commit is contained in:
parent
b600d3371f
commit
a83a15e1a8
3 changed files with 62 additions and 9 deletions
|
@ -109,9 +109,12 @@ cdef class PyComparator(object):
|
|||
cdef const comparator.Comparator* get_comparator(self):
|
||||
return NULL
|
||||
|
||||
cdef set_info_log(self, shared_ptr[logger.Logger] info_log):
|
||||
pass
|
||||
|
||||
@cython.internal
|
||||
cdef class PyGenericComparator(PyComparator):
|
||||
cdef const comparator.Comparator* comparator_ptr
|
||||
cdef comparator.ComparatorWrapper* comparator_ptr
|
||||
cdef object ob
|
||||
|
||||
def __cinit__(self, object ob):
|
||||
|
@ -121,11 +124,10 @@ cdef class PyGenericComparator(PyComparator):
|
|||
raise TypeError("Cannot set comparator: %s" % ob)
|
||||
|
||||
self.ob = ob
|
||||
self.comparator_ptr = <comparator.Comparator*>(
|
||||
new comparator.ComparatorWrapper(
|
||||
self.comparator_ptr = new comparator.ComparatorWrapper(
|
||||
bytes_to_string(ob.name()),
|
||||
<void*>ob,
|
||||
compare_callback))
|
||||
compare_callback)
|
||||
|
||||
def __dealloc__(self):
|
||||
if not self.comparator_ptr == NULL:
|
||||
|
@ -135,7 +137,10 @@ cdef class PyGenericComparator(PyComparator):
|
|||
return self.ob
|
||||
|
||||
cdef const comparator.Comparator* get_comparator(self):
|
||||
return self.comparator_ptr
|
||||
return <comparator.Comparator*> self.comparator_ptr
|
||||
|
||||
cdef set_info_log(self, shared_ptr[logger.Logger] info_log):
|
||||
self.comparator_ptr.set_info_log(info_log)
|
||||
|
||||
@cython.internal
|
||||
cdef class PyBytewiseComparator(PyComparator):
|
||||
|
@ -160,10 +165,17 @@ cdef class PyBytewiseComparator(PyComparator):
|
|||
|
||||
cdef int compare_callback(
|
||||
void* ctx,
|
||||
logger.Logger* log,
|
||||
string& error_msg,
|
||||
const Slice& a,
|
||||
const Slice& b) with gil:
|
||||
|
||||
return (<object>ctx).compare(slice_to_bytes(a), slice_to_bytes(b))
|
||||
try:
|
||||
return (<object>ctx).compare(slice_to_bytes(a), slice_to_bytes(b))
|
||||
except BaseException as error:
|
||||
tb = traceback.format_exc()
|
||||
logger.Log(log, "Error in compare callback: %s", <bytes>tb)
|
||||
error_msg.assign(<bytes>str(error))
|
||||
|
||||
BytewiseComparator = PyBytewiseComparator
|
||||
#########################################
|
||||
|
@ -1090,6 +1102,12 @@ cdef class DB(object):
|
|||
cython.address(self.db))
|
||||
|
||||
check_status(st)
|
||||
|
||||
# Inject the loggers into the python callbacks
|
||||
cdef shared_ptr[logger.Logger] info_log = self.db.GetOptions().info_log
|
||||
if opts.py_comparator is not None:
|
||||
opts.py_comparator.set_info_log(info_log)
|
||||
|
||||
self.opts = opts
|
||||
self.opts.in_use = True
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
from libcpp.string cimport string
|
||||
from slice_ cimport Slice
|
||||
from logger cimport Logger
|
||||
from std_memory cimport shared_ptr
|
||||
|
||||
cdef extern from "rocksdb/comparator.h" namespace "rocksdb":
|
||||
cdef cppclass Comparator:
|
||||
const char* Name()
|
||||
|
@ -7,8 +10,14 @@ cdef extern from "rocksdb/comparator.h" namespace "rocksdb":
|
|||
|
||||
cdef extern const Comparator* BytewiseComparator() nogil except +
|
||||
|
||||
ctypedef int (*compare_func)(void*, const Slice&, const Slice&)
|
||||
ctypedef int (*compare_func)(
|
||||
void*,
|
||||
Logger*,
|
||||
string&,
|
||||
const Slice&,
|
||||
const Slice&)
|
||||
|
||||
cdef extern from "cpp/comparator_wrapper.hpp" namespace "py_rocks":
|
||||
cdef cppclass ComparatorWrapper:
|
||||
ComparatorWrapper(string, void*, compare_func) nogil except +
|
||||
void set_info_log(shared_ptr[Logger]) nogil except+
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
#include "rocksdb/comparator.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include <stdexcept>
|
||||
|
||||
using std::string;
|
||||
using rocksdb::Comparator;
|
||||
using rocksdb::Slice;
|
||||
using rocksdb::Logger;
|
||||
|
||||
namespace py_rocks {
|
||||
class ComparatorWrapper: public Comparator {
|
||||
public:
|
||||
typedef int (*compare_func)(void*, const Slice&, const Slice&);
|
||||
typedef int (*compare_func)(
|
||||
void*,
|
||||
Logger*,
|
||||
string&,
|
||||
const Slice&,
|
||||
const Slice&);
|
||||
|
||||
ComparatorWrapper(
|
||||
string name,
|
||||
|
@ -19,7 +27,20 @@ namespace py_rocks {
|
|||
{}
|
||||
|
||||
int Compare(const Slice& a, const Slice& b) const {
|
||||
return this->compare_callback(this->compare_context, a, b);
|
||||
string error_msg;
|
||||
int val;
|
||||
|
||||
val = this->compare_callback(
|
||||
this->compare_context,
|
||||
this->info_log.get(),
|
||||
error_msg,
|
||||
a,
|
||||
b);
|
||||
|
||||
if (error_msg.size()) {
|
||||
throw std::runtime_error(error_msg.c_str());
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
const char* Name() const {
|
||||
|
@ -29,9 +50,14 @@ namespace py_rocks {
|
|||
void FindShortestSeparator(string* start, const Slice& limit) const {}
|
||||
void FindShortSuccessor(string* key) const {}
|
||||
|
||||
void set_info_log(std::shared_ptr<Logger> info_log) {
|
||||
this->info_log = info_log;
|
||||
}
|
||||
|
||||
private:
|
||||
string name;
|
||||
void* compare_context;
|
||||
compare_func compare_callback;
|
||||
std::shared_ptr<Logger> info_log;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue