mirror of https://github.com/ceph/go-ceph
rados: implement binding for rados_read_op_read
This commit implements binding for rados_read_op_read RADOS Read operation. Includes a unit test. Signed-off-by: Robert Vasek <robert.vasek@cern.ch>
This commit is contained in:
parent
0e3ed2982f
commit
937f8d8164
|
@ -932,6 +932,12 @@
|
|||
"comment": "CmpExt ensures that given object range (extent) satisfies comparison.\n PREVIEW\n\nImplements:\n void rados_write_op_cmpext(rados_write_op_t write_op,\n const char * cmp_buf,\n size_t cmp_len,\n uint64_t off,\n int * prval);\n",
|
||||
"added_in_version": "v0.12.0",
|
||||
"expected_stable_version": "v0.14.0"
|
||||
},
|
||||
{
|
||||
"name": "ReadOp.Read",
|
||||
"comment": "Read bytes from offset into buffer.\nlen(buffer) is the maximum number of bytes read from the object.\nbuffer[:ReadOpReadStep.BytesRead] then contains object data.\n PREVIEW\n\nImplements:\n void rados_read_op_read(rados_read_op_t read_op,\n uint64_t offset,\n size_t len,\n char * buffer,\n size_t * bytes_read,\n int * prval)\n",
|
||||
"added_in_version": "v0.14.0",
|
||||
"expected_stable_version": "v0.16.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
Name | Added in Version | Expected Stable Version |
|
||||
---- | ---------------- | ----------------------- |
|
||||
WriteOp.CmpExt | v0.12.0 | v0.14.0 |
|
||||
ReadOp.Read | v0.14.0 | v0.16.0 |
|
||||
|
||||
## Package: rbd
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
//go:build ceph_preview
|
||||
// +build ceph_preview
|
||||
|
||||
package rados
|
||||
|
||||
// #cgo LDFLAGS: -lrados
|
||||
// #include <rados/librados.h>
|
||||
// #include <stdlib.h>
|
||||
//
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// ReadOpReadStep holds the result of the Read read operation.
|
||||
// Result is valid only after Operate() was called.
|
||||
type ReadOpReadStep struct {
|
||||
// C returned data:
|
||||
bytesRead *C.size_t
|
||||
prval *C.int
|
||||
|
||||
BytesRead int64 // Bytes read by this action.
|
||||
Result int // Result of this action.
|
||||
}
|
||||
|
||||
func (s *ReadOpReadStep) update() error {
|
||||
s.BytesRead = (int64)(*s.bytesRead)
|
||||
s.Result = (int)(*s.prval)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ReadOpReadStep) free() {
|
||||
C.free(unsafe.Pointer(s.bytesRead))
|
||||
C.free(unsafe.Pointer(s.prval))
|
||||
|
||||
s.bytesRead = nil
|
||||
s.prval = nil
|
||||
}
|
||||
|
||||
func newReadOpReadStep() *ReadOpReadStep {
|
||||
return &ReadOpReadStep{
|
||||
bytesRead: (*C.size_t)(C.malloc(C.sizeof_size_t)),
|
||||
prval: (*C.int)(C.malloc(C.sizeof_int)),
|
||||
}
|
||||
}
|
||||
|
||||
// Read bytes from offset into buffer.
|
||||
// len(buffer) is the maximum number of bytes read from the object.
|
||||
// buffer[:ReadOpReadStep.BytesRead] then contains object data.
|
||||
// PREVIEW
|
||||
//
|
||||
// Implements:
|
||||
// void rados_read_op_read(rados_read_op_t read_op,
|
||||
// uint64_t offset,
|
||||
// size_t len,
|
||||
// char * buffer,
|
||||
// size_t * bytes_read,
|
||||
// int * prval)
|
||||
func (r *ReadOp) Read(offset uint64, buffer []byte) *ReadOpReadStep {
|
||||
oe := newReadStep(buffer, offset)
|
||||
readStep := newReadOpReadStep()
|
||||
r.steps = append(r.steps, oe, readStep)
|
||||
C.rados_read_op_read(
|
||||
r.op,
|
||||
oe.cOffset,
|
||||
oe.cReadLen,
|
||||
oe.cBuffer,
|
||||
readStep.bytesRead,
|
||||
readStep.prval,
|
||||
)
|
||||
|
||||
return readStep
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//go:build ceph_preview
|
||||
// +build ceph_preview
|
||||
|
||||
package rados
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func (suite *RadosTestSuite) TestReadOpRead() {
|
||||
suite.SetupConnection()
|
||||
ta := assert.New(suite.T())
|
||||
|
||||
var (
|
||||
oid = "TestReadOpRead"
|
||||
data = []byte("data to read")
|
||||
err error
|
||||
)
|
||||
|
||||
// Create an object and populate it with data.
|
||||
op1 := CreateWriteOp()
|
||||
defer op1.Release()
|
||||
op1.Create(CreateIdempotent)
|
||||
op1.WriteFull(data)
|
||||
err = op1.Operate(suite.ioctx, oid, OperationNoFlag)
|
||||
ta.NoError(err)
|
||||
|
||||
// Read the object's contents and compare them with expected data.
|
||||
readBuf := make([]byte, 64)
|
||||
op2 := CreateReadOp()
|
||||
defer op2.Release()
|
||||
readOpRes := op2.Read(0, readBuf)
|
||||
err = op2.Operate(suite.ioctx, oid, OperationNoFlag)
|
||||
ta.NoError(err)
|
||||
ta.Equal(int(0), readOpRes.Result)
|
||||
ta.Equal(int64(len(data)), readOpRes.BytesRead)
|
||||
ta.Equal(data, readBuf[:readOpRes.BytesRead])
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package rados
|
||||
|
||||
// #include <stdint.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type readStep struct {
|
||||
withoutUpdate
|
||||
withoutFree
|
||||
// the c pointer utilizes the Go byteslice data and no free is needed
|
||||
|
||||
// inputs:
|
||||
b []byte
|
||||
|
||||
// arguments:
|
||||
cBuffer *C.char
|
||||
cReadLen C.size_t
|
||||
cOffset C.uint64_t
|
||||
}
|
||||
|
||||
func newReadStep(b []byte, offset uint64) *readStep {
|
||||
return &readStep{
|
||||
b: b,
|
||||
cBuffer: (*C.char)(unsafe.Pointer(&b[0])), // TODO: must be pinned
|
||||
cReadLen: C.size_t(len(b)),
|
||||
cOffset: C.uint64_t(offset),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue