Skip to content

Commit

Permalink
rados: implement binding for rados_read_op_read
Browse files Browse the repository at this point in the history
This commit implements binding for rados_read_op_read RADOS Read operation.
Includes a unit test.

Signed-off-by: Robert Vasek <[email protected]>
  • Loading branch information
gman0 committed Jan 7, 2022
1 parent 0e3ed29 commit be5e4cf
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 0 deletions.
6 changes: 6 additions & 0 deletions docs/api-status.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.12.0",
"expected_stable_version": "v0.14.0"
}
]
},
Expand Down
1 change: 1 addition & 0 deletions docs/api-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Name | Added in Version | Expected Stable Version |
---- | ---------------- | ----------------------- |
WriteOp.CmpExt | v0.12.0 | v0.14.0 |
ReadOp.Read | v0.12.0 | v0.14.0 |

## Package: rbd

Expand Down
75 changes: 75 additions & 0 deletions rados/read_op_read.go
Original file line number Diff line number Diff line change
@@ -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
}
38 changes: 38 additions & 0 deletions rados/read_op_read_test.go
Original file line number Diff line number Diff line change
@@ -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])
}
31 changes: 31 additions & 0 deletions rados/read_step.go
Original file line number Diff line number Diff line change
@@ -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),
}
}

0 comments on commit be5e4cf

Please sign in to comment.