diff --git a/rocksdb/_rocksdb.pyx b/rocksdb/_rocksdb.pyx index 5bf1501bb44aefa576aaa86e9d98bcc3b7b594c9..1af70b1e5bd662f8c85477d9df5d91e634649cf6 100644 --- a/rocksdb/_rocksdb.pyx +++ b/rocksdb/_rocksdb.pyx @@ -513,16 +513,18 @@ cdef class Options(object): cdef PyCache py_block_cache cdef PyCache py_block_cache_compressed cdef PySliceTransform py_prefix_extractor + # Used to protect sharing of Options with many DB-objects + cdef cpp_bool in_use def __cinit__(self): self.opts = NULL self.opts = new options.Options() + self.in_use = False def __dealloc__(self): if not self.opts == NULL: del self.opts - def __init__(self, **kwargs): self.py_comparator = BytewiseComparator() self.py_merge_operator = None @@ -1057,6 +1059,7 @@ cdef class WriteBatch(object): def count(self): return self.batch.Count() +@cython.no_gc_clear cdef class DB(object): cdef Options opts cdef db.DB* db @@ -1065,8 +1068,11 @@ cdef class DB(object): cdef Status st cdef string db_path self.db = NULL + self.opts = None + if opts.in_use: + raise Exception("Options object is already used by another DB") db_path = path_to_string(db_name) if read_only: @@ -1085,10 +1091,13 @@ cdef class DB(object): check_status(st) self.opts = opts + self.opts.in_use = True def __dealloc__(self): if not self.db == NULL: del self.db + if self.opts is not None: + self.opts.in_use = False def put(self, key, value, sync=False, disable_wal=False): cdef Status st diff --git a/rocksdb/tests/test_db.py b/rocksdb/tests/test_db.py index 8f5508c4fa0109ce9e02ad07ea69c4bb79b0e3ac..1ffa2ff8745730ef5e6d631507bba5533bfc21e9 100644 --- a/rocksdb/tests/test_db.py +++ b/rocksdb/tests/test_db.py @@ -26,6 +26,11 @@ class TestDB(unittest.TestCase, TestHelper): def tearDown(self): self._close_db() + def test_options_used_twice(self): + expected = "Options object is already used by another DB" + with self.assertRaisesRegexp(Exception, expected): + rocksdb.DB("/tmp/test2", self.db.options) + def test_unicode_path(self): name = b'/tmp/M\xc3\xbcnchen'.decode('utf8') rocksdb.DB(name, rocksdb.Options(create_if_missing=True))