initial commit: starting go-rados library

Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
This commit is contained in:
Noah Watkins 2014-05-24 10:36:12 -07:00
commit 3a6efa08d6
4 changed files with 241 additions and 0 deletions

75
conn.go Normal file
View File

@ -0,0 +1,75 @@
package rados
// #cgo LDFLAGS: -lrados
// #include <stdlib.h>
// #include <rados/librados.h>
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))
}
}

78
pool.go Normal file
View File

@ -0,0 +1,78 @@
package rados
// #cgo LDFLAGS: -lrados
// #include <stdlib.h>
// #include <rados/librados.h>
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))
}
}

37
rados.go Normal file
View File

@ -0,0 +1,37 @@
package rados
// #cgo LDFLAGS: -lrados
// #include <stdlib.h>
// #include <rados/librados.h>
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))
}
}

51
rados_test.go Normal file
View File

@ -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")
// }
//}