mirror of https://github.com/ceph/go-ceph
rados: implement binding for read_op_omap_get_vals_by_keys
This commit implements binding for read_op_omap_get_vals_by_keys RADOS Read operation. Includes a unit test. Signed-off-by: Robert Vasek <robert.vasek@cern.ch>
This commit is contained in:
parent
4cf39ce07b
commit
573598cf22
|
@ -976,6 +976,18 @@
|
|||
"comment": "Set an xattr.\n PREVIEW\n\nImplements:\n void rados_write_op_setxattr(rados_write_op_t write_op,\n const char * name,\n const char * value,\n size_t value_len)\n",
|
||||
"added_in_version": "v0.14.0",
|
||||
"expected_stable_version": "v0.16.0"
|
||||
},
|
||||
{
|
||||
"name": "ReadOpOmapGetValsByKeysStep.Next",
|
||||
"comment": "Next gets the next omap key/value pair referenced by\nReadOpOmapGetValsByKeysStep's internal iterator.\nIf there are no more elements to retrieve, (nil, nil) is returned.\nMay be called only after Operate() finished.\n PREVIEW\n",
|
||||
"added_in_version": "v0.14.0",
|
||||
"expected_stable_version": "v0.16.0"
|
||||
},
|
||||
{
|
||||
"name": "ReadOp.GetOmapValuesByKeys",
|
||||
"comment": "GetOmapValuesByKeys starts iterating over specific key/value pairs.\n PREVIEW\n\nImplements:\n void rados_read_op_omap_get_vals_by_keys(rados_read_op_t read_op,\n char const * const * keys,\n size_t keys_len,\n rados_omap_iter_t * iter,\n int * prval)\n",
|
||||
"added_in_version": "v0.14.0",
|
||||
"expected_stable_version": "v0.16.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -25,6 +25,8 @@ WriteOp.Remove | v0.14.0 | v0.16.0 |
|
|||
ReadOp.AssertVersion | v0.14.0 | v0.16.0 |
|
||||
WriteOp.AssertVersion | v0.14.0 | v0.16.0 |
|
||||
WriteOp.SetXattr | v0.14.0 | v0.16.0 |
|
||||
ReadOpOmapGetValsByKeysStep.Next | v0.14.0 | v0.16.0 |
|
||||
ReadOp.GetOmapValuesByKeys | v0.14.0 | v0.16.0 |
|
||||
|
||||
## Package: rbd
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
//go:build ceph_preview
|
||||
// +build ceph_preview
|
||||
|
||||
package rados
|
||||
|
||||
// #cgo LDFLAGS: -lrados
|
||||
// #include <rados/librados.h>
|
||||
// #include <stdlib.h>
|
||||
//
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ReadOpOmapGetValsByKeysStep holds the result of the
|
||||
// GetOmapValuesByKeys read operation.
|
||||
// Result is valid only after Operate() was called.
|
||||
type ReadOpOmapGetValsByKeysStep struct {
|
||||
// C arguments
|
||||
|
||||
iter C.rados_omap_iter_t
|
||||
prval *C.int
|
||||
|
||||
// Internal state
|
||||
|
||||
// canIterate is only set after the operation is performed and is
|
||||
// intended to prevent premature fetching of data.
|
||||
canIterate bool
|
||||
}
|
||||
|
||||
func newReadOpOmapGetValsByKeysStep() *ReadOpOmapGetValsByKeysStep {
|
||||
s := &ReadOpOmapGetValsByKeysStep{
|
||||
prval: (*C.int)(C.malloc(C.sizeof_int)),
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *ReadOpOmapGetValsByKeysStep) free() {
|
||||
s.canIterate = false
|
||||
C.rados_omap_get_end(s.iter)
|
||||
|
||||
C.free(unsafe.Pointer(s.prval))
|
||||
s.prval = nil
|
||||
}
|
||||
|
||||
func (s *ReadOpOmapGetValsByKeysStep) update() error {
|
||||
err := getError(*s.prval)
|
||||
s.canIterate = (err == nil)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Next gets the next omap key/value pair referenced by
|
||||
// ReadOpOmapGetValsByKeysStep's internal iterator.
|
||||
// If there are no more elements to retrieve, (nil, nil) is returned.
|
||||
// May be called only after Operate() finished.
|
||||
// PREVIEW
|
||||
func (s *ReadOpOmapGetValsByKeysStep) Next() (*OmapKeyValue, error) {
|
||||
if !s.canIterate {
|
||||
return nil, ErrOperationIncomplete
|
||||
}
|
||||
|
||||
var (
|
||||
cKey *C.char
|
||||
cVal *C.char
|
||||
cValLen C.size_t
|
||||
)
|
||||
|
||||
ret := C.rados_omap_get_next(s.iter, &cKey, &cVal, &cValLen)
|
||||
if ret != 0 {
|
||||
return nil, getError(ret)
|
||||
}
|
||||
|
||||
if cKey == nil {
|
||||
// Iterator has reached the end of the list.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &OmapKeyValue{
|
||||
Key: C.GoString(cKey),
|
||||
Value: C.GoBytes(unsafe.Pointer(cVal), C.int(cValLen)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetOmapValuesByKeys starts iterating over specific key/value pairs.
|
||||
// PREVIEW
|
||||
//
|
||||
// Implements:
|
||||
// void rados_read_op_omap_get_vals_by_keys(rados_read_op_t read_op,
|
||||
// char const * const * keys,
|
||||
// size_t keys_len,
|
||||
// rados_omap_iter_t * iter,
|
||||
// int * prval)
|
||||
func (r *ReadOp) GetOmapValuesByKeys(keys []string) *ReadOpOmapGetValsByKeysStep {
|
||||
s := newReadOpOmapGetValsByKeysStep()
|
||||
r.steps = append(r.steps, s)
|
||||
|
||||
cKeys := make([]*C.char, len(keys))
|
||||
defer func() {
|
||||
for _, cKeyPtr := range cKeys {
|
||||
C.free(unsafe.Pointer(cKeyPtr))
|
||||
}
|
||||
}()
|
||||
|
||||
for i, key := range keys {
|
||||
cKeys[i] = C.CString(key)
|
||||
}
|
||||
|
||||
C.rados_read_op_omap_get_vals_by_keys(
|
||||
r.op,
|
||||
&cKeys[0],
|
||||
C.size_t(len(keys)),
|
||||
&s.iter,
|
||||
s.prval,
|
||||
)
|
||||
|
||||
return s
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
//go:build ceph_preview
|
||||
// +build ceph_preview
|
||||
|
||||
package rados
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func (suite *RadosTestSuite) TestReadOpOmapGetValsByKeys() {
|
||||
suite.SetupConnection()
|
||||
ta := assert.New(suite.T())
|
||||
|
||||
var (
|
||||
oid = "TestReadOpOmapGetValsByKeys"
|
||||
kvs = map[string][]byte{
|
||||
"k1": []byte("v1"),
|
||||
"k2": []byte("v2"),
|
||||
}
|
||||
err error
|
||||
)
|
||||
|
||||
// Create an object and populate it with data.
|
||||
|
||||
op1 := CreateWriteOp()
|
||||
defer op1.Release()
|
||||
op1.Create(CreateIdempotent)
|
||||
op1.SetOmap(kvs)
|
||||
err = op1.Operate(suite.ioctx, oid, OperationNoFlag)
|
||||
ta.NoError(err)
|
||||
|
||||
// Retrieve objects omap key-value pairs by ks keys, but add
|
||||
// a few non-existingones which are expected to be silently skipped.
|
||||
|
||||
var (
|
||||
actualKVs = make(map[string][]byte)
|
||||
ks = []string{"k1", "k2", "xx", "yy"}
|
||||
)
|
||||
|
||||
op2 := CreateReadOp()
|
||||
defer op2.Release()
|
||||
kvStep := op2.GetOmapValuesByKeys(ks)
|
||||
|
||||
_, err = kvStep.Next()
|
||||
ta.Equal(ErrOperationIncomplete, err)
|
||||
|
||||
err = op2.Operate(suite.ioctx, oid, OperationNoFlag)
|
||||
ta.NoError(err)
|
||||
|
||||
for {
|
||||
kv, err := kvStep.Next()
|
||||
ta.NoError(err)
|
||||
|
||||
if kv == nil {
|
||||
break
|
||||
}
|
||||
|
||||
actualKVs[kv.Key] = kv.Value
|
||||
}
|
||||
|
||||
ta.Equal(kvs, actualKVs)
|
||||
}
|
Loading…
Reference in New Issue