mirror of https://github.com/ceph/go-ceph
rados/striper: start new striper package
Start a new `rados/striper` package that wraps Ceph's libradosstriper. The libradosstriper library builds on top of the librados library to support striping large "objects" over multiple RADOS objects. Fixes: #1011 Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
60ea53dabd
commit
33ed5cea3d
|
@ -0,0 +1,32 @@
|
|||
//go:build ceph_preview
|
||||
|
||||
package striper
|
||||
|
||||
/*
|
||||
#include <errno.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"github.com/ceph/go-ceph/internal/errutil"
|
||||
)
|
||||
|
||||
// radosStriperError represents an error condition returned from the Ceph
|
||||
// rados striper APIs.
|
||||
type radosStriperError int
|
||||
|
||||
// Error returns the error string for the radosStriperError type.
|
||||
func (e radosStriperError) Error() string {
|
||||
return errutil.FormatErrorCode("rados", int(e))
|
||||
}
|
||||
|
||||
func (e radosStriperError) ErrorCode() int {
|
||||
return int(e)
|
||||
}
|
||||
|
||||
func getError(e C.int) error {
|
||||
if e == 0 {
|
||||
return nil
|
||||
}
|
||||
return radosStriperError(e)
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//go:build ceph_preview
|
||||
|
||||
package striper
|
||||
|
||||
// #cgo LDFLAGS: -lrados -lradosstriper
|
||||
// #include <stdlib.h>
|
||||
// #include <radosstriper/libradosstriper.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Read bytes into data from the striped object at the specified offset.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_read(rados_striper_t striper,
|
||||
// const char *soid,
|
||||
// const char *buf,
|
||||
// size_t len,
|
||||
// uint64_t off);
|
||||
func (s *Striper) Read(soid string, data []byte, offset uint64) (int, error) {
|
||||
csoid := C.CString(soid)
|
||||
defer C.free(unsafe.Pointer(csoid))
|
||||
|
||||
var bufptr *C.char
|
||||
if len(data) > 0 {
|
||||
bufptr = (*C.char)(unsafe.Pointer(&data[0]))
|
||||
}
|
||||
|
||||
ret := C.rados_striper_read(
|
||||
s.striper,
|
||||
csoid,
|
||||
bufptr,
|
||||
C.size_t(len(data)),
|
||||
C.uint64_t(offset))
|
||||
if ret >= 0 {
|
||||
return int(ret), nil
|
||||
}
|
||||
return 0, getError(ret)
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
//go:build (octopus || pacific || quincy) && ceph_preview
|
||||
|
||||
package striper
|
||||
|
||||
// #cgo LDFLAGS: -lrados -lradosstriper
|
||||
// #include <stdlib.h>
|
||||
// #include <radosstriper/libradosstriper.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Stat returns metadata describing the striped object.
|
||||
// This version of Stat uses an older API that does not provide time
|
||||
// granularity below a second: the Nsec value of the StatInfo.ModTime field
|
||||
// will always be zero.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_stat(rados_striper_t striper,
|
||||
// const char* soid,
|
||||
// uint64_t *psize,
|
||||
// time_t *pmtime);
|
||||
func (s *Striper) Stat(soid string) (StatInfo, error) {
|
||||
csoid := C.CString(soid)
|
||||
defer C.free(unsafe.Pointer(csoid))
|
||||
|
||||
var (
|
||||
size C.uint64_t
|
||||
mtime C.time_t
|
||||
)
|
||||
ret := C.rados_striper_stat(
|
||||
s.striper,
|
||||
csoid,
|
||||
&size,
|
||||
&mtime)
|
||||
|
||||
if ret < 0 {
|
||||
return StatInfo{}, getError(ret)
|
||||
}
|
||||
modts := Timespec{Sec: int64(mtime)}
|
||||
return StatInfo{
|
||||
Size: uint64(size),
|
||||
ModTime: modts,
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
//go:build !(octopus || pacific || quincy) && ceph_preview
|
||||
|
||||
package striper
|
||||
|
||||
// #cgo LDFLAGS: -lrados -lradosstriper
|
||||
// #include <stdlib.h>
|
||||
// #include <radosstriper/libradosstriper.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
ts "github.com/ceph/go-ceph/internal/timespec"
|
||||
)
|
||||
|
||||
// Stat returns metadata describing the striped object.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_stat2(rados_striper_t striper,
|
||||
// const char* soid,
|
||||
// uint64_t *psize,
|
||||
// struct timespec *pmtime);
|
||||
func (s *Striper) Stat(soid string) (StatInfo, error) {
|
||||
csoid := C.CString(soid)
|
||||
defer C.free(unsafe.Pointer(csoid))
|
||||
|
||||
var (
|
||||
size C.uint64_t
|
||||
mtime C.struct_timespec
|
||||
)
|
||||
ret := C.rados_striper_stat2(
|
||||
s.striper,
|
||||
csoid,
|
||||
&size,
|
||||
&mtime)
|
||||
|
||||
if ret < 0 {
|
||||
return StatInfo{}, getError(ret)
|
||||
}
|
||||
return StatInfo{
|
||||
Size: uint64(size),
|
||||
ModTime: Timespec(ts.CStructToTimespec(ts.CTimespecPtr(&mtime))),
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
//go:build ceph_preview
|
||||
|
||||
package striper
|
||||
|
||||
import (
|
||||
ts "github.com/ceph/go-ceph/internal/timespec"
|
||||
)
|
||||
|
||||
// Timespec behaves similarly to C's struct timespec.
|
||||
type Timespec ts.Timespec
|
||||
|
||||
// StatInfo contains values returned by a Striper's Stat call.
|
||||
type StatInfo struct {
|
||||
Size uint64
|
||||
ModTime Timespec
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
//go:build ceph_preview
|
||||
|
||||
package striper
|
||||
|
||||
// #cgo LDFLAGS: -lrados -lradosstriper
|
||||
// #include <errno.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <radosstriper/libradosstriper.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"github.com/ceph/go-ceph/rados"
|
||||
)
|
||||
|
||||
// Striper helps manage the reading, writing, and management of RADOS
|
||||
// striped objects.
|
||||
type Striper struct {
|
||||
striper C.rados_striper_t
|
||||
|
||||
// Hold a reference back to the ioctx that the striper depends on so
|
||||
// that Go doesn't garbage collect it prematurely.
|
||||
ioctx *rados.IOContext
|
||||
}
|
||||
|
||||
// Layout contains a group of values used to define the size parameters of
|
||||
// striped objects. Note that these parameters only effect new striped objects.
|
||||
// Existing striped objects retain the parameters they were created with.
|
||||
type Layout struct {
|
||||
StripeUnit uint
|
||||
StripeCount uint
|
||||
ObjectSize uint
|
||||
}
|
||||
|
||||
// New returns a rados Striper object created from a rados IOContext.
|
||||
func New(ioctx *rados.IOContext) (*Striper, error) {
|
||||
var s C.rados_striper_t
|
||||
ret := C.rados_striper_create(cephIoctx(ioctx), &s)
|
||||
if err := getError(ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Striper{s, ioctx}, nil
|
||||
}
|
||||
|
||||
// NewWithLayout returns a rados Striper object created from a rados IOContext
|
||||
// and striper layout parameters. These parameters will be used when new
|
||||
// objects are created.
|
||||
func NewWithLayout(ioctx *rados.IOContext, layout Layout) (*Striper, error) {
|
||||
striper, err := New(ioctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := striper.SetObjectLayoutStripeUnit(layout.StripeUnit); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := striper.SetObjectLayoutStripeCount(layout.StripeCount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := striper.SetObjectLayoutObjectSize(layout.ObjectSize); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return striper, nil
|
||||
}
|
||||
|
||||
// Destroy the radosstriper object at the Ceph API level.
|
||||
func (s *Striper) Destroy() {
|
||||
C.rados_striper_destroy(s.striper)
|
||||
}
|
||||
|
||||
// SetObjectLayoutStripeUnit sets the stripe unit value used to layout
|
||||
// new objects.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_set_object_layout_stripe_unit(rados_striper_t striper,
|
||||
// unsigned int stripe_unit);
|
||||
func (s *Striper) SetObjectLayoutStripeUnit(count uint) error {
|
||||
ret := C.rados_striper_set_object_layout_stripe_unit(
|
||||
s.striper,
|
||||
C.uint(count),
|
||||
)
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// SetObjectLayoutStripeCount sets the stripe count value used to layout
|
||||
// new objects.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_set_object_layout_stripe_count(rados_striper_t striper,
|
||||
// unsigned int stripe_count);
|
||||
func (s *Striper) SetObjectLayoutStripeCount(count uint) error {
|
||||
ret := C.rados_striper_set_object_layout_stripe_count(
|
||||
s.striper,
|
||||
C.uint(count),
|
||||
)
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// SetObjectLayoutObjectSize sets the object size value used to layout
|
||||
// new objects.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_set_object_layout_object_size(rados_striper_t striper,
|
||||
// unsigned int object_size);
|
||||
func (s *Striper) SetObjectLayoutObjectSize(count uint) error {
|
||||
ret := C.rados_striper_set_object_layout_object_size(
|
||||
s.striper,
|
||||
C.uint(count),
|
||||
)
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// cephIoctx returns a ceph rados_ioctx_t given a go-ceph rados IOContext.
|
||||
func cephIoctx(radosIoctx *rados.IOContext) C.rados_ioctx_t {
|
||||
p := radosIoctx.Pointer()
|
||||
if p == nil {
|
||||
panic("invalid IOContext pointer")
|
||||
}
|
||||
return C.rados_ioctx_t(p)
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
//go:build ceph_preview
|
||||
|
||||
package striper
|
||||
|
||||
// #cgo LDFLAGS: -lrados -lradosstriper
|
||||
// #include <stdlib.h>
|
||||
// #include <radosstriper/libradosstriper.h>
|
||||
import "C"
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// Write bytes from data into the striped object at the specified offset.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_write(rados_striper_t striper,
|
||||
// const char *soid,
|
||||
// const char *buf,
|
||||
// size_t len,
|
||||
// uint64_t off);
|
||||
func (s *Striper) Write(soid string, data []byte, offset uint64) error {
|
||||
csoid := C.CString(soid)
|
||||
defer C.free(unsafe.Pointer(csoid))
|
||||
|
||||
bufptr := (*C.char)(unsafe.Pointer(&data[0]))
|
||||
ret := C.rados_striper_write(
|
||||
s.striper,
|
||||
csoid,
|
||||
bufptr,
|
||||
C.size_t(len(data)),
|
||||
C.uint64_t(offset))
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// WriteFull writes all of the bytes in data to the striped object, truncating
|
||||
// the object to the length of data.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_write_full(rados_striper_t striper,
|
||||
// const char *soid,
|
||||
// const char *buf,
|
||||
// size_t len);
|
||||
func (s *Striper) WriteFull(soid string, data []byte) error {
|
||||
csoid := C.CString(soid)
|
||||
defer C.free(unsafe.Pointer(csoid))
|
||||
|
||||
bufptr := (*C.char)(unsafe.Pointer(&data[0]))
|
||||
ret := C.rados_striper_write_full(
|
||||
s.striper,
|
||||
csoid,
|
||||
bufptr,
|
||||
C.size_t(len(data)))
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// Append the bytes in data to the end of the striped object.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_append(rados_striper_t striper,
|
||||
// const char *soid,
|
||||
// const char *buf,
|
||||
// size_t len);
|
||||
func (s *Striper) Append(soid string, data []byte) error {
|
||||
csoid := C.CString(soid)
|
||||
defer C.free(unsafe.Pointer(csoid))
|
||||
|
||||
bufptr := (*C.char)(unsafe.Pointer(&data[0]))
|
||||
ret := C.rados_striper_append(
|
||||
s.striper,
|
||||
csoid,
|
||||
bufptr,
|
||||
C.size_t(len(data)))
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// Remove a striped RADOS object.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_remove(rados_striper_t striper,
|
||||
// const char *soid);
|
||||
func (s *Striper) Remove(soid string) error {
|
||||
csoid := C.CString(soid)
|
||||
defer C.free(unsafe.Pointer(csoid))
|
||||
|
||||
ret := C.rados_striper_remove(s.striper, csoid)
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// Truncate a striped object, setting it to the specified size.
|
||||
//
|
||||
// Implements:
|
||||
//
|
||||
// int rados_striper_trunc(rados_striper_t striper, const char *soid, uint64_t size);
|
||||
func (s *Striper) Truncate(soid string, size uint64) error {
|
||||
csoid := C.CString(soid)
|
||||
defer C.free(unsafe.Pointer(csoid))
|
||||
|
||||
ret := C.rados_striper_trunc(
|
||||
s.striper,
|
||||
csoid,
|
||||
C.uint64_t(size))
|
||||
return getError(ret)
|
||||
}
|
Loading…
Reference in New Issue