diff --git a/cephfs/command.go b/cephfs/command.go index 3ef780cbb..e12e5d7bd 100644 --- a/cephfs/command.go +++ b/cephfs/command.go @@ -14,6 +14,10 @@ import ( "github.com/ceph/go-ceph/internal/cutil" ) +func cephBufferFree(p unsafe.Pointer) { + C.ceph_buffer_free((*C.char)(p)) +} + // MdsCommand sends commands to the specified MDS. func (mount *MountInfo) MdsCommand(mdsSpec string, args [][]byte) ([]byte, string, error) { return mount.mdsCommand(mdsSpec, args, nil) @@ -40,7 +44,7 @@ func (mount *MountInfo) mdsCommand(mdsSpec string, args [][]byte, inputBuffer [] defer C.free(unsafe.Pointer(spec)) ci := cutil.NewCommandInput(args, inputBuffer) defer ci.Free() - co := cutil.NewCommandOutput() + co := cutil.NewCommandOutput(cephBufferFree) defer co.Free() ret := C.ceph_mds_command( diff --git a/internal/cutil/command_output.go b/internal/cutil/command_output.go index b6863a73f..4855c5813 100644 --- a/internal/cutil/command_output.go +++ b/internal/cutil/command_output.go @@ -12,6 +12,7 @@ import ( // CommandOutput can be used to manage the outputs of ceph's *_command // functions. type CommandOutput struct { + free FreeFunc outBuf *C.char outBufLen C.size_t outs *C.char @@ -21,17 +22,19 @@ type CommandOutput struct { // NewCommandOutput returns an empty CommandOutput. The pointers that // a CommandOutput provides can be used to get the results of ceph's // *_command functions. -func NewCommandOutput() *CommandOutput { - return &CommandOutput{} +func NewCommandOutput(free FreeFunc) *CommandOutput { + return &CommandOutput{ + free: free, + } } // Free any C memory tracked by this object. func (co *CommandOutput) Free() { if co.outBuf != nil { - C.free(unsafe.Pointer(co.outBuf)) + co.free(unsafe.Pointer(co.outBuf)) } if co.outs != nil { - C.free(unsafe.Pointer(co.outs)) + co.free(unsafe.Pointer(co.outs)) } } @@ -79,3 +82,9 @@ func testSetString(strp CharPtrPtr, lenp SizeTPtr, s string) { *sp = C.CString(s) *lp = C.size_t(len(s)) } + +// free wraps C.free. +// Required for unit tests that may not use cgo directly. +func free(p unsafe.Pointer) { + C.free(p) +} diff --git a/internal/cutil/command_output_test.go b/internal/cutil/command_output_test.go index 41619a6fe..3b321a812 100644 --- a/internal/cutil/command_output_test.go +++ b/internal/cutil/command_output_test.go @@ -8,12 +8,12 @@ import ( func TestCommandOutput(t *testing.T) { t.Run("newAndFree", func(t *testing.T) { - co := NewCommandOutput() + co := NewCommandOutput(free) assert.NotNil(t, co) co.Free() }) t.Run("setValues", func(t *testing.T) { - co := NewCommandOutput() + co := NewCommandOutput(free) assert.NotNil(t, co) defer co.Free() testSetString(co.OutBuf(), co.OutBufLen(), "i got style") @@ -23,7 +23,7 @@ func TestCommandOutput(t *testing.T) { assert.EqualValues(t, "i got rhythm", s) }) t.Run("setOnlyOutBuf", func(t *testing.T) { - co := NewCommandOutput() + co := NewCommandOutput(free) assert.NotNil(t, co) defer co.Free() testSetString(co.OutBuf(), co.OutBufLen(), "i got style") @@ -32,7 +32,7 @@ func TestCommandOutput(t *testing.T) { assert.EqualValues(t, "", s) }) t.Run("setOnlyOuts", func(t *testing.T) { - co := NewCommandOutput() + co := NewCommandOutput(free) assert.NotNil(t, co) defer co.Free() testSetString(co.Outs(), co.OutsLen(), "i got rhythm") diff --git a/internal/cutil/type_aliases.go b/internal/cutil/type_aliases.go index f566fdaec..79495ef98 100644 --- a/internal/cutil/type_aliases.go +++ b/internal/cutil/type_aliases.go @@ -23,3 +23,6 @@ type CharPtr unsafe.Pointer // SizeTPtr is an unsafe pointer wrapping C's `size_t*`. type SizeTPtr unsafe.Pointer + +// FreeFunc is a wrapper around calls to, or act like, C's free function. +type FreeFunc func(unsafe.Pointer) diff --git a/rados/command.go b/rados/command.go index 1d6a1b565..2601bfddd 100644 --- a/rados/command.go +++ b/rados/command.go @@ -11,6 +11,10 @@ import ( "github.com/ceph/go-ceph/internal/cutil" ) +func radosBufferFree(p unsafe.Pointer) { + C.rados_buffer_free((*C.char)(p)) +} + // MonCommand sends a command to one of the monitors func (c *Conn) MonCommand(args []byte) ([]byte, string, error) { return c.monCommand(args, nil) @@ -24,7 +28,7 @@ func (c *Conn) MonCommandWithInputBuffer(args, inputBuffer []byte) ([]byte, stri func (c *Conn) monCommand(args, inputBuffer []byte) ([]byte, string, error) { ci := cutil.NewCommandInput([][]byte{args}, inputBuffer) defer ci.Free() - co := cutil.NewCommandOutput() + co := cutil.NewCommandOutput(radosBufferFree) defer co.Free() ret := C.rados_mon_command( @@ -70,7 +74,7 @@ func (c *Conn) pgCommand(pgid []byte, args [][]byte, inputBuffer []byte) ([]byte defer C.free(unsafe.Pointer(name)) ci := cutil.NewCommandInput(args, inputBuffer) defer ci.Free() - co := cutil.NewCommandOutput() + co := cutil.NewCommandOutput(radosBufferFree) defer co.Free() ret := C.rados_pg_command( @@ -107,7 +111,7 @@ func (c *Conn) MgrCommandWithInputBuffer(args [][]byte, inputBuffer []byte) ([]b func (c *Conn) mgrCommand(args [][]byte, inputBuffer []byte) ([]byte, string, error) { ci := cutil.NewCommandInput(args, inputBuffer) defer ci.Free() - co := cutil.NewCommandOutput() + co := cutil.NewCommandOutput(radosBufferFree) defer co.Free() ret := C.rados_mgr_command(