Skip to content

Commit

Permalink
Merge pull request #62 from lmb/reuse-mdb-val
Browse files Browse the repository at this point in the history
lmdb: internal C.MDB_val fields in Txn for re-use during Get/PutReserve
  • Loading branch information
bmatsuo committed Mar 31, 2016
2 parents 903459e + fb24e5f commit 19f54dd
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 29 deletions.
48 changes: 25 additions & 23 deletions lmdb/cursor.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,63 +139,62 @@ func (c *Cursor) DBI() DBI {
//
// See mdb_cursor_get.
func (c *Cursor) Get(setkey, setval []byte, op uint) (key, val []byte, err error) {
var k, v *C.MDB_val
switch {
case len(setkey) == 0:
k, v, err = c.getVal0(op)
err = c.getVal0(op)
case len(setval) == 0:
k, v, err = c.getVal1(setkey, op)
err = c.getVal1(setkey, op)
default:
k, v, err = c.getVal2(setkey, setval, op)
err = c.getVal2(setkey, setval, op)
}
if err != nil {
*c.txn.key = C.MDB_val{}
*c.txn.val = C.MDB_val{}
return nil, nil, err
}
return c.txn.bytes(k), c.txn.bytes(v), nil
k := c.txn.bytes(c.txn.key)
v := c.txn.bytes(c.txn.val)
*c.txn.key = C.MDB_val{}
*c.txn.val = C.MDB_val{}
return k, v, nil
}

// getVal0 retrieves items from the database without using given key or value
// data for reference (Next, First, Last, etc).
//
// See mdb_cursor_get.
func (c *Cursor) getVal0(op uint) (key, val *C.MDB_val, err error) {
key = new(C.MDB_val)
val = new(C.MDB_val)
ret := C.mdb_cursor_get(c._c, (*C.MDB_val)(key), (*C.MDB_val)(val), C.MDB_cursor_op(op))
return key, val, operrno("mdb_cursor_get", ret)
func (c *Cursor) getVal0(op uint) error {
ret := C.mdb_cursor_get(c._c, c.txn.key, c.txn.val, C.MDB_cursor_op(op))
return operrno("mdb_cursor_get", ret)
}

// getVal1 retrieves items from the database using key data for reference
// (Set, SetRange, etc).
//
// See mdb_cursor_get.
func (c *Cursor) getVal1(setkey []byte, op uint) (key, val *C.MDB_val, err error) {
key = new(C.MDB_val)
val = new(C.MDB_val)
func (c *Cursor) getVal1(setkey []byte, op uint) error {
ret := C.lmdbgo_mdb_cursor_get1(
c._c,
unsafe.Pointer(&setkey[0]), C.size_t(len(setkey)),
(*C.MDB_val)(key), (*C.MDB_val)(val),
c.txn.key, c.txn.val,
C.MDB_cursor_op(op),
)
return key, val, operrno("mdb_cursor_get", ret)
return operrno("mdb_cursor_get", ret)
}

// getVal2 retrieves items from the database using key and value data for
// reference (GetBoth, GetBothRange, etc).
//
// See mdb_cursor_get.
func (c *Cursor) getVal2(setkey, setval []byte, op uint) (key, val *C.MDB_val, err error) {
key = new(C.MDB_val)
val = new(C.MDB_val)
func (c *Cursor) getVal2(setkey, setval []byte, op uint) error {
ret := C.lmdbgo_mdb_cursor_get2(
c._c,
unsafe.Pointer(&setkey[0]), C.size_t(len(setkey)),
unsafe.Pointer(&setval[0]), C.size_t(len(setval)),
(*C.MDB_val)(key), (*C.MDB_val)(val),
c.txn.key, c.txn.val,
C.MDB_cursor_op(op),
)
return key, val, operrno("mdb_cursor_get", ret)
return operrno("mdb_cursor_get", ret)
}

func (c *Cursor) putNilKey(flags uint) error {
Expand Down Expand Up @@ -231,18 +230,21 @@ func (c *Cursor) PutReserve(key []byte, n int, flags uint) ([]byte, error) {
return nil, c.putNilKey(flags)
}

val := &C.MDB_val{mv_size: C.size_t(n)}
c.txn.val.mv_size = C.size_t(n)
ret := C.lmdbgo_mdb_cursor_put1(
c._c,
unsafe.Pointer(&key[0]), C.size_t(len(key)),
(*C.MDB_val)(val),
c.txn.val,
C.uint(flags|C.MDB_RESERVE),
)
err := operrno("mdb_cursor_put", ret)
if err != nil {
*c.txn.val = C.MDB_val{}
return nil, err
}
return getBytes(val), nil
b := getBytes(c.txn.val)
*c.txn.val = C.MDB_val{}
return b, nil
}

// PutMulti stores a set of contiguous items with stride size under key.
Expand Down
24 changes: 18 additions & 6 deletions lmdb/txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ type Txn struct {
env *Env
_txn *C.MDB_txn
errLogf func(format string, v ...interface{})
key *C.MDB_val
val *C.MDB_val
}

// beginTxn does not lock the OS thread which is a prerequisite for creating a
Expand All @@ -58,11 +60,16 @@ func beginTxn(env *Env, parent *Txn, flags uint) (*Txn, error) {
readonly: (flags&Readonly != 0),
env: env,
}

var ptxn *C.MDB_txn
if parent == nil {
ptxn = nil
txn.key = new(C.MDB_val)
txn.val = new(C.MDB_val)
} else {
ptxn = parent._txn
txn.key = parent.key
txn.val = parent.val
}
ret := C.mdb_txn_begin(env._env, ptxn, C.uint(flags), &txn._txn)
if ret != success {
Expand Down Expand Up @@ -275,17 +282,19 @@ func (txn *Txn) bytes(val *C.MDB_val) []byte {
// See mdb_get.
func (txn *Txn) Get(dbi DBI, key []byte) ([]byte, error) {
kdata, kn := valBytes(key)
val := new(C.MDB_val)
ret := C.lmdbgo_mdb_get(
txn._txn, C.MDB_dbi(dbi),
unsafe.Pointer(&kdata[0]), C.size_t(kn),
(*C.MDB_val)(val),
txn.val,
)
err := operrno("mdb_get", ret)
if err != nil {
*txn.val = C.MDB_val{}
return nil, err
}
return txn.bytes(val), nil
b := txn.bytes(txn.val)
*txn.val = C.MDB_val{}
return b, nil
}

func (txn *Txn) putNilKey(dbi DBI, flags uint) error {
Expand Down Expand Up @@ -323,18 +332,21 @@ func (txn *Txn) PutReserve(dbi DBI, key []byte, n int, flags uint) ([]byte, erro
if len(key) == 0 {
return nil, txn.putNilKey(dbi, flags)
}
val := &C.MDB_val{mv_size: C.size_t(n)}
txn.val.mv_size = C.size_t(n)
ret := C.lmdbgo_mdb_put1(
txn._txn, C.MDB_dbi(dbi),
unsafe.Pointer(&key[0]), C.size_t(len(key)),
(*C.MDB_val)(val),
txn.val,
C.uint(flags|C.MDB_RESERVE),
)
err := operrno("mdb_put", ret)
if err != nil {
*txn.val = C.MDB_val{}
return nil, err
}
return getBytes(val), nil
b := getBytes(txn.val)
*txn.val = C.MDB_val{}
return b, nil
}

// Del deletes an item from database dbi. Del ignores val unless dbi has the
Expand Down

0 comments on commit 19f54dd

Please sign in to comment.