mirror of
https://github.com/status-im/nim-rocksdb.git
synced 2025-02-19 18:38:15 +00:00
reuse read and write options
* fixes segfault in del * fixes initResource freeing options before they get used * fixes failing test cases * avoids reallocating options on every access * deallocates fields in reverse creation order
This commit is contained in:
parent
e05b1a411d
commit
e48a45bd44
76
rocksdb.nim
76
rocksdb.nim
@ -15,13 +15,6 @@ when useCApi:
|
||||
import rocksdb/librocksdb
|
||||
export librocksdb
|
||||
|
||||
template managedResource(name) =
|
||||
template freeResource(r: `rocksdb name t`) =
|
||||
`rocksdb name destroy`(r)
|
||||
|
||||
managedResource(WriteOptions)
|
||||
managedResource(ReadOptions)
|
||||
|
||||
type
|
||||
RocksPtr[T] = object
|
||||
res: T
|
||||
@ -31,17 +24,26 @@ when useCApi:
|
||||
when false:
|
||||
# XXX: generic types cannot have destructors at the moment:
|
||||
# https://github.com/nim-lang/Nim/issues/5366
|
||||
proc `=destroy`*[T](rocksPtr: var RocksPtr[T]) =
|
||||
freeResource rocksPtr.res
|
||||
template managedResource(name) =
|
||||
template freeResource(r: `rocksdb name t`) =
|
||||
`rocksdb name destroy`(r)
|
||||
|
||||
proc toRocksPtr[T](res: T): RocksPtr[T] =
|
||||
result.res = res
|
||||
managedResource(WriteOptions)
|
||||
managedResource(ReadOptions)
|
||||
template initResource(resourceName): auto =
|
||||
var p = toRocksPtr(`rocksdb resourceName create`())
|
||||
# XXX: work-around the destructor issue above:
|
||||
# XXX: work-around disabled - it frees the resource too early - need to
|
||||
# free resource manually!
|
||||
# defer: freeResource p.res
|
||||
p.res
|
||||
|
||||
proc `=destroy`*[T](rocksPtr: var RocksPtr[T]) =
|
||||
freeResource rocksPtr.res
|
||||
|
||||
proc toRocksPtr[T](res: T): RocksPtr[T] =
|
||||
result.res = res
|
||||
|
||||
template initResource(resourceName): auto =
|
||||
var p = toRocksPtr(`rocksdb resourceName create`())
|
||||
# XXX: work-around the destructor issue above:
|
||||
defer: freeResource p.res
|
||||
p.res
|
||||
else:
|
||||
{.error: "The C++ API of RocksDB is not supported yet".}
|
||||
|
||||
@ -62,6 +64,8 @@ type
|
||||
db: rocksdb_t
|
||||
backupEngine: rocksdb_backup_engine_t
|
||||
options: rocksdb_options_t
|
||||
readOptions: rocksdb_readoptions_t
|
||||
writeOptions: rocksdb_writeoptions_t
|
||||
|
||||
RocksDBResult*[T] = object
|
||||
case ok*: bool
|
||||
@ -100,6 +104,8 @@ proc init*(rocks: var RocksDBInstance,
|
||||
cpus = countProcessors(),
|
||||
createIfMissing = true): RocksDBResult[void] =
|
||||
rocks.options = rocksdb_options_create()
|
||||
rocks.readOptions = rocksdb_readoptions_create()
|
||||
rocks.writeOptions = rocksdb_writeoptions_create()
|
||||
|
||||
# Optimize RocksDB. This is the easiest way to get RocksDB to perform well:
|
||||
rocksdb_options_increase_parallelism(rocks.options, cpus.int32)
|
||||
@ -155,10 +161,9 @@ template getImpl {.dirty.} =
|
||||
assert key.len > 0
|
||||
|
||||
var
|
||||
options = initResource ReadOptions
|
||||
errors: cstring
|
||||
len: csize
|
||||
data = rocksdb_get(db.db, options,
|
||||
data = rocksdb_get(db.db, db.readOptions,
|
||||
cast[cstring](unsafeAddr key[0]), key.len,
|
||||
addr len, errors.addr)
|
||||
bailOnErrors()
|
||||
@ -176,10 +181,9 @@ proc put*(db: RocksDBInstance, key, val: KeyValueType): RocksDBResult[void] =
|
||||
assert key.len > 0
|
||||
|
||||
var
|
||||
options = initResource WriteOptions
|
||||
errors: cstring
|
||||
|
||||
rocksdb_put(db.db, options,
|
||||
rocksdb_put(db.db, db.writeOptions,
|
||||
cast[cstring](unsafeAddr key[0]), key.len,
|
||||
cast[cstring](if val.len > 0: unsafeAddr val[0] else: nil), val.len,
|
||||
errors.addr)
|
||||
@ -188,19 +192,12 @@ proc put*(db: RocksDBInstance, key, val: KeyValueType): RocksDBResult[void] =
|
||||
returnOk()
|
||||
|
||||
proc del*(db: RocksDBInstance, key: KeyValueType): RocksDBResult[void] =
|
||||
when false:
|
||||
# XXX: For yet unknown reasons, the code below fails with SIGSEGV.
|
||||
# Investigate if this the correct usage of `rocksdb_delete`.
|
||||
var options = initResource WriteOptions
|
||||
var errors: cstringArray
|
||||
echo key.len
|
||||
rocksdb_delete(db.db, options,
|
||||
cast[cstring](unsafeAddr key[0]), key.len,
|
||||
errors)
|
||||
bailOnErrors()
|
||||
returnOk()
|
||||
else:
|
||||
put(db, key, @[])
|
||||
var errors: cstring
|
||||
rocksdb_delete(db.db, db.writeOptions,
|
||||
cast[cstring](unsafeAddr key[0]), key.len,
|
||||
errors.addr)
|
||||
bailOnErrors()
|
||||
returnOk()
|
||||
|
||||
proc contains*(db: RocksDBInstance, key: KeyValueType): RocksDBResult[bool] =
|
||||
assert key.len > 0
|
||||
@ -222,6 +219,14 @@ proc backup*(db: RocksDBInstance): RocksDBResult[void] =
|
||||
# https://github.com/nim-lang/Nim/issues/8112
|
||||
# proc `=destroy`*(db: var RocksDBInstance) =
|
||||
proc close*(db: var RocksDBInstance) =
|
||||
template freeField(name) =
|
||||
if db.`name`.isNil:
|
||||
`rocksdb name destroy`(db.`name`)
|
||||
db.`name` = nil
|
||||
freeField(writeOptions)
|
||||
freeField(readOptions)
|
||||
freeField(options)
|
||||
|
||||
if not db.backupEngine.isNil:
|
||||
rocksdb_backup_engine_close(db.backupEngine)
|
||||
db.backupEngine = nil
|
||||
@ -229,8 +234,3 @@ proc close*(db: var RocksDBInstance) =
|
||||
if not db.db.isNil:
|
||||
rocksdb_close(db.db)
|
||||
db.db = nil
|
||||
|
||||
if not db.options.isNil:
|
||||
rocksdb_options_destroy(db.options)
|
||||
db.options = nil
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user