mirror of https://github.com/ceph/go-ceph
rados: add GetOmapValues function to the ReadOp
Refactor the previous ListOmapValues logic into a new read op step that can be used for iteration over the results of the operation. The previous function is now based on the ReadOp. Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
bc6cabbe9f
commit
701bb74897
153
rados/omap.go
153
rados/omap.go
|
@ -85,6 +85,104 @@ func (sos *setOmapStep) free() {
|
||||||
sos.withRefs.free()
|
sos.withRefs.free()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OmapKeyValue items are returned by the GetOmapStep's Next call.
|
||||||
|
type OmapKeyValue struct {
|
||||||
|
Key string
|
||||||
|
Value []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOmapStep values are used to get the results of an GetOmapValues call
|
||||||
|
// on a WriteOp. Until the Operate method of the WriteOp is called the Next
|
||||||
|
// call will return an error. After Operate is called, the Next call will
|
||||||
|
// return valid results.
|
||||||
|
//
|
||||||
|
// The life cycle of the GetOmapStep is bound to the ReadOp, if the ReadOp
|
||||||
|
// Release method is called the public methods of the step must no longer be
|
||||||
|
// used and may return errors.
|
||||||
|
type GetOmapStep struct {
|
||||||
|
// inputs:
|
||||||
|
startAfter string
|
||||||
|
filterPrefix string
|
||||||
|
maxReturn uint64
|
||||||
|
|
||||||
|
// arguments:
|
||||||
|
cStartAfter *C.char
|
||||||
|
cFilterPrefix *C.char
|
||||||
|
|
||||||
|
// C returned data:
|
||||||
|
iter C.rados_omap_iter_t
|
||||||
|
more C.uchar
|
||||||
|
rval 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 newGetOmapStep(startAfter, filterPrefix string, maxReturn uint64) *GetOmapStep {
|
||||||
|
gos := &GetOmapStep{
|
||||||
|
startAfter: startAfter,
|
||||||
|
filterPrefix: filterPrefix,
|
||||||
|
maxReturn: maxReturn,
|
||||||
|
cStartAfter: C.CString(startAfter),
|
||||||
|
cFilterPrefix: C.CString(filterPrefix),
|
||||||
|
}
|
||||||
|
runtime.SetFinalizer(gos, opStepFinalizer)
|
||||||
|
return gos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gos *GetOmapStep) free() {
|
||||||
|
gos.canIterate = false
|
||||||
|
if gos.iter != nil {
|
||||||
|
C.rados_omap_get_end(gos.iter)
|
||||||
|
}
|
||||||
|
gos.iter = nil
|
||||||
|
gos.more = 0
|
||||||
|
gos.rval = 0
|
||||||
|
C.free(unsafe.Pointer(gos.cStartAfter))
|
||||||
|
gos.cStartAfter = nil
|
||||||
|
C.free(unsafe.Pointer(gos.cFilterPrefix))
|
||||||
|
gos.cFilterPrefix = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gos *GetOmapStep) update() error {
|
||||||
|
err := getError(gos.rval)
|
||||||
|
gos.canIterate = (err == nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next key value pair or nil if iteration is exhausted.
|
||||||
|
func (gos *GetOmapStep) Next() (*OmapKeyValue, error) {
|
||||||
|
if !gos.canIterate {
|
||||||
|
return nil, ErrOperationIncomplete
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
cKey *C.char
|
||||||
|
cVal *C.char
|
||||||
|
cLen C.size_t
|
||||||
|
)
|
||||||
|
ret := C.rados_omap_get_next(gos.iter, &cKey, &cVal, &cLen)
|
||||||
|
if ret != 0 {
|
||||||
|
return nil, getError(ret)
|
||||||
|
}
|
||||||
|
if cKey == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return &OmapKeyValue{
|
||||||
|
Key: C.GoString(cKey),
|
||||||
|
Value: C.GoBytes(unsafe.Pointer(cVal), C.int(cLen)),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// More returns true if there are more matching keys available.
|
||||||
|
func (gos *GetOmapStep) More() bool {
|
||||||
|
// tad bit hacky, but go can't automatically convert from
|
||||||
|
// unsigned char to bool
|
||||||
|
return gos.more != 0
|
||||||
|
}
|
||||||
|
|
||||||
// SetOmap appends the map `pairs` to the omap `oid`
|
// SetOmap appends the map `pairs` to the omap `oid`
|
||||||
func (ioctx *IOContext) SetOmap(oid string, pairs map[string][]byte) error {
|
func (ioctx *IOContext) SetOmap(oid string, pairs map[string][]byte) error {
|
||||||
op := CreateWriteOp()
|
op := CreateWriteOp()
|
||||||
|
@ -105,58 +203,25 @@ type OmapListFunc func(key string, value []byte)
|
||||||
// `maxReturn`: iterate no more than `maxReturn` key/value pairs
|
// `maxReturn`: iterate no more than `maxReturn` key/value pairs
|
||||||
// `listFn`: the function called at each iteration
|
// `listFn`: the function called at each iteration
|
||||||
func (ioctx *IOContext) ListOmapValues(oid string, startAfter string, filterPrefix string, maxReturn int64, listFn OmapListFunc) error {
|
func (ioctx *IOContext) ListOmapValues(oid string, startAfter string, filterPrefix string, maxReturn int64, listFn OmapListFunc) error {
|
||||||
c_oid := C.CString(oid)
|
|
||||||
c_start_after := C.CString(startAfter)
|
|
||||||
c_filter_prefix := C.CString(filterPrefix)
|
|
||||||
c_max_return := C.uint64_t(maxReturn)
|
|
||||||
|
|
||||||
defer C.free(unsafe.Pointer(c_oid))
|
op := CreateReadOp()
|
||||||
defer C.free(unsafe.Pointer(c_start_after))
|
defer op.Release()
|
||||||
defer C.free(unsafe.Pointer(c_filter_prefix))
|
gos := op.GetOmapValues(startAfter, filterPrefix, uint64(maxReturn))
|
||||||
|
err := op.operateCompat(ioctx, oid)
|
||||||
op := C.rados_create_read_op()
|
if err != nil {
|
||||||
|
return err
|
||||||
var c_iter C.rados_omap_iter_t
|
|
||||||
var c_prval C.int
|
|
||||||
C.rados_read_op_omap_get_vals2(
|
|
||||||
op,
|
|
||||||
c_start_after,
|
|
||||||
c_filter_prefix,
|
|
||||||
c_max_return,
|
|
||||||
&c_iter,
|
|
||||||
nil,
|
|
||||||
&c_prval,
|
|
||||||
)
|
|
||||||
|
|
||||||
ret := C.rados_read_op_operate(op, ioctx.ioctx, c_oid, 0)
|
|
||||||
|
|
||||||
if int(ret) != 0 {
|
|
||||||
return getError(ret)
|
|
||||||
} else if int(c_prval) != 0 {
|
|
||||||
return getError(c_prval)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var c_key *C.char
|
kv, err := gos.Next()
|
||||||
var c_val *C.char
|
if err != nil {
|
||||||
var c_len C.size_t
|
return err
|
||||||
|
|
||||||
ret = C.rados_omap_get_next(c_iter, &c_key, &c_val, &c_len)
|
|
||||||
|
|
||||||
if int(ret) != 0 {
|
|
||||||
return getError(ret)
|
|
||||||
}
|
}
|
||||||
|
if kv == nil {
|
||||||
if c_key == nil {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
listFn(kv.Key, kv.Value)
|
||||||
listFn(C.GoString(c_key), C.GoBytes(unsafe.Pointer(c_val), C.int(c_len)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
C.rados_omap_get_end(c_iter)
|
|
||||||
C.rados_release_read_op(op)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,3 +55,22 @@ func (r *ReadOp) operateCompat(ioctx *IOContext, oid string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetOmapValues is used to iterate over a set, or sub-set, of omap keys
|
||||||
|
// as part of a read operation. An GetOmapStep is returned from this
|
||||||
|
// function. The GetOmapStep may be used to iterate over the key-value
|
||||||
|
// pairs after the Operate call has been performed.
|
||||||
|
func (r *ReadOp) GetOmapValues(startAfter, filterPrefix string, maxReturn uint64) *GetOmapStep {
|
||||||
|
gos := newGetOmapStep(startAfter, filterPrefix, maxReturn)
|
||||||
|
r.steps = append(r.steps, gos)
|
||||||
|
C.rados_read_op_omap_get_vals2(
|
||||||
|
r.op,
|
||||||
|
gos.cStartAfter,
|
||||||
|
gos.cFilterPrefix,
|
||||||
|
C.uint64_t(gos.maxReturn),
|
||||||
|
&gos.iter,
|
||||||
|
&gos.more,
|
||||||
|
&gos.rval,
|
||||||
|
)
|
||||||
|
return gos
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue