mirror of
https://github.com/ceph/go-ceph
synced 2024-12-22 06:10:09 +00:00
cutil: allow passing free functions to command output type
The *_command functions in librados and libcephfs document the use of specific free functions for data allocated. These functions are currently just wrappers around C's free() function. However, to be more strictly compliant this change adds a free-function callback to the CommandOutput type and the specific free functions are now used outside the unit tests. Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
f2d0bb4692
commit
e2a78eec02
@ -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().SetFreeFunc(cephBufferFree)
|
||||
defer co.Free()
|
||||
|
||||
ret := C.ceph_mds_command(
|
||||
|
@ -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
|
||||
@ -22,16 +23,28 @@ type CommandOutput struct {
|
||||
// a CommandOutput provides can be used to get the results of ceph's
|
||||
// *_command functions.
|
||||
func NewCommandOutput() *CommandOutput {
|
||||
return &CommandOutput{}
|
||||
return &CommandOutput{
|
||||
free: free,
|
||||
}
|
||||
}
|
||||
|
||||
// SetFreeFunc sets the function used to free memory held by CommandOutput.
|
||||
// Not all uses of CommandOutput expect to use the basic C.free function
|
||||
// and either require or prefer the use of a custom deallocation function.
|
||||
// Use SetFreeFunc to change the free function and return the modified
|
||||
// CommandOutput object.
|
||||
func (co *CommandOutput) SetFreeFunc(f FreeFunc) *CommandOutput {
|
||||
co.free = f
|
||||
return co
|
||||
}
|
||||
|
||||
// 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 +92,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)
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package cutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -40,4 +41,16 @@ func TestCommandOutput(t *testing.T) {
|
||||
assert.Nil(t, b)
|
||||
assert.EqualValues(t, "i got rhythm", s)
|
||||
})
|
||||
t.Run("customFreeFunc", func(t *testing.T) {
|
||||
callCount := 0
|
||||
co := NewCommandOutput().SetFreeFunc(func(p unsafe.Pointer) {
|
||||
callCount++
|
||||
free(p)
|
||||
})
|
||||
assert.NotNil(t, co)
|
||||
testSetString(co.OutBuf(), co.OutBufLen(), "i got style")
|
||||
testSetString(co.Outs(), co.OutsLen(), "i got rhythm")
|
||||
co.Free()
|
||||
assert.Equal(t, 2, callCount)
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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().SetFreeFunc(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().SetFreeFunc(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().SetFreeFunc(radosBufferFree)
|
||||
defer co.Free()
|
||||
|
||||
ret := C.rados_mgr_command(
|
||||
|
Loading…
Reference in New Issue
Block a user