diff --git a/rados/striper/xattr.go b/rados/striper/xattr.go new file mode 100644 index 000000000..20b7a6ba3 --- /dev/null +++ b/rados/striper/xattr.go @@ -0,0 +1,150 @@ +//go:build ceph_preview + +package striper + +// #cgo LDFLAGS: -lrados -lradosstriper +// #include +// #include +import "C" + +import ( + "errors" + "unsafe" +) + +var errStopIteration = errors.New("stop iteraton") + +// GetXattr retrieves an extended attribute (xattr) of the given name from the +// specified striped object. +// +// Implements: +// +// int rados_striper_getxattr(rados_striper_t striper, +// const char *oid, +// const char *name, +// char *buf, +// size_t len); +func (s *Striper) GetXattr(soid string, name string, data []byte) (int, error) { + csoid := C.CString(soid) + cName := C.CString(name) + defer C.free(unsafe.Pointer(csoid)) + defer C.free(unsafe.Pointer(cName)) + + ret := C.rados_striper_getxattr( + s.striper, + csoid, + cName, + (*C.char)(unsafe.Pointer(&data[0])), + (C.size_t)(len(data))) + + if ret >= 0 { + return int(ret), nil + } + return 0, getError(ret) +} + +// SetXattr sets an extended attribute (xattr) of the given name on the +// specified striped object. +// +// Implements: +// +// int rados_striper_setxattr(rados_striper_t striper, +// const char *oid, +// const char *name, +// const char *buf, +// size_t len); +func (s *Striper) SetXattr(soid string, name string, data []byte) error { + csoid := C.CString(soid) + cName := C.CString(name) + defer C.free(unsafe.Pointer(csoid)) + defer C.free(unsafe.Pointer(cName)) + + ret := C.rados_striper_setxattr( + s.striper, + csoid, + cName, + (*C.char)(unsafe.Pointer(&data[0])), + (C.size_t)(len(data))) + + return getError(ret) +} + +// RmXattr removes the extended attribute (xattr) of the given name from the +// striped object. +// +// Implements: +// +// int rados_striper_rmxattr(rados_striper_t striper, +// const char *oid, +// const char *name); +func (s *Striper) RmXattr(soid string, name string) error { + csoid := C.CString(soid) + cName := C.CString(name) + defer C.free(unsafe.Pointer(csoid)) + defer C.free(unsafe.Pointer(cName)) + + ret := C.rados_striper_rmxattr(s.striper, csoid, cName) + return getError(ret) +} + +// getXattrsNext wraps the function to fetch a xattr name/value pair +// from the iterator. If the iterator is exhausted the error value +// will be errStopIteration. +// +// Implements: +// +// int rados_striper_getxattrs_next(rados_xattrs_iter_t iter, +// const char **name, +// const char **val, +// size_t *len); +func getXattrsNext(it C.rados_xattrs_iter_t) (string, []byte, error) { + var ( + cName, cValue *C.char + cLen C.size_t + ) + defer C.free(unsafe.Pointer(cName)) + defer C.free(unsafe.Pointer(cValue)) + + ret := C.rados_striper_getxattrs_next(it, &cName, &cValue, &cLen) + if ret < 0 { + return "", nil, getError(ret) + } + if cName == nil && cValue == nil { + return "", nil, errStopIteration + } + return C.GoString(cName), C.GoBytes(unsafe.Pointer(cValue), C.int(cLen)), nil +} + +// ListXattrs returns a map containing all of the extended attributes (xattrs) +// for a striped object. The xattr names provide the key strings and the map's +// values are byte slices. +// +// Implements: +// +// int rados_striper_getxattrs(rados_striper_t striper, +// const char *oid, +// rados_xattrs_iter_t *iter); +func (s *Striper) ListXattrs(soid string) (map[string][]byte, error) { + csoid := C.CString(soid) + defer C.free(unsafe.Pointer(csoid)) + + var it C.rados_xattrs_iter_t + ret := C.rados_striper_getxattrs(s.striper, csoid, &it) + if ret < 0 { + return nil, getError(ret) + } + defer C.rados_striper_getxattrs_end(it) + + m := make(map[string][]byte) + for { + xname, xvalue, err := getXattrsNext(it) + if err == errStopIteration { + break + } + if err != nil { + return nil, err + } + m[xname] = xvalue + } + return m, nil +}