From ce64ef536a27365cf040fe806838033a2da4a187 Mon Sep 17 00:00:00 2001 From: John Mulligan Date: Wed, 25 Mar 2020 09:20:32 -0400 Subject: [PATCH] cephfs: split (mds) command functions and tests into new files Start organizing some of the cephfs functionality into functions grouped by files by moving the MDS command functions into a new file. Move the tests dedicated to those functions into a new matching file too. Signed-off-by: John Mulligan --- cephfs/cephfs.go | 73 ----------------------------------- cephfs/cephfs_test.go | 34 ----------------- cephfs/command.go | 86 ++++++++++++++++++++++++++++++++++++++++++ cephfs/command_test.go | 41 ++++++++++++++++++++ 4 files changed, 127 insertions(+), 107 deletions(-) create mode 100644 cephfs/command.go create mode 100644 cephfs/command_test.go diff --git a/cephfs/cephfs.go b/cephfs/cephfs.go index 6a8876d..25f3d30 100644 --- a/cephfs/cephfs.go +++ b/cephfs/cephfs.go @@ -211,76 +211,3 @@ func (mount *MountInfo) IsMounted() bool { ret := C.ceph_is_mounted(mount.mount) return ret == 1 } - -// MdsCommand sends commands to the specified MDS. -func (mount *MountInfo) MdsCommand(mdsSpec string, args [][]byte) ([]byte, string, error) { - return mount.mdsCommand(mdsSpec, args, nil) -} - -// MdsCommandWithInputBuffer sends commands to the specified MDS, with an input -// buffer. -func (mount *MountInfo) MdsCommandWithInputBuffer(mdsSpec string, args [][]byte, inputBuffer []byte) ([]byte, string, error) { - return mount.mdsCommand(mdsSpec, args, inputBuffer) -} - -// mdsCommand supports sending formatted commands to MDS. -// -// Implements: -// int ceph_mds_command(struct ceph_mount_info *cmount, -// const char *mds_spec, -// const char **cmd, -// size_t cmdlen, -// const char *inbuf, size_t inbuflen, -// char **outbuf, size_t *outbuflen, -// char **outs, size_t *outslen); -func (mount *MountInfo) mdsCommand(mdsSpec string, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) { - spec := C.CString(mdsSpec) - defer C.free(unsafe.Pointer(spec)) - - argc := len(args) - argv := make([]*C.char, argc) - - for i, arg := range args { - argv[i] = C.CString(string(arg)) - } - // free all array elements in a single defer - defer func() { - for i := range argv { - C.free(unsafe.Pointer(argv[i])) - } - }() - - var ( - outs, outbuf *C.char - outslen, outbuflen C.size_t - ) - inbuf := C.CString(string(inputBuffer)) - inbufLen := len(inputBuffer) - defer C.free(unsafe.Pointer(inbuf)) - - ret := C.ceph_mds_command( - mount.mount, // cephfs mount ref - spec, // mds spec - &argv[0], // cmd array - C.size_t(argc), // cmd array length - inbuf, // bulk input - C.size_t(inbufLen), // length inbuf - &outbuf, // buffer - &outbuflen, // buffer length - &outs, // status string - &outslen) - - if outslen > 0 { - info = C.GoStringN(outs, C.int(outslen)) - C.free(unsafe.Pointer(outs)) - } - if outbuflen > 0 { - buffer = C.GoBytes(unsafe.Pointer(outbuf), C.int(outbuflen)) - C.free(unsafe.Pointer(outbuf)) - } - if ret != 0 { - return nil, info, getError(ret) - } - - return buffer, info, nil -} diff --git a/cephfs/cephfs_test.go b/cephfs/cephfs_test.go index ac6a1ba..da18aaf 100644 --- a/cephfs/cephfs_test.go +++ b/cephfs/cephfs_test.go @@ -1,7 +1,6 @@ package cephfs import ( - "encoding/json" "fmt" "os" "path" @@ -310,39 +309,6 @@ func TestCreateMountWithId(t *testing.T) { assert.Contains(t, string(buf), `"bobolink"`) } -func TestMdsCommand(t *testing.T) { - mount := fsConnect(t) - defer fsDisconnect(t, mount) - - cmd := []byte(`{"prefix": "client ls"}`) - buf, info, err := mount.MdsCommand( - testMdsName, - [][]byte{cmd}) - assert.NoError(t, err) - assert.NotEqual(t, "", string(buf)) - assert.Equal(t, "", string(info)) - assert.Contains(t, string(buf), "ceph_version") - // response should also be valid json - var j []interface{} - err = json.Unmarshal(buf, &j) - assert.NoError(t, err) - assert.GreaterOrEqual(t, len(j), 1) -} - -func TestMdsCommandError(t *testing.T) { - mount := fsConnect(t) - defer fsDisconnect(t, mount) - - cmd := []byte("iAMinValId~~~") - buf, info, err := mount.MdsCommand( - testMdsName, - [][]byte{cmd}) - assert.Error(t, err) - assert.Equal(t, "", string(buf)) - assert.NotEqual(t, "", string(info)) - assert.Contains(t, string(info), "unparseable JSON") -} - func TestMountWithRoot(t *testing.T) { bMount := fsConnect(t) defer fsDisconnect(t, bMount) diff --git a/cephfs/command.go b/cephfs/command.go new file mode 100644 index 0000000..0c4b3b3 --- /dev/null +++ b/cephfs/command.go @@ -0,0 +1,86 @@ +package cephfs + +/* +#cgo LDFLAGS: -lcephfs +#cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64 +#include +#include +*/ +import "C" + +import ( + "unsafe" +) + +// MdsCommand sends commands to the specified MDS. +func (mount *MountInfo) MdsCommand(mdsSpec string, args [][]byte) ([]byte, string, error) { + return mount.mdsCommand(mdsSpec, args, nil) +} + +// MdsCommandWithInputBuffer sends commands to the specified MDS, with an input +// buffer. +func (mount *MountInfo) MdsCommandWithInputBuffer(mdsSpec string, args [][]byte, inputBuffer []byte) ([]byte, string, error) { + return mount.mdsCommand(mdsSpec, args, inputBuffer) +} + +// mdsCommand supports sending formatted commands to MDS. +// +// Implements: +// int ceph_mds_command(struct ceph_mount_info *cmount, +// const char *mds_spec, +// const char **cmd, +// size_t cmdlen, +// const char *inbuf, size_t inbuflen, +// char **outbuf, size_t *outbuflen, +// char **outs, size_t *outslen); +func (mount *MountInfo) mdsCommand(mdsSpec string, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) { + spec := C.CString(mdsSpec) + defer C.free(unsafe.Pointer(spec)) + + argc := len(args) + argv := make([]*C.char, argc) + + for i, arg := range args { + argv[i] = C.CString(string(arg)) + } + // free all array elements in a single defer + defer func() { + for i := range argv { + C.free(unsafe.Pointer(argv[i])) + } + }() + + var ( + outs, outbuf *C.char + outslen, outbuflen C.size_t + ) + inbuf := C.CString(string(inputBuffer)) + inbufLen := len(inputBuffer) + defer C.free(unsafe.Pointer(inbuf)) + + ret := C.ceph_mds_command( + mount.mount, // cephfs mount ref + spec, // mds spec + &argv[0], // cmd array + C.size_t(argc), // cmd array length + inbuf, // bulk input + C.size_t(inbufLen), // length inbuf + &outbuf, // buffer + &outbuflen, // buffer length + &outs, // status string + &outslen) + + if outslen > 0 { + info = C.GoStringN(outs, C.int(outslen)) + C.free(unsafe.Pointer(outs)) + } + if outbuflen > 0 { + buffer = C.GoBytes(unsafe.Pointer(outbuf), C.int(outbuflen)) + C.free(unsafe.Pointer(outbuf)) + } + if ret != 0 { + return nil, info, getError(ret) + } + + return buffer, info, nil +} diff --git a/cephfs/command_test.go b/cephfs/command_test.go new file mode 100644 index 0000000..0911241 --- /dev/null +++ b/cephfs/command_test.go @@ -0,0 +1,41 @@ +package cephfs + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMdsCommand(t *testing.T) { + mount := fsConnect(t) + defer fsDisconnect(t, mount) + + cmd := []byte(`{"prefix": "client ls"}`) + buf, info, err := mount.MdsCommand( + testMdsName, + [][]byte{cmd}) + assert.NoError(t, err) + assert.NotEqual(t, "", string(buf)) + assert.Equal(t, "", string(info)) + assert.Contains(t, string(buf), "ceph_version") + // response should also be valid json + var j []interface{} + err = json.Unmarshal(buf, &j) + assert.NoError(t, err) + assert.GreaterOrEqual(t, len(j), 1) +} + +func TestMdsCommandError(t *testing.T) { + mount := fsConnect(t) + defer fsDisconnect(t, mount) + + cmd := []byte("iAMinValId~~~") + buf, info, err := mount.MdsCommand( + testMdsName, + [][]byte{cmd}) + assert.Error(t, err) + assert.Equal(t, "", string(buf)) + assert.NotEqual(t, "", string(info)) + assert.Contains(t, string(info), "unparseable JSON") +}