diff --git a/db.go b/db.go index fdfc8186..08b16889 100644 --- a/db.go +++ b/db.go @@ -264,6 +264,20 @@ func (db *DB) GetCF(opts *ReadOptions, cf *ColumnFamilyHandle, key []byte) (*Sli return NewSlice(cValue, cValLen), nil } +// GetPinned returns the data associated with the key from the database. +func (db *DB) GetPinned(opts *ReadOptions, key []byte) (*PinnableSliceHandle, error) { + var ( + cErr *C.char + cKey = byteToChar(key) + ) + cHandle := C.rocksdb_get_pinned(db.c, opts.c, cKey, C.size_t(len(key)), &cErr) + if cErr != nil { + defer C.free(unsafe.Pointer(cErr)) + return nil, errors.New(C.GoString(cErr)) + } + return NewNativePinnableSliceHandle(cHandle), nil +} + // MultiGet returns the data associated with the passed keys from the database func (db *DB) MultiGet(opts *ReadOptions, keys ...[]byte) (Slices, error) { cKeys, cKeySizes := byteSlicesToCSlices(keys) diff --git a/db_test.go b/db_test.go index c689b35e..8dc0ec77 100644 --- a/db_test.go +++ b/db_test.go @@ -21,6 +21,7 @@ func TestDBCRUD(t *testing.T) { givenKey = []byte("hello") givenVal1 = []byte("world1") givenVal2 = []byte("world2") + givenVal3 = []byte("world2") wo = NewDefaultWriteOptions() ro = NewDefaultReadOptions() ) @@ -41,11 +42,23 @@ func TestDBCRUD(t *testing.T) { ensure.Nil(t, err) ensure.DeepEqual(t, v2.Data(), givenVal2) + // retrieve pinned + v3, err := db.GetPinned(ro, givenKey) + defer v3.Destroy() + ensure.Nil(t, err) + ensure.DeepEqual(t, v3.Data(), givenVal3) + // delete ensure.Nil(t, db.Delete(wo, givenKey)) - v3, err := db.Get(ro, givenKey) + v4, err := db.Get(ro, givenKey) ensure.Nil(t, err) - ensure.True(t, v3.Data() == nil) + ensure.True(t, v4.Data() == nil) + + // retrieve missing pinned + v5, err := db.GetPinned(ro, givenKey) + defer v5.Destroy() + ensure.Nil(t, err) + ensure.Nil(t, v5.Data()) } func TestDBCRUDDBPaths(t *testing.T) { diff --git a/slice.go b/slice.go index 22b48e09..bcdc4c16 100644 --- a/slice.go +++ b/slice.go @@ -1,6 +1,7 @@ package gorocksdb // #include +// #include "rocksdb/c.h" import "C" import "unsafe" @@ -48,3 +49,30 @@ func (s *Slice) Free() { s.freed = true } } + +// PinnableSliceHandle represents a handle to a PinnableSlice. +type PinnableSliceHandle struct { + c *C.rocksdb_pinnableslice_t +} + +// NewNativePinnableSliceHandle creates a PinnableSliceHandle object. +func NewNativePinnableSliceHandle(c *C.rocksdb_pinnableslice_t) *PinnableSliceHandle { + return &PinnableSliceHandle{c} +} + +// Data returns the data of the slice. +func (h *PinnableSliceHandle) Data() []byte { + if h.c == nil { + return nil + } + + var cValLen C.size_t + cValue := C.rocksdb_pinnableslice_value(h.c, &cValLen) + + return charToByte(cValue, cValLen) +} + +// Destroy calls the destructor of the underlying pinnable slice handle. +func (h *PinnableSliceHandle) Destroy() { + C.rocksdb_pinnableslice_destroy(h.c) +}