Skip to content

Commit

Permalink
Implement multiget
Browse files Browse the repository at this point in the history
  • Loading branch information
JelteF committed Mar 23, 2018
1 parent c8dc4df commit 893b80f
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
44 changes: 44 additions & 0 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package gorocksdb
import "C"
import (
"errors"
"fmt"
"unsafe"
)

Expand Down Expand Up @@ -263,6 +264,49 @@ func (db *DB) GetCF(opts *ReadOptions, cf *ColumnFamilyHandle, key []byte) (*Sli
return NewSlice(cValue, cValLen), nil
}

// Get returns the data associated with the key from the database.
func (db *DB) MultiGet(opts *ReadOptions, keys ...[]byte) (Slices, error) {
cKeys, cKeySizes := bytesSliceToArray(keys)
defer freeCharsArray(cKeys, len(keys))
vals, cVals := emptyCharSlice(len(keys))
rocksErrs, cRocksErrs := emptyCharSlice(len(keys))
valSizes, cValSizes := emptySizetSlice(len(keys))
_ = vals
_ = valSizes

C.rocksdb_multi_get(
db.c,
opts.c,
C.size_t(len(keys)),
cKeys,
cKeySizes,
cVals,
cValSizes,
cRocksErrs,
)

var errs []error

for i, rocksErr := range rocksErrs {
if rocksErr != nil {
defer C.free(unsafe.Pointer(rocksErr))
err := fmt.Errorf("getting %q failed: %v", string(keys[i]), C.GoString(rocksErr))
errs = append(errs, err)
}
}

if len(errs) > 0 {
return nil, fmt.Errorf("failed to get %d keys, first error: %v", len(errs), errs[0])
}

slices := make(Slices, len(keys))
for i, val := range vals {
slices[i] = NewSlice(val, valSizes[i])
}

return slices, nil
}

// Put writes data associated with a key to the database.
func (db *DB) Put(opts *WriteOptions, key, value []byte) error {
var (
Expand Down
32 changes: 32 additions & 0 deletions db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,35 @@ func newTestDBPathNames(t *testing.T, name string, names []string, target_sizes

return db
}

func TestDBMultiGet(t *testing.T) {
db := newTestDB(t, "TestDBMultiGet", nil)
defer db.Close()

var (
givenKey1 = []byte("hello1")
givenKey2 = []byte("hello2")
givenKey3 = []byte("hello3")
givenVal1 = []byte("world1")
givenVal2 = []byte("world2")
givenVal3 = []byte("world3")
wo = NewDefaultWriteOptions()
ro = NewDefaultReadOptions()
)

// create
ensure.Nil(t, db.Put(wo, givenKey1, givenVal1))
ensure.Nil(t, db.Put(wo, givenKey2, givenVal2))
ensure.Nil(t, db.Put(wo, givenKey3, givenVal3))

// retrieve
values, err := db.MultiGet(ro, []byte("noexist"), givenKey1, givenKey2, givenKey3)
defer values.Destroy()
ensure.Nil(t, err)
ensure.DeepEqual(t, len(values), 4)

ensure.DeepEqual(t, values[0].Data(), []byte(nil))
ensure.DeepEqual(t, values[1].Data(), givenVal1)
ensure.DeepEqual(t, values[2].Data(), givenVal2)
ensure.DeepEqual(t, values[3].Data(), givenVal3)
}
8 changes: 8 additions & 0 deletions slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ type Slice struct {
freed bool
}

type Slices []*Slice

func (slices Slices) Destroy() {
for _, s := range slices {
s.Free()
}
}

// NewSlice returns a slice with the given data.
func NewSlice(data *C.char, size C.size_t) *Slice {
return &Slice{data, size, false}
Expand Down

0 comments on commit 893b80f

Please sign in to comment.