From c8b92d5adb68c572763aba9425b11899f1550471 Mon Sep 17 00:00:00 2001
From: hofmockel <dreagonfly@gmx.de>
Date: Thu, 23 Jan 2014 08:53:14 +0100
Subject: [PATCH] Fore future use, prevent options beeing shared with other DB
 objects

For better logging I'm going to inject the rocksdb info_logger into the C++ Wrapper classes
=> The classes on the options object have a member to a DB specific logger
=> This c++ classes can only belong to a SINGLE db
=> For simplicity make this requirement also for the options object itself
---
 rocksdb/_rocksdb.pyx     | 11 ++++++++++-
 rocksdb/tests/test_db.py |  5 +++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/rocksdb/_rocksdb.pyx b/rocksdb/_rocksdb.pyx
index 5bf1501..1af70b1 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 8f5508c..1ffa2ff 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))
-- 
GitLab