From 0443277bb91feb79cbd920ed3565b42e60dcf9e7 Mon Sep 17 00:00:00 2001 From: Robert Vasek Date: Mon, 27 Sep 2021 14:08:50 +0200 Subject: [PATCH] rados: implement binding for rados_write_op_cmpext This commit implements binding for rados_write_op_cmpext RADOS Write operation. Includes a unit test. Signed-off-by: Robert Vasek --- docs/api-status.json | 10 +++++- docs/api-status.md | 10 ++++-- internal/cutil/aliases.go | 3 ++ rados/write_op_preview.go | 63 ++++++++++++++++++++++++++++++++++ rados/write_op_preview_test.go | 40 +++++++++++++++++++++ 5 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 rados/write_op_preview.go create mode 100644 rados/write_op_preview_test.go diff --git a/docs/api-status.json b/docs/api-status.json index fca3255580..8fee5c283b 100644 --- a/docs/api-status.json +++ b/docs/api-status.json @@ -925,6 +925,14 @@ "name": "WriteOp.WriteSame", "comment": "WriteSame write a given byte slice to the object multiple times, until\nwriteLen is satisfied.\n\nImplements:\n void rados_write_op_writesame(rados_write_op_t write_op,\n const char *buffer,\n size_t data_len,\n size_t write_len,\n uint64_t offset);\n" } + ], + "preview_api": [ + { + "name": "WriteOp.CmpExt", + "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" + } ] }, "rbd": { @@ -1709,4 +1717,4 @@ } ] } -} +} \ No newline at end of file diff --git a/docs/api-status.md b/docs/api-status.md index 5f37686fd3..2f921ea4a9 100644 --- a/docs/api-status.md +++ b/docs/api-status.md @@ -8,6 +8,12 @@ ## Package: rados +### Preview APIs + +Name | Added in Version | Expected Stable Version | +---- | ---------------- | ----------------------- | +WriteOp.CmpExt | v0.12.0 | v0.14.0 | + ## Package: rbd ### Deprecated APIs @@ -20,10 +26,10 @@ Snapshot.Set | v0.10.0 | | ## Package: rbd/admin -### Preview APIs - ## Package: rgw/admin ### Preview APIs +Name | Added in Version | Expected Stable Version | +---- | ---------------- | ----------------------- | diff --git a/internal/cutil/aliases.go b/internal/cutil/aliases.go index 309c19dab1..610ead9168 100644 --- a/internal/cutil/aliases.go +++ b/internal/cutil/aliases.go @@ -23,6 +23,9 @@ const ( SizeTSize = C.sizeof_size_t ) +// Compile-time assertion ensuring that Go's `int` is at least as large as C's. +const _ = unsafe.Sizeof(int(0)) - C.sizeof_int + // SizeT wraps size_t from C. type SizeT C.size_t diff --git a/rados/write_op_preview.go b/rados/write_op_preview.go new file mode 100644 index 0000000000..2a01411a6a --- /dev/null +++ b/rados/write_op_preview.go @@ -0,0 +1,63 @@ +//go:build ceph_preview +// +build ceph_preview + +package rados + +// #cgo LDFLAGS: -lrados +// #include +// #include +// +import "C" + +import ( + "unsafe" +) + +// WriteOpCmpExtStep holds result of the CmpExt write operation. +// Result is valid only after Operate() was called. +type WriteOpCmpExtStep struct { + // C returned data: + prval *C.int + + // Result of the CmpExt write operation. + Result int +} + +func (s *WriteOpCmpExtStep) update() error { + s.Result = int(*s.prval) + return nil +} + +func (s *WriteOpCmpExtStep) free() { + C.free(unsafe.Pointer(s.prval)) + s.prval = nil +} + +func newWriteOpCmpExtStep() *WriteOpCmpExtStep { + return &WriteOpCmpExtStep{ + prval: (*C.int)(C.malloc(C.sizeof_int)), + } +} + +// CmpExt ensures that given object range (extent) satisfies comparison. +// PREVIEW +// +// Implements: +// void rados_write_op_cmpext(rados_write_op_t write_op, +// const char * cmp_buf, +// size_t cmp_len, +// uint64_t off, +// int * prval); +func (w *WriteOp) CmpExt(b []byte, offset uint64) *WriteOpCmpExtStep { + oe := newWriteStep(b, 0, offset) + cmpExtStep := newWriteOpCmpExtStep() + w.steps = append(w.steps, oe, cmpExtStep) + C.rados_write_op_cmpext( + w.op, + oe.cBuffer, + oe.cDataLen, + oe.cOffset, + cmpExtStep.prval) + + return cmpExtStep +} diff --git a/rados/write_op_preview_test.go b/rados/write_op_preview_test.go new file mode 100644 index 0000000000..b6319db2e8 --- /dev/null +++ b/rados/write_op_preview_test.go @@ -0,0 +1,40 @@ +//go:build ceph_preview +// +build ceph_preview + +package rados + +import ( + "github.com/stretchr/testify/assert" +) + +func (suite *RadosTestSuite) TestWriteOpCmpExt() { + suite.SetupConnection() + ta := assert.New(suite.T()) + + oid := "TestWriteOpCmpExt" + data := []byte("compare this") + + // Create an object and populate it with data. + op1 := CreateWriteOp() + defer op1.Release() + op1.Create(CreateIdempotent) + op1.WriteFull([]byte(data)) + err := op1.Operate(suite.ioctx, oid, OperationNoFlag) + ta.NoError(err) + + // Compare contents of the object. Should succeed. + op2 := CreateWriteOp() + defer op2.Release() + cmpExtRes1 := op2.CmpExt(data, 0) + err = op2.Operate(suite.ioctx, oid, OperationNoFlag) + ta.NoError(err) + ta.Equal(cmpExtRes1.Result, int(0)) + + // Compare contents of the object. Should fail. + op3 := CreateWriteOp() + defer op3.Release() + cmpExtRes2 := op3.CmpExt([]byte("xxx"), 0) + err = op3.Operate(suite.ioctx, oid, OperationNoFlag) + ta.Error(err) + ta.NotEqual(cmpExtRes2.Result, int(0)) +}