Skip to content

Commit

Permalink
Merge branch 'v0_27'
Browse files Browse the repository at this point in the history
  • Loading branch information
AskAlexSharov committed Feb 26, 2023
2 parents 7716cdb + eda876f commit d473be6
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 14 deletions.
37 changes: 33 additions & 4 deletions mdbx/cursor.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package mdbx
*/
import "C"
import (
"fmt"
"sync"
"unsafe"
)

Expand Down Expand Up @@ -71,14 +73,24 @@ func openCursor(txn *Txn, db DBI) (*Cursor, error) {
return c, nil
}

// Renew associates readonly cursor with txn.
// Renew associates cursor with txn.
//
// See mdb_cursor_renew.
func (c *Cursor) Renew(txn *Txn) error {
ret := C.mdbx_cursor_renew(txn._txn, c._c)
err := operrno("mdbx_cursor_renew", ret)
if err != nil {
return err
if ret != success {
return operrno("mdbx_cursor_renew", ret)
}
c.txn = txn
return nil
}

// Bind Using of the `mdbx_cursor_bind()` is equivalent to calling mdbx_cursor_renew() but with specifying an arbitrary
// dbi handle.
func (c *Cursor) Bind(txn *Txn, db DBI) error {
ret := C.mdbx_cursor_bind(txn._txn, c._c, C.MDBX_dbi(db))
if ret != success {
return operrno("mdbx_cursor_bind", ret)
}
c.txn = txn
return nil
Expand Down Expand Up @@ -308,3 +320,20 @@ func (c *Cursor) Count() (uint64, error) {
}
return uint64(_size), nil
}

var cursorPool = sync.Pool{
New: func() interface{} {
return CreateCursor()
},
}

func CursorFromPool() *Cursor { return cursorPool.Get().(*Cursor) }
func CursorToPool(c *Cursor) { cursorPool.Put(c) }

func CreateCursor() *Cursor {
c := &Cursor{_c: C.mdbx_cursor_create(nil)}
if c._c == nil {
panic(fmt.Errorf("mdbx.CreateCursor: OOM"))
}
return c
}
127 changes: 117 additions & 10 deletions mdbx/cursor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,90 @@ func TestCursor_Renew(t *testing.T) {
}
}

func TestCursor_Bind(t *testing.T) {
env := setup(t)

var db1, db2 DBI
err := env.Update(func(txn *Txn) (err error) {
db1, err = txn.CreateDBI("testing1")
return err
})
if err != nil {
t.Error(err)
return
}

err = env.Update(func(txn *Txn) (err error) {
put := func(k, v string) {
if err == nil {
err = txn.Put(db1, []byte(k), []byte(v), 0)
}
}
put("k1", "v1")
put("k2", "v2")
put("k3", "v3")
return err
})
if err != nil {
t.Error("err")
}

var cur *Cursor
err = env.View(func(txn *Txn) (err error) {
cur, err = txn.OpenCursor(db2)
if err != nil {
return err
}
return nil
})
if err != nil {
t.Error(err)
}

err = env.View(func(txn *Txn) (err error) {
{
err = cur.Bind(txn, db1)
if err != nil {
return err
}

k, v, err := cur.Get(nil, nil, Next)
if err != nil {
return err
}
if string(k) != "k1" {
return fmt.Errorf("key: %q", k)
}
if string(v) != "v1" {
return fmt.Errorf("val: %q", v)
}
}

{
c2 := CreateCursor()
err = c2.Bind(txn, db1)
if err != nil {
return err
}

k, v, err := c2.Get(nil, nil, Next)
if err != nil {
return err
}
if string(k) != "k1" {
return fmt.Errorf("key: %q", k)
}
if string(v) != "v1" {
return fmt.Errorf("val: %q", v)
}
}
return nil
})
if err != nil {
t.Error(err)
}
}

func BenchmarkCursor(b *testing.B) {
env, _ := setup(b)

Expand Down Expand Up @@ -924,9 +1008,10 @@ func BenchmarkCursor(b *testing.B) {
func BenchmarkCursor_Renew(b *testing.B) {
env, _ := setup(b)

var db DBI
var cur *Cursor
err := env.View(func(txn *Txn) (err error) {
db, err := txn.OpenRoot(0)
db, err = txn.OpenRoot(0)
if err != nil {
return err
}
Expand All @@ -939,16 +1024,38 @@ func BenchmarkCursor_Renew(b *testing.B) {
}

_ = env.View(func(txn *Txn) (err error) {
b.ResetTimer()
defer b.StopTimer()

for i := 0; i < b.N; i++ {
err = cur.Renew(txn)
if err != nil {
return err
b.Run("1", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if err := cur.Renew(txn); err != nil {
panic(err)
}
}
}

})
b.Run("2", func(b *testing.B) {
for i := 0; i < b.N; i++ {
if err := cur.Bind(txn, db); err != nil {
panic(err)
}
}
})
b.Run("3", func(b *testing.B) {
for i := 0; i < b.N; i++ {
c, err := txn.OpenCursor(db)
if err != nil {
panic(err)
}
c.Close()
}
})
b.Run("4", func(b *testing.B) {
for i := 0; i < b.N; i++ {
cur := CursorFromPool()
if err := cur.Bind(txn, db); err != nil {
panic(err)
}
CursorToPool(cur)
}
})
return nil
})
}
1 change: 1 addition & 0 deletions mdbx/error_unix.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build !windows
// +build !windows

package mdbx
Expand Down

0 comments on commit d473be6

Please sign in to comment.