commit 3a6efa08d603c13e04747b38591c43d15b67d772 Author: Noah Watkins Date: Sat May 24 10:36:12 2014 -0700 initial commit: starting go-rados library Signed-off-by: Noah Watkins diff --git a/conn.go b/conn.go new file mode 100644 index 0000000..c07a3f1 --- /dev/null +++ b/conn.go @@ -0,0 +1,75 @@ +package rados + +// #cgo LDFLAGS: -lrados +// #include +// #include +import "C" + +import "unsafe" + +type Conn struct { + cluster C.rados_t +} + +func (c *Conn) PingMonitor(id string) (string, error) { + c_id := C.CString(id) + defer C.free(unsafe.Pointer(c_id)) + + var strlen C.size_t + var strout *C.char + + ret := C.rados_ping_monitor(c.cluster, c_id, &strout, &strlen) + defer C.rados_buffer_free(strout) + + if ret == 0 { + reply := C.GoStringN(strout, (C.int)(strlen)) + return reply, nil + } else { + return "", RadosError(int(ret)) + } +} + +func (c *Conn) Connect() error { + ret := C.rados_connect(c.cluster) + if ret == 0 { + return nil + } else { + return RadosError(int(ret)) + } +} + +func (c *Conn) Shutdown() { + C.rados_shutdown(c.cluster) +} + +func (c *Conn) ReadConfigFile(path string) error { + c_path := C.CString(path) + defer C.free(unsafe.Pointer(c_path)) + ret := C.rados_conf_read_file(c.cluster, c_path) + if ret == 0 { + return nil + } else { + return RadosError(int(ret)) + } +} + +func (c *Conn) ReadDefaultConfigFile() error { + ret := C.rados_conf_read_file(c.cluster, nil) + if ret == 0 { + return nil + } else { + return RadosError(int(ret)) + } +} + +func (c *Conn) OpenPool(pool string) (*Pool, error) { + c_pool := C.CString(pool) + defer C.free(unsafe.Pointer(c_pool)) + ioctx := &Pool{} + ret := C.rados_ioctx_create(c.cluster, c_pool, &ioctx.ioctx) + if ret == 0 { + return ioctx, nil + } else { + return nil, RadosError(int(ret)) + } +} diff --git a/pool.go b/pool.go new file mode 100644 index 0000000..76fdf62 --- /dev/null +++ b/pool.go @@ -0,0 +1,78 @@ +package rados + +// #cgo LDFLAGS: -lrados +// #include +// #include +import "C" + +import "unsafe" + +type Pool struct { + ioctx C.rados_ioctx_t +} + +func (p *Pool) Write(oid string, data []byte, offset uint64) error { + c_oid := C.CString(oid) + defer C.free(unsafe.Pointer(c_oid)) + + ret := C.rados_write(p.ioctx, c_oid, + (*C.char)(unsafe.Pointer(&data[0])), + (C.size_t)(len(data)), + (C.uint64_t)(offset)) + + if ret == 0 { + return nil + } else { + return RadosError(int(ret)) + } +} + +// Read +func (p *Pool) Read(oid string, data []byte, offset uint64) (int, error) { + if len(data) == 0 { + return 0, nil + } + + c_oid := C.CString(oid) + defer C.free(unsafe.Pointer(c_oid)) + + ret := C.rados_read( + p.ioctx, + c_oid, + (*C.char)(unsafe.Pointer(&data[0])), + (C.size_t)(len(data)), + (C.uint64_t)(offset)) + + if ret >= 0 { + return int(ret), nil + } else { + return 0, RadosError(int(ret)) + } +} + +// Delete +func (p *Pool) Delete(oid string) error { + c_oid := C.CString(oid) + defer C.free(unsafe.Pointer(c_oid)) + + ret := C.rados_remove(p.ioctx, c_oid) + + if ret == 0 { + return nil + } else { + return RadosError(int(ret)) + } +} + +func (p *Pool) Truncate(oid string, size uint64) error { + c_oid := C.CString(oid) + defer C.free(unsafe.Pointer(c_oid)) + + ret := C.rados_trunc(p.ioctx, c_oid, (C.uint64_t)(size)) + + if ret == 0 { + return nil + } else { + return RadosError(int(ret)) + } +} diff --git a/rados.go b/rados.go new file mode 100644 index 0000000..159cf8f --- /dev/null +++ b/rados.go @@ -0,0 +1,37 @@ +package rados + +// #cgo LDFLAGS: -lrados +// #include +// #include +import "C" + +import ( + "unsafe" + "fmt" +) + +type RadosError int + +func (e RadosError) Error() string { + return fmt.Sprintf("rados: ret=%d", e) +} + +func Version() (int, int, int) { + var c_major, c_minor, c_patch C.int + C.rados_version(&c_major, &c_minor, &c_patch) + return int(c_major), int(c_minor), int(c_patch) +} + +func Open(id string) (*Conn, error) { + c_id := C.CString(id) + defer C.free(unsafe.Pointer(c_id)) + + conn := &Conn{} + ret := C.rados_create(&conn.cluster, c_id) + + if ret == 0 { + return conn, nil + } else { + return nil, RadosError(int(ret)) + } +} diff --git a/rados_test.go b/rados_test.go new file mode 100644 index 0000000..cda8644 --- /dev/null +++ b/rados_test.go @@ -0,0 +1,51 @@ +package rados_test + +import "testing" +//import "bytes" +import "github.com/noahdesu/rados" +import "github.com/stretchr/testify/assert" + +func TestVersion(t *testing.T) { + var major, minor, patch = rados.Version() + assert.False(t, major < 0 || major > 1000, "invalid major") + assert.False(t, minor < 0 || minor > 1000, "invalid minor") + assert.False(t, patch < 0 || patch > 1000, "invalid patch") +} + +func TestOpen(t *testing.T) { + _, err := rados.Open("admin") + assert.Equal(t, err, nil, "error") +} + +func TestConnect(t *testing.T) { + conn, _ := rados.Open("admin") + conn.ReadDefaultConfigFile() + err := conn.Connect() + assert.Equal(t, err, nil) +} + +func TestPingMonitor(t *testing.T) { + conn, _ := rados.Open("admin") + conn.ReadDefaultConfigFile() + conn.Connect() + reply, err := conn.PingMonitor("kyoto") + assert.Equal(t, err, nil) + assert.True(t, len(reply) > 0) +} + +//func TestConnect(t *testing.T) { +// conn, _ := rados.Open("admin") +// conn.ReadConfigFile("/home/nwatkins/ceph/ceph/src/ceph.conf") +// conn.Connect() +// pool, _ := conn.OpenPool("data") +// +// data_in := []byte("blah"); +// data_out := make([]byte, 10) +// +// pool.Write("xyz", data_in, 0) +// pool.Read("xyz", data_out[:4], 0) +// +// if !bytes.Equal(data_in, data_out[:4]) { +// t.Errorf("yuk") +// } +//}