mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-26 08:10:20 +00:00
dep: add github.com/ceph/go-ceph for rbd API
Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
parent
3226b17d08
commit
ba99275f90
14
Gopkg.lock
generated
14
Gopkg.lock
generated
@ -25,6 +25,18 @@
|
||||
revision = "ba2c2ddd89069b46a7011d4106f6868f17ee1705"
|
||||
version = "v3.6.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:286a840b63ddce8e6f85368e22a834aefcaaf23f18a58ce01a42d7a978d21baf"
|
||||
name = "github.com/ceph/go-ceph"
|
||||
packages = [
|
||||
"errutil",
|
||||
"rados",
|
||||
"rbd",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "dc289754c8976f8cca2eb47dbea81895a4cac872"
|
||||
version = "v0.2.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:7f21fa1f8ab9a529dba26a7e9cf20de217c307fa1d96cb599d3afd9e5c83e9d6"
|
||||
name = "github.com/container-storage-interface/spec"
|
||||
@ -1331,6 +1343,8 @@
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/ceph/go-ceph/rados",
|
||||
"github.com/ceph/go-ceph/rbd",
|
||||
"github.com/container-storage-interface/spec/lib/go/csi",
|
||||
"github.com/golang/protobuf/ptypes",
|
||||
"github.com/golang/protobuf/ptypes/timestamp",
|
||||
|
@ -75,6 +75,10 @@
|
||||
branch = "master"
|
||||
name = "k8s.io/utils"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/ceph/go-ceph"
|
||||
version = "0.2"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
non-go = true
|
||||
@ -84,4 +88,3 @@
|
||||
[[prune.project]]
|
||||
name = "github.com/kubernetes-csi/external-snapshotter"
|
||||
non-go = false
|
||||
|
||||
|
21
vendor/github.com/ceph/go-ceph/LICENSE
generated
vendored
Normal file
21
vendor/github.com/ceph/go-ceph/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Noah Watkins
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
45
vendor/github.com/ceph/go-ceph/errutil/strerror.go
generated
vendored
Normal file
45
vendor/github.com/ceph/go-ceph/errutil/strerror.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Package errutil provides common functions for dealing with error conditions for
|
||||
all ceph api wrappers.
|
||||
*/
|
||||
package errutil
|
||||
|
||||
/* force XSI-complaint strerror_r() */
|
||||
|
||||
// #define _POSIX_C_SOURCE 200112L
|
||||
// #undef _GNU_SOURCE
|
||||
// #include <stdlib.h>
|
||||
// #include <errno.h>
|
||||
// #include <string.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// FormatErrno returns the absolute value of the errno as well as a string
|
||||
// describing the errno. The string will be empty is the errno is not known.
|
||||
func FormatErrno(errno int) (int, string) {
|
||||
buf := make([]byte, 1024)
|
||||
// strerror expects errno >= 0
|
||||
if errno < 0 {
|
||||
errno = -errno
|
||||
}
|
||||
|
||||
ret := C.strerror_r(
|
||||
C.int(errno),
|
||||
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||
C.size_t(len(buf)))
|
||||
if ret != 0 {
|
||||
return errno, ""
|
||||
}
|
||||
|
||||
return errno, C.GoString((*C.char)(unsafe.Pointer(&buf[0])))
|
||||
}
|
||||
|
||||
// StrError returns a string describing the errno. The string will be empty if
|
||||
// the errno is not known.
|
||||
func StrError(errno int) string {
|
||||
_, s := FormatErrno(errno)
|
||||
return s
|
||||
}
|
408
vendor/github.com/ceph/go-ceph/rados/conn.go
generated
vendored
Normal file
408
vendor/github.com/ceph/go-ceph/rados/conn.go
generated
vendored
Normal file
@ -0,0 +1,408 @@
|
||||
package rados
|
||||
|
||||
// #cgo LDFLAGS: -lrados
|
||||
// #include <stdlib.h>
|
||||
// #include <rados/librados.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotConnected is returned when functions are called without a RADOS connection
|
||||
ErrNotConnected = errors.New("RADOS not connected")
|
||||
)
|
||||
|
||||
// ClusterStat represents Ceph cluster statistics.
|
||||
type ClusterStat struct {
|
||||
Kb uint64
|
||||
Kb_used uint64
|
||||
Kb_avail uint64
|
||||
Num_objects uint64
|
||||
}
|
||||
|
||||
// Conn is a connection handle to a Ceph cluster.
|
||||
type Conn struct {
|
||||
cluster C.rados_t
|
||||
connected bool
|
||||
}
|
||||
|
||||
// ClusterRef represents a fundamental RADOS cluster connection.
|
||||
type ClusterRef C.rados_t
|
||||
|
||||
// Cluster returns the underlying RADOS cluster reference for this Conn.
|
||||
func (c *Conn) Cluster() ClusterRef {
|
||||
return ClusterRef(c.cluster)
|
||||
}
|
||||
|
||||
// PingMonitor sends a ping to a monitor and returns the reply.
|
||||
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
|
||||
}
|
||||
return "", RadosError(int(ret))
|
||||
}
|
||||
|
||||
// Connect establishes a connection to a RADOS cluster. It returns an error,
|
||||
// if any.
|
||||
func (c *Conn) Connect() error {
|
||||
ret := C.rados_connect(c.cluster)
|
||||
if ret != 0 {
|
||||
return RadosError(int(ret))
|
||||
}
|
||||
c.connected = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown disconnects from the cluster.
|
||||
func (c *Conn) Shutdown() {
|
||||
if err := c.ensure_connected(); err != nil {
|
||||
return
|
||||
}
|
||||
freeConn(c)
|
||||
}
|
||||
|
||||
// ReadConfigFile configures the connection using a Ceph configuration file.
|
||||
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)
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// ReadDefaultConfigFile configures the connection using a Ceph configuration
|
||||
// file located at default locations.
|
||||
func (c *Conn) ReadDefaultConfigFile() error {
|
||||
ret := C.rados_conf_read_file(c.cluster, nil)
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// OpenIOContext creates and returns a new IOContext for the given pool.
|
||||
//
|
||||
// Implements:
|
||||
// int rados_ioctx_create(rados_t cluster, const char *pool_name,
|
||||
// rados_ioctx_t *ioctx);
|
||||
func (c *Conn) OpenIOContext(pool string) (*IOContext, error) {
|
||||
c_pool := C.CString(pool)
|
||||
defer C.free(unsafe.Pointer(c_pool))
|
||||
ioctx := &IOContext{}
|
||||
ret := C.rados_ioctx_create(c.cluster, c_pool, &ioctx.ioctx)
|
||||
if ret == 0 {
|
||||
return ioctx, nil
|
||||
}
|
||||
return nil, RadosError(int(ret))
|
||||
}
|
||||
|
||||
// ListPools returns the names of all existing pools.
|
||||
func (c *Conn) ListPools() (names []string, err error) {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
ret := int(C.rados_pool_list(c.cluster,
|
||||
(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
|
||||
if ret < 0 {
|
||||
return nil, RadosError(int(ret))
|
||||
}
|
||||
|
||||
if ret > len(buf) {
|
||||
buf = make([]byte, ret)
|
||||
continue
|
||||
}
|
||||
|
||||
tmp := bytes.SplitAfter(buf[:ret-1], []byte{0})
|
||||
for _, s := range tmp {
|
||||
if len(s) > 0 {
|
||||
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetConfigOption sets the value of the configuration option identified by
|
||||
// the given name.
|
||||
func (c *Conn) SetConfigOption(option, value string) error {
|
||||
c_opt, c_val := C.CString(option), C.CString(value)
|
||||
defer C.free(unsafe.Pointer(c_opt))
|
||||
defer C.free(unsafe.Pointer(c_val))
|
||||
ret := C.rados_conf_set(c.cluster, c_opt, c_val)
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// GetConfigOption returns the value of the Ceph configuration option
|
||||
// identified by the given name.
|
||||
func (c *Conn) GetConfigOption(name string) (value string, err error) {
|
||||
buf := make([]byte, 4096)
|
||||
c_name := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
ret := int(C.rados_conf_get(c.cluster, c_name,
|
||||
(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
|
||||
// FIXME: ret may be -ENAMETOOLONG if the buffer is not large enough. We
|
||||
// can handle this case, but we need a reliable way to test for
|
||||
// -ENAMETOOLONG constant. Will the syscall/Errno stuff in Go help?
|
||||
if ret == 0 {
|
||||
value = C.GoString((*C.char)(unsafe.Pointer(&buf[0])))
|
||||
return value, nil
|
||||
}
|
||||
return "", RadosError(ret)
|
||||
}
|
||||
|
||||
// WaitForLatestOSDMap blocks the caller until the latest OSD map has been
|
||||
// retrieved.
|
||||
func (c *Conn) WaitForLatestOSDMap() error {
|
||||
ret := C.rados_wait_for_latest_osdmap(c.cluster)
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
func (c *Conn) ensure_connected() error {
|
||||
if c.connected {
|
||||
return nil
|
||||
}
|
||||
return ErrNotConnected
|
||||
}
|
||||
|
||||
// GetClusterStats returns statistics about the cluster associated with the
|
||||
// connection.
|
||||
func (c *Conn) GetClusterStats() (stat ClusterStat, err error) {
|
||||
if err := c.ensure_connected(); err != nil {
|
||||
return ClusterStat{}, err
|
||||
}
|
||||
c_stat := C.struct_rados_cluster_stat_t{}
|
||||
ret := C.rados_cluster_stat(c.cluster, &c_stat)
|
||||
if ret < 0 {
|
||||
return ClusterStat{}, RadosError(int(ret))
|
||||
}
|
||||
return ClusterStat{
|
||||
Kb: uint64(c_stat.kb),
|
||||
Kb_used: uint64(c_stat.kb_used),
|
||||
Kb_avail: uint64(c_stat.kb_avail),
|
||||
Num_objects: uint64(c_stat.num_objects),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ParseCmdLineArgs configures the connection from command line arguments.
|
||||
func (c *Conn) ParseCmdLineArgs(args []string) error {
|
||||
// add an empty element 0 -- Ceph treats the array as the actual contents
|
||||
// of argv and skips the first element (the executable name)
|
||||
argc := C.int(len(args) + 1)
|
||||
argv := make([]*C.char, argc)
|
||||
|
||||
// make the first element a string just in case it is ever examined
|
||||
argv[0] = C.CString("placeholder")
|
||||
defer C.free(unsafe.Pointer(argv[0]))
|
||||
|
||||
for i, arg := range args {
|
||||
argv[i+1] = C.CString(arg)
|
||||
defer C.free(unsafe.Pointer(argv[i+1]))
|
||||
}
|
||||
|
||||
ret := C.rados_conf_parse_argv(c.cluster, argc, &argv[0])
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// ParseDefaultConfigEnv configures the connection from the default Ceph
|
||||
// environment variable(s).
|
||||
func (c *Conn) ParseDefaultConfigEnv() error {
|
||||
ret := C.rados_conf_parse_env(c.cluster, nil)
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// GetFSID returns the fsid of the cluster as a hexadecimal string. The fsid
|
||||
// is a unique identifier of an entire Ceph cluster.
|
||||
func (c *Conn) GetFSID() (fsid string, err error) {
|
||||
buf := make([]byte, 37)
|
||||
ret := int(C.rados_cluster_fsid(c.cluster,
|
||||
(*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
|
||||
// FIXME: the success case isn't documented correctly in librados.h
|
||||
if ret == 36 {
|
||||
fsid = C.GoString((*C.char)(unsafe.Pointer(&buf[0])))
|
||||
return fsid, nil
|
||||
}
|
||||
return "", RadosError(int(ret))
|
||||
}
|
||||
|
||||
// GetInstanceID returns a globally unique identifier for the cluster
|
||||
// connection instance.
|
||||
func (c *Conn) GetInstanceID() uint64 {
|
||||
// FIXME: are there any error cases for this?
|
||||
return uint64(C.rados_get_instance_id(c.cluster))
|
||||
}
|
||||
|
||||
// MakePool creates a new pool with default settings.
|
||||
func (c *Conn) MakePool(name string) error {
|
||||
c_name := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
ret := int(C.rados_pool_create(c.cluster, c_name))
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// DeletePool deletes a pool and all the data inside the pool.
|
||||
func (c *Conn) DeletePool(name string) error {
|
||||
if err := c.ensure_connected(); err != nil {
|
||||
return err
|
||||
}
|
||||
c_name := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
ret := int(C.rados_pool_delete(c.cluster, c_name))
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// GetPoolByName returns the ID of the pool with a given name.
|
||||
func (c *Conn) GetPoolByName(name string) (int64, error) {
|
||||
if err := c.ensure_connected(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
c_name := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
ret := int64(C.rados_pool_lookup(c.cluster, c_name))
|
||||
if ret < 0 {
|
||||
return 0, RadosError(ret)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// GetPoolByID returns the name of a pool by a given ID.
|
||||
func (c *Conn) GetPoolByID(id int64) (string, error) {
|
||||
buf := make([]byte, 4096)
|
||||
if err := c.ensure_connected(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
c_id := C.int64_t(id)
|
||||
ret := int(C.rados_pool_reverse_lookup(c.cluster, c_id, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))))
|
||||
if ret < 0 {
|
||||
return "", RadosError(ret)
|
||||
}
|
||||
return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil
|
||||
}
|
||||
|
||||
// MonCommand sends a command to one of the monitors
|
||||
func (c *Conn) MonCommand(args []byte) (buffer []byte, info string, err error) {
|
||||
return c.monCommand(args, nil)
|
||||
}
|
||||
|
||||
// MonCommandWithInputBuffer sends a command to one of the monitors, with an input buffer
|
||||
func (c *Conn) MonCommandWithInputBuffer(args, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
return c.monCommand(args, inputBuffer)
|
||||
}
|
||||
|
||||
func (c *Conn) monCommand(args, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
argv := C.CString(string(args))
|
||||
defer C.free(unsafe.Pointer(argv))
|
||||
|
||||
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.rados_mon_command(c.cluster,
|
||||
&argv, 1,
|
||||
inbuf, // bulk input (e.g. crush map)
|
||||
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 {
|
||||
err = RadosError(int(ret))
|
||||
return nil, info, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// PGCommand sends a command to one of the PGs
|
||||
//
|
||||
// Implements:
|
||||
// int rados_pg_command(rados_t cluster, const char *pgstr,
|
||||
// const char **cmd, size_t cmdlen,
|
||||
// const char *inbuf, size_t inbuflen,
|
||||
// char **outbuf, size_t *outbuflen,
|
||||
// char **outs, size_t *outslen);
|
||||
func (c *Conn) PGCommand(pgid []byte, args [][]byte) (buffer []byte, info string, err error) {
|
||||
return c.pgCommand(pgid, args, nil)
|
||||
}
|
||||
|
||||
// PGCommandWithInputBuffer sends a command to one of the PGs, with an input buffer
|
||||
//
|
||||
// Implements:
|
||||
// int rados_pg_command(rados_t cluster, const char *pgstr,
|
||||
// const char **cmd, size_t cmdlen,
|
||||
// const char *inbuf, size_t inbuflen,
|
||||
// char **outbuf, size_t *outbuflen,
|
||||
// char **outs, size_t *outslen);
|
||||
func (c *Conn) PGCommandWithInputBuffer(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
return c.pgCommand(pgid, args, inputBuffer)
|
||||
}
|
||||
|
||||
func (c *Conn) pgCommand(pgid []byte, args [][]byte, inputBuffer []byte) (buffer []byte, info string, err error) {
|
||||
name := C.CString(string(pgid))
|
||||
defer C.free(unsafe.Pointer(name))
|
||||
|
||||
argc := len(args)
|
||||
argv := make([]*C.char, argc)
|
||||
|
||||
for i, arg := range args {
|
||||
argv[i] = C.CString(string(arg))
|
||||
defer 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.rados_pg_command(c.cluster,
|
||||
name,
|
||||
&argv[0],
|
||||
C.size_t(argc),
|
||||
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 {
|
||||
err = RadosError(int(ret))
|
||||
return nil, info, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
4
vendor/github.com/ceph/go-ceph/rados/doc.go
generated
vendored
Normal file
4
vendor/github.com/ceph/go-ceph/rados/doc.go
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/*
|
||||
Package rados contains a set of wrappers around Ceph's librados API.
|
||||
*/
|
||||
package rados
|
622
vendor/github.com/ceph/go-ceph/rados/ioctx.go
generated
vendored
Normal file
622
vendor/github.com/ceph/go-ceph/rados/ioctx.go
generated
vendored
Normal file
@ -0,0 +1,622 @@
|
||||
package rados
|
||||
|
||||
// #cgo LDFLAGS: -lrados
|
||||
// #include <errno.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <rados/librados.h>
|
||||
//
|
||||
// char* nextChunk(char **idx) {
|
||||
// char *copy;
|
||||
// copy = strdup(*idx);
|
||||
// *idx += strlen(*idx) + 1;
|
||||
// return copy;
|
||||
// }
|
||||
//
|
||||
// #if __APPLE__
|
||||
// #define ceph_time_t __darwin_time_t
|
||||
// #define ceph_suseconds_t __darwin_suseconds_t
|
||||
// #elif __GLIBC__
|
||||
// #define ceph_time_t __time_t
|
||||
// #define ceph_suseconds_t __suseconds_t
|
||||
// #else
|
||||
// #define ceph_time_t time_t
|
||||
// #define ceph_suseconds_t suseconds_t
|
||||
// #endif
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// CreateOption is passed to IOContext.Create() and should be one of
|
||||
// CreateExclusive or CreateIdempotent.
|
||||
type CreateOption int
|
||||
|
||||
const (
|
||||
// CreateExclusive if used with IOContext.Create() and the object
|
||||
// already exists, the function will return an error.
|
||||
CreateExclusive = C.LIBRADOS_CREATE_EXCLUSIVE
|
||||
// CreateIdempotent if used with IOContext.Create() and the object
|
||||
// already exists, the function will not return an error.
|
||||
CreateIdempotent = C.LIBRADOS_CREATE_IDEMPOTENT
|
||||
)
|
||||
|
||||
// PoolStat represents Ceph pool statistics.
|
||||
type PoolStat struct {
|
||||
// space used in bytes
|
||||
Num_bytes uint64
|
||||
// space used in KB
|
||||
Num_kb uint64
|
||||
// number of objects in the pool
|
||||
Num_objects uint64
|
||||
// number of clones of objects
|
||||
Num_object_clones uint64
|
||||
// num_objects * num_replicas
|
||||
Num_object_copies uint64
|
||||
Num_objects_missing_on_primary uint64
|
||||
// number of objects found on no OSDs
|
||||
Num_objects_unfound uint64
|
||||
// number of objects replicated fewer times than they should be
|
||||
// (but found on at least one OSD)
|
||||
Num_objects_degraded uint64
|
||||
Num_rd uint64
|
||||
Num_rd_kb uint64
|
||||
Num_wr uint64
|
||||
Num_wr_kb uint64
|
||||
}
|
||||
|
||||
// ObjectStat represents an object stat information
|
||||
type ObjectStat struct {
|
||||
// current length in bytes
|
||||
Size uint64
|
||||
// last modification time
|
||||
ModTime time.Time
|
||||
}
|
||||
|
||||
// LockInfo represents information on a current Ceph lock
|
||||
type LockInfo struct {
|
||||
NumLockers int
|
||||
Exclusive bool
|
||||
Tag string
|
||||
Clients []string
|
||||
Cookies []string
|
||||
Addrs []string
|
||||
}
|
||||
|
||||
// IOContext represents a context for performing I/O within a pool.
|
||||
type IOContext struct {
|
||||
ioctx C.rados_ioctx_t
|
||||
}
|
||||
|
||||
// Pointer returns a uintptr representation of the IOContext.
|
||||
func (ioctx *IOContext) Pointer() uintptr {
|
||||
return uintptr(ioctx.ioctx)
|
||||
}
|
||||
|
||||
// SetNamespace sets the namespace for objects within this IO context (pool).
|
||||
// Setting namespace to a empty or zero length string sets the pool to the default namespace.
|
||||
func (ioctx *IOContext) SetNamespace(namespace string) {
|
||||
var c_ns *C.char
|
||||
if len(namespace) > 0 {
|
||||
c_ns = C.CString(namespace)
|
||||
defer C.free(unsafe.Pointer(c_ns))
|
||||
}
|
||||
C.rados_ioctx_set_namespace(ioctx.ioctx, c_ns)
|
||||
}
|
||||
|
||||
// Create a new object with key oid.
|
||||
//
|
||||
// Implements:
|
||||
// void rados_write_op_create(rados_write_op_t write_op, int exclusive,
|
||||
// const char* category)
|
||||
func (ioctx *IOContext) Create(oid string, exclusive CreateOption) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
op := C.rados_create_write_op()
|
||||
C.rados_write_op_create(op, C.int(exclusive), nil)
|
||||
ret := C.rados_write_op_operate(op, ioctx.ioctx, c_oid, nil, 0)
|
||||
C.rados_release_write_op(op)
|
||||
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// Write writes len(data) bytes to the object with key oid starting at byte
|
||||
// offset offset. It returns an error, if any.
|
||||
func (ioctx *IOContext) Write(oid string, data []byte, offset uint64) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
dataPointer := unsafe.Pointer(nil)
|
||||
if len(data) > 0 {
|
||||
dataPointer = unsafe.Pointer(&data[0])
|
||||
}
|
||||
|
||||
ret := C.rados_write(ioctx.ioctx, c_oid,
|
||||
(*C.char)(dataPointer),
|
||||
(C.size_t)(len(data)),
|
||||
(C.uint64_t)(offset))
|
||||
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// WriteFull writes len(data) bytes to the object with key oid.
|
||||
// The object is filled with the provided data. If the object exists,
|
||||
// it is atomically truncated and then written. It returns an error, if any.
|
||||
func (ioctx *IOContext) WriteFull(oid string, data []byte) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
ret := C.rados_write_full(ioctx.ioctx, c_oid,
|
||||
(*C.char)(unsafe.Pointer(&data[0])),
|
||||
(C.size_t)(len(data)))
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// Append appends len(data) bytes to the object with key oid.
|
||||
// The object is appended with the provided data. If the object exists,
|
||||
// it is atomically appended to. It returns an error, if any.
|
||||
func (ioctx *IOContext) Append(oid string, data []byte) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
ret := C.rados_append(ioctx.ioctx, c_oid,
|
||||
(*C.char)(unsafe.Pointer(&data[0])),
|
||||
(C.size_t)(len(data)))
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// Read reads up to len(data) bytes from the object with key oid starting at byte
|
||||
// offset offset. It returns the number of bytes read and an error, if any.
|
||||
func (ioctx *IOContext) Read(oid string, data []byte, offset uint64) (int, error) {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
var buf *C.char
|
||||
if len(data) > 0 {
|
||||
buf = (*C.char)(unsafe.Pointer(&data[0]))
|
||||
}
|
||||
|
||||
ret := C.rados_read(
|
||||
ioctx.ioctx,
|
||||
c_oid,
|
||||
buf,
|
||||
(C.size_t)(len(data)),
|
||||
(C.uint64_t)(offset))
|
||||
|
||||
if ret >= 0 {
|
||||
return int(ret), nil
|
||||
}
|
||||
return 0, getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// Delete deletes the object with key oid. It returns an error, if any.
|
||||
func (ioctx *IOContext) Delete(oid string) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
return getRadosError(int(C.rados_remove(ioctx.ioctx, c_oid)))
|
||||
}
|
||||
|
||||
// Truncate resizes the object with key oid to size size. If the operation
|
||||
// enlarges the object, the new area is logically filled with zeroes. If the
|
||||
// operation shrinks the object, the excess data is removed. It returns an
|
||||
// error, if any.
|
||||
func (ioctx *IOContext) Truncate(oid string, size uint64) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
return getRadosError(int(C.rados_trunc(ioctx.ioctx, c_oid, (C.uint64_t)(size))))
|
||||
}
|
||||
|
||||
// Destroy informs librados that the I/O context is no longer in use.
|
||||
// Resources associated with the context may not be freed immediately, and the
|
||||
// context should not be used again after calling this method.
|
||||
func (ioctx *IOContext) Destroy() {
|
||||
C.rados_ioctx_destroy(ioctx.ioctx)
|
||||
}
|
||||
|
||||
// GetPoolStats returns a set of statistics about the pool associated with this I/O
|
||||
// context.
|
||||
//
|
||||
// Implements:
|
||||
// int rados_ioctx_pool_stat(rados_ioctx_t io,
|
||||
// struct rados_pool_stat_t *stats);
|
||||
func (ioctx *IOContext) GetPoolStats() (stat PoolStat, err error) {
|
||||
c_stat := C.struct_rados_pool_stat_t{}
|
||||
ret := C.rados_ioctx_pool_stat(ioctx.ioctx, &c_stat)
|
||||
if ret < 0 {
|
||||
return PoolStat{}, getRadosError(int(ret))
|
||||
}
|
||||
return PoolStat{
|
||||
Num_bytes: uint64(c_stat.num_bytes),
|
||||
Num_kb: uint64(c_stat.num_kb),
|
||||
Num_objects: uint64(c_stat.num_objects),
|
||||
Num_object_clones: uint64(c_stat.num_object_clones),
|
||||
Num_object_copies: uint64(c_stat.num_object_copies),
|
||||
Num_objects_missing_on_primary: uint64(c_stat.num_objects_missing_on_primary),
|
||||
Num_objects_unfound: uint64(c_stat.num_objects_unfound),
|
||||
Num_objects_degraded: uint64(c_stat.num_objects_degraded),
|
||||
Num_rd: uint64(c_stat.num_rd),
|
||||
Num_rd_kb: uint64(c_stat.num_rd_kb),
|
||||
Num_wr: uint64(c_stat.num_wr),
|
||||
Num_wr_kb: uint64(c_stat.num_wr_kb),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetPoolName returns the name of the pool associated with the I/O context.
|
||||
func (ioctx *IOContext) GetPoolName() (name string, err error) {
|
||||
buf := make([]byte, 128)
|
||||
for {
|
||||
ret := C.rados_ioctx_get_pool_name(ioctx.ioctx,
|
||||
(*C.char)(unsafe.Pointer(&buf[0])), C.unsigned(len(buf)))
|
||||
if ret == -C.ERANGE {
|
||||
buf = make([]byte, len(buf)*2)
|
||||
continue
|
||||
} else if ret < 0 {
|
||||
return "", getRadosError(int(ret))
|
||||
}
|
||||
name = C.GoStringN((*C.char)(unsafe.Pointer(&buf[0])), ret)
|
||||
return name, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ObjectListFunc is the type of the function called for each object visited
|
||||
// by ListObjects.
|
||||
type ObjectListFunc func(oid string)
|
||||
|
||||
// ListObjects lists all of the objects in the pool associated with the I/O
|
||||
// context, and called the provided listFn function for each object, passing
|
||||
// to the function the name of the object. Call SetNamespace with
|
||||
// RadosAllNamespaces before calling this function to return objects from all
|
||||
// namespaces
|
||||
func (ioctx *IOContext) ListObjects(listFn ObjectListFunc) error {
|
||||
var ctx C.rados_list_ctx_t
|
||||
ret := C.rados_nobjects_list_open(ioctx.ioctx, &ctx)
|
||||
if ret < 0 {
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
defer func() { C.rados_nobjects_list_close(ctx) }()
|
||||
|
||||
for {
|
||||
var c_entry *C.char
|
||||
ret := C.rados_nobjects_list_next(ctx, &c_entry, nil, nil)
|
||||
if ret == -C.ENOENT {
|
||||
return nil
|
||||
} else if ret < 0 {
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
listFn(C.GoString(c_entry))
|
||||
}
|
||||
}
|
||||
|
||||
// Stat returns the size of the object and its last modification time
|
||||
func (ioctx *IOContext) Stat(object string) (stat ObjectStat, err error) {
|
||||
var c_psize C.uint64_t
|
||||
var c_pmtime C.time_t
|
||||
c_object := C.CString(object)
|
||||
defer C.free(unsafe.Pointer(c_object))
|
||||
|
||||
ret := C.rados_stat(
|
||||
ioctx.ioctx,
|
||||
c_object,
|
||||
&c_psize,
|
||||
&c_pmtime)
|
||||
|
||||
if ret < 0 {
|
||||
return ObjectStat{}, getRadosError(int(ret))
|
||||
}
|
||||
return ObjectStat{
|
||||
Size: uint64(c_psize),
|
||||
ModTime: time.Unix(int64(c_pmtime), 0),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetXattr gets an xattr with key `name`, it returns the length of
|
||||
// the key read or an error if not successful
|
||||
func (ioctx *IOContext) GetXattr(object string, name string, data []byte) (int, error) {
|
||||
c_object := C.CString(object)
|
||||
c_name := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(c_object))
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
|
||||
ret := C.rados_getxattr(
|
||||
ioctx.ioctx,
|
||||
c_object,
|
||||
c_name,
|
||||
(*C.char)(unsafe.Pointer(&data[0])),
|
||||
(C.size_t)(len(data)))
|
||||
|
||||
if ret >= 0 {
|
||||
return int(ret), nil
|
||||
}
|
||||
return 0, getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// SetXattr sets an xattr for an object with key `name` with value as `data`
|
||||
func (ioctx *IOContext) SetXattr(object string, name string, data []byte) error {
|
||||
c_object := C.CString(object)
|
||||
c_name := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(c_object))
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
|
||||
ret := C.rados_setxattr(
|
||||
ioctx.ioctx,
|
||||
c_object,
|
||||
c_name,
|
||||
(*C.char)(unsafe.Pointer(&data[0])),
|
||||
(C.size_t)(len(data)))
|
||||
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// ListXattrs lists all the xattrs for an object. The xattrs are returned as a
|
||||
// mapping of string keys and byte-slice values.
|
||||
func (ioctx *IOContext) ListXattrs(oid string) (map[string][]byte, error) {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
var it C.rados_xattrs_iter_t
|
||||
|
||||
ret := C.rados_getxattrs(ioctx.ioctx, c_oid, &it)
|
||||
if ret < 0 {
|
||||
return nil, getRadosError(int(ret))
|
||||
}
|
||||
defer func() { C.rados_getxattrs_end(it) }()
|
||||
m := make(map[string][]byte)
|
||||
for {
|
||||
var c_name, c_val *C.char
|
||||
var c_len C.size_t
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
defer C.free(unsafe.Pointer(c_val))
|
||||
|
||||
ret := C.rados_getxattrs_next(it, &c_name, &c_val, &c_len)
|
||||
if ret < 0 {
|
||||
return nil, getRadosError(int(ret))
|
||||
}
|
||||
// rados api returns a null name,val & 0-length upon
|
||||
// end of iteration
|
||||
if c_name == nil {
|
||||
return m, nil // stop iteration
|
||||
}
|
||||
m[C.GoString(c_name)] = C.GoBytes(unsafe.Pointer(c_val), (C.int)(c_len))
|
||||
}
|
||||
}
|
||||
|
||||
// RmXattr removes an xattr with key `name` from object `oid`
|
||||
func (ioctx *IOContext) RmXattr(oid string, name string) error {
|
||||
c_oid := C.CString(oid)
|
||||
c_name := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
|
||||
ret := C.rados_rmxattr(
|
||||
ioctx.ioctx,
|
||||
c_oid,
|
||||
c_name)
|
||||
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// LockExclusive takes an exclusive lock on an object.
|
||||
func (ioctx *IOContext) LockExclusive(oid, name, cookie, desc string, duration time.Duration, flags *byte) (int, error) {
|
||||
c_oid := C.CString(oid)
|
||||
c_name := C.CString(name)
|
||||
c_cookie := C.CString(cookie)
|
||||
c_desc := C.CString(desc)
|
||||
|
||||
var c_duration C.struct_timeval
|
||||
if duration != 0 {
|
||||
tv := syscall.NsecToTimeval(duration.Nanoseconds())
|
||||
c_duration = C.struct_timeval{tv_sec: C.ceph_time_t(tv.Sec), tv_usec: C.ceph_suseconds_t(tv.Usec)}
|
||||
}
|
||||
|
||||
var c_flags C.uint8_t
|
||||
if flags != nil {
|
||||
c_flags = C.uint8_t(*flags)
|
||||
}
|
||||
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
defer C.free(unsafe.Pointer(c_cookie))
|
||||
defer C.free(unsafe.Pointer(c_desc))
|
||||
|
||||
ret := C.rados_lock_exclusive(
|
||||
ioctx.ioctx,
|
||||
c_oid,
|
||||
c_name,
|
||||
c_cookie,
|
||||
c_desc,
|
||||
&c_duration,
|
||||
c_flags)
|
||||
|
||||
// 0 on success, negative error code on failure
|
||||
// -EBUSY if the lock is already held by another (client, cookie) pair
|
||||
// -EEXIST if the lock is already held by the same (client, cookie) pair
|
||||
|
||||
switch ret {
|
||||
case 0:
|
||||
return int(ret), nil
|
||||
case -C.EBUSY:
|
||||
return int(ret), nil
|
||||
case -C.EEXIST:
|
||||
return int(ret), nil
|
||||
default:
|
||||
return int(ret), RadosError(int(ret))
|
||||
}
|
||||
}
|
||||
|
||||
// LockShared takes a shared lock on an object.
|
||||
func (ioctx *IOContext) LockShared(oid, name, cookie, tag, desc string, duration time.Duration, flags *byte) (int, error) {
|
||||
c_oid := C.CString(oid)
|
||||
c_name := C.CString(name)
|
||||
c_cookie := C.CString(cookie)
|
||||
c_tag := C.CString(tag)
|
||||
c_desc := C.CString(desc)
|
||||
|
||||
var c_duration C.struct_timeval
|
||||
if duration != 0 {
|
||||
tv := syscall.NsecToTimeval(duration.Nanoseconds())
|
||||
c_duration = C.struct_timeval{tv_sec: C.ceph_time_t(tv.Sec), tv_usec: C.ceph_suseconds_t(tv.Usec)}
|
||||
}
|
||||
|
||||
var c_flags C.uint8_t
|
||||
if flags != nil {
|
||||
c_flags = C.uint8_t(*flags)
|
||||
}
|
||||
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
defer C.free(unsafe.Pointer(c_cookie))
|
||||
defer C.free(unsafe.Pointer(c_tag))
|
||||
defer C.free(unsafe.Pointer(c_desc))
|
||||
|
||||
ret := C.rados_lock_shared(
|
||||
ioctx.ioctx,
|
||||
c_oid,
|
||||
c_name,
|
||||
c_cookie,
|
||||
c_tag,
|
||||
c_desc,
|
||||
&c_duration,
|
||||
c_flags)
|
||||
|
||||
// 0 on success, negative error code on failure
|
||||
// -EBUSY if the lock is already held by another (client, cookie) pair
|
||||
// -EEXIST if the lock is already held by the same (client, cookie) pair
|
||||
|
||||
switch ret {
|
||||
case 0:
|
||||
return int(ret), nil
|
||||
case -C.EBUSY:
|
||||
return int(ret), nil
|
||||
case -C.EEXIST:
|
||||
return int(ret), nil
|
||||
default:
|
||||
return int(ret), RadosError(int(ret))
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock releases a shared or exclusive lock on an object.
|
||||
func (ioctx *IOContext) Unlock(oid, name, cookie string) (int, error) {
|
||||
c_oid := C.CString(oid)
|
||||
c_name := C.CString(name)
|
||||
c_cookie := C.CString(cookie)
|
||||
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
defer C.free(unsafe.Pointer(c_cookie))
|
||||
|
||||
// 0 on success, negative error code on failure
|
||||
// -ENOENT if the lock is not held by the specified (client, cookie) pair
|
||||
|
||||
ret := C.rados_unlock(
|
||||
ioctx.ioctx,
|
||||
c_oid,
|
||||
c_name,
|
||||
c_cookie)
|
||||
|
||||
switch ret {
|
||||
case 0:
|
||||
return int(ret), nil
|
||||
case -C.ENOENT:
|
||||
return int(ret), nil
|
||||
default:
|
||||
return int(ret), RadosError(int(ret))
|
||||
}
|
||||
}
|
||||
|
||||
// ListLockers lists clients that have locked the named object lock and
|
||||
// information about the lock.
|
||||
// The number of bytes required in each buffer is put in the corresponding size
|
||||
// out parameter. If any of the provided buffers are too short, -ERANGE is
|
||||
// returned after these sizes are filled in.
|
||||
func (ioctx *IOContext) ListLockers(oid, name string) (*LockInfo, error) {
|
||||
c_oid := C.CString(oid)
|
||||
c_name := C.CString(name)
|
||||
|
||||
c_tag := (*C.char)(C.malloc(C.size_t(1024)))
|
||||
c_clients := (*C.char)(C.malloc(C.size_t(1024)))
|
||||
c_cookies := (*C.char)(C.malloc(C.size_t(1024)))
|
||||
c_addrs := (*C.char)(C.malloc(C.size_t(1024)))
|
||||
|
||||
var c_exclusive C.int
|
||||
c_tag_len := C.size_t(1024)
|
||||
c_clients_len := C.size_t(1024)
|
||||
c_cookies_len := C.size_t(1024)
|
||||
c_addrs_len := C.size_t(1024)
|
||||
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
defer C.free(unsafe.Pointer(c_tag))
|
||||
defer C.free(unsafe.Pointer(c_clients))
|
||||
defer C.free(unsafe.Pointer(c_cookies))
|
||||
defer C.free(unsafe.Pointer(c_addrs))
|
||||
|
||||
ret := C.rados_list_lockers(
|
||||
ioctx.ioctx,
|
||||
c_oid,
|
||||
c_name,
|
||||
&c_exclusive,
|
||||
c_tag,
|
||||
&c_tag_len,
|
||||
c_clients,
|
||||
&c_clients_len,
|
||||
c_cookies,
|
||||
&c_cookies_len,
|
||||
c_addrs,
|
||||
&c_addrs_len)
|
||||
|
||||
splitCString := func(items *C.char, itemsLen C.size_t) []string {
|
||||
currLen := 0
|
||||
clients := []string{}
|
||||
for currLen < int(itemsLen) {
|
||||
client := C.GoString(C.nextChunk(&items))
|
||||
clients = append(clients, client)
|
||||
currLen += len(client) + 1
|
||||
}
|
||||
return clients
|
||||
}
|
||||
|
||||
if ret < 0 {
|
||||
return nil, RadosError(int(ret))
|
||||
}
|
||||
return &LockInfo{int(ret), c_exclusive == 1, C.GoString(c_tag), splitCString(c_clients, c_clients_len), splitCString(c_cookies, c_cookies_len), splitCString(c_addrs, c_addrs_len)}, nil
|
||||
}
|
||||
|
||||
// BreakLock releases a shared or exclusive lock on an object, which was taken by the specified client.
|
||||
func (ioctx *IOContext) BreakLock(oid, name, client, cookie string) (int, error) {
|
||||
c_oid := C.CString(oid)
|
||||
c_name := C.CString(name)
|
||||
c_client := C.CString(client)
|
||||
c_cookie := C.CString(cookie)
|
||||
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
defer C.free(unsafe.Pointer(c_client))
|
||||
defer C.free(unsafe.Pointer(c_cookie))
|
||||
|
||||
// 0 on success, negative error code on failure
|
||||
// -ENOENT if the lock is not held by the specified (client, cookie) pair
|
||||
// -EINVAL if the client cannot be parsed
|
||||
|
||||
ret := C.rados_break_lock(
|
||||
ioctx.ioctx,
|
||||
c_oid,
|
||||
c_name,
|
||||
c_client,
|
||||
c_cookie)
|
||||
|
||||
switch ret {
|
||||
case 0:
|
||||
return int(ret), nil
|
||||
case -C.ENOENT:
|
||||
return int(ret), nil
|
||||
case -C.EINVAL: // -EINVAL
|
||||
return int(ret), nil
|
||||
default:
|
||||
return int(ret), RadosError(int(ret))
|
||||
}
|
||||
}
|
92
vendor/github.com/ceph/go-ceph/rados/object_iter.go
generated
vendored
Normal file
92
vendor/github.com/ceph/go-ceph/rados/object_iter.go
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
package rados
|
||||
|
||||
// #cgo LDFLAGS: -lrados
|
||||
// #include <rados/librados.h>
|
||||
//
|
||||
import "C"
|
||||
|
||||
// Iter supports iterating over objects in the ioctx.
|
||||
type Iter struct {
|
||||
ctx C.rados_list_ctx_t
|
||||
err error
|
||||
entry string
|
||||
namespace string
|
||||
}
|
||||
|
||||
// IterToken supports reporting on and seeking to different positions.
|
||||
type IterToken uint32
|
||||
|
||||
// Iter returns a Iterator object that can be used to list the object names in the current pool
|
||||
func (ioctx *IOContext) Iter() (*Iter, error) {
|
||||
iter := Iter{}
|
||||
if cerr := C.rados_nobjects_list_open(ioctx.ioctx, &iter.ctx); cerr < 0 {
|
||||
return nil, getRadosError(int(cerr))
|
||||
}
|
||||
return &iter, nil
|
||||
}
|
||||
|
||||
// Token returns a token marking the current position of the iterator. To be used in combination with Iter.Seek()
|
||||
func (iter *Iter) Token() IterToken {
|
||||
return IterToken(C.rados_nobjects_list_get_pg_hash_position(iter.ctx))
|
||||
}
|
||||
|
||||
// Seek moves the iterator to the position indicated by the token.
|
||||
func (iter *Iter) Seek(token IterToken) {
|
||||
C.rados_nobjects_list_seek(iter.ctx, C.uint32_t(token))
|
||||
}
|
||||
|
||||
// Next retrieves the next object name in the pool/namespace iterator.
|
||||
// Upon a successful invocation (return value of true), the Value method should
|
||||
// be used to obtain the name of the retrieved object name. When the iterator is
|
||||
// exhausted, Next returns false. The Err method should used to verify whether the
|
||||
// end of the iterator was reached, or the iterator received an error.
|
||||
//
|
||||
// Example:
|
||||
// iter := pool.Iter()
|
||||
// defer iter.Close()
|
||||
// for iter.Next() {
|
||||
// fmt.Printf("%v\n", iter.Value())
|
||||
// }
|
||||
// return iter.Err()
|
||||
//
|
||||
func (iter *Iter) Next() bool {
|
||||
var c_entry *C.char
|
||||
var c_namespace *C.char
|
||||
if cerr := C.rados_nobjects_list_next(iter.ctx, &c_entry, nil, &c_namespace); cerr < 0 {
|
||||
iter.err = getRadosError(int(cerr))
|
||||
return false
|
||||
}
|
||||
iter.entry = C.GoString(c_entry)
|
||||
iter.namespace = C.GoString(c_namespace)
|
||||
return true
|
||||
}
|
||||
|
||||
// Value returns the current value of the iterator (object name), after a successful call to Next.
|
||||
func (iter *Iter) Value() string {
|
||||
if iter.err != nil {
|
||||
return ""
|
||||
}
|
||||
return iter.entry
|
||||
}
|
||||
|
||||
// Namespace returns the namespace associated with the current value of the iterator (object name), after a successful call to Next.
|
||||
func (iter *Iter) Namespace() string {
|
||||
if iter.err != nil {
|
||||
return ""
|
||||
}
|
||||
return iter.namespace
|
||||
}
|
||||
|
||||
// Err checks whether the iterator has encountered an error.
|
||||
func (iter *Iter) Err() error {
|
||||
if iter.err == ErrNotFound {
|
||||
return nil
|
||||
}
|
||||
return iter.err
|
||||
}
|
||||
|
||||
// Close the iterator cursor on the server. Be aware that iterators are not closed automatically
|
||||
// at the end of iteration.
|
||||
func (iter *Iter) Close() {
|
||||
C.rados_nobjects_list_close(iter.ctx)
|
||||
}
|
228
vendor/github.com/ceph/go-ceph/rados/omap.go
generated
vendored
Normal file
228
vendor/github.com/ceph/go-ceph/rados/omap.go
generated
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
package rados
|
||||
|
||||
// #cgo LDFLAGS: -lrados
|
||||
// #include <stdlib.h>
|
||||
// #include <rados/librados.h>
|
||||
//
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// SetOmap appends the map `pairs` to the omap `oid`
|
||||
func (ioctx *IOContext) SetOmap(oid string, pairs map[string][]byte) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
var s C.size_t
|
||||
var c *C.char
|
||||
ptrSize := unsafe.Sizeof(c)
|
||||
|
||||
c_keys := C.malloc(C.size_t(len(pairs)) * C.size_t(ptrSize))
|
||||
c_values := C.malloc(C.size_t(len(pairs)) * C.size_t(ptrSize))
|
||||
c_lengths := C.malloc(C.size_t(len(pairs)) * C.size_t(unsafe.Sizeof(s)))
|
||||
|
||||
defer C.free(unsafe.Pointer(c_keys))
|
||||
defer C.free(unsafe.Pointer(c_values))
|
||||
defer C.free(unsafe.Pointer(c_lengths))
|
||||
|
||||
i := 0
|
||||
for key, value := range pairs {
|
||||
// key
|
||||
c_key_ptr := (**C.char)(unsafe.Pointer(uintptr(c_keys) + uintptr(i)*ptrSize))
|
||||
*c_key_ptr = C.CString(key)
|
||||
defer C.free(unsafe.Pointer(*c_key_ptr))
|
||||
|
||||
// value and its length
|
||||
c_value_ptr := (**C.char)(unsafe.Pointer(uintptr(c_values) + uintptr(i)*ptrSize))
|
||||
|
||||
var c_length C.size_t
|
||||
if len(value) > 0 {
|
||||
*c_value_ptr = (*C.char)(unsafe.Pointer(&value[0]))
|
||||
c_length = C.size_t(len(value))
|
||||
} else {
|
||||
*c_value_ptr = nil
|
||||
c_length = C.size_t(0)
|
||||
}
|
||||
|
||||
c_length_ptr := (*C.size_t)(unsafe.Pointer(uintptr(c_lengths) + uintptr(i)*ptrSize))
|
||||
*c_length_ptr = c_length
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
op := C.rados_create_write_op()
|
||||
C.rados_write_op_omap_set(
|
||||
op,
|
||||
(**C.char)(c_keys),
|
||||
(**C.char)(c_values),
|
||||
(*C.size_t)(c_lengths),
|
||||
C.size_t(len(pairs)))
|
||||
|
||||
ret := C.rados_write_op_operate(op, ioctx.ioctx, c_oid, nil, 0)
|
||||
C.rados_release_write_op(op)
|
||||
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// OmapListFunc is the type of the function called for each omap key
|
||||
// visited by ListOmapValues
|
||||
type OmapListFunc func(key string, value []byte)
|
||||
|
||||
// ListOmapValues iterates over the keys and values in an omap by way of
|
||||
// a callback function.
|
||||
//
|
||||
// `startAfter`: iterate only on the keys after this specified one
|
||||
// `filterPrefix`: iterate only on the keys beginning with this prefix
|
||||
// `maxReturn`: iterate no more than `maxReturn` key/value pairs
|
||||
// `listFn`: the function called at each iteration
|
||||
func (ioctx *IOContext) ListOmapValues(oid string, startAfter string, filterPrefix string, maxReturn int64, listFn OmapListFunc) error {
|
||||
c_oid := C.CString(oid)
|
||||
c_start_after := C.CString(startAfter)
|
||||
c_filter_prefix := C.CString(filterPrefix)
|
||||
c_max_return := C.uint64_t(maxReturn)
|
||||
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
defer C.free(unsafe.Pointer(c_start_after))
|
||||
defer C.free(unsafe.Pointer(c_filter_prefix))
|
||||
|
||||
op := C.rados_create_read_op()
|
||||
|
||||
var c_iter C.rados_omap_iter_t
|
||||
var c_prval C.int
|
||||
C.rados_read_op_omap_get_vals2(
|
||||
op,
|
||||
c_start_after,
|
||||
c_filter_prefix,
|
||||
c_max_return,
|
||||
&c_iter,
|
||||
nil,
|
||||
&c_prval,
|
||||
)
|
||||
|
||||
ret := C.rados_read_op_operate(op, ioctx.ioctx, c_oid, 0)
|
||||
|
||||
if int(ret) != 0 {
|
||||
return getRadosError(int(ret))
|
||||
} else if int(c_prval) != 0 {
|
||||
return RadosError(int(c_prval))
|
||||
}
|
||||
|
||||
for {
|
||||
var c_key *C.char
|
||||
var c_val *C.char
|
||||
var c_len C.size_t
|
||||
|
||||
ret = C.rados_omap_get_next(c_iter, &c_key, &c_val, &c_len)
|
||||
|
||||
if int(ret) != 0 {
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
if c_key == nil {
|
||||
break
|
||||
}
|
||||
|
||||
listFn(C.GoString(c_key), C.GoBytes(unsafe.Pointer(c_val), C.int(c_len)))
|
||||
}
|
||||
|
||||
C.rados_omap_get_end(c_iter)
|
||||
C.rados_release_read_op(op)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOmapValues fetches a set of keys and their values from an omap and returns then as a map
|
||||
// `startAfter`: retrieve only the keys after this specified one
|
||||
// `filterPrefix`: retrieve only the keys beginning with this prefix
|
||||
// `maxReturn`: retrieve no more than `maxReturn` key/value pairs
|
||||
func (ioctx *IOContext) GetOmapValues(oid string, startAfter string, filterPrefix string, maxReturn int64) (map[string][]byte, error) {
|
||||
omap := map[string][]byte{}
|
||||
|
||||
err := ioctx.ListOmapValues(
|
||||
oid, startAfter, filterPrefix, maxReturn,
|
||||
func(key string, value []byte) {
|
||||
omap[key] = value
|
||||
},
|
||||
)
|
||||
|
||||
return omap, err
|
||||
}
|
||||
|
||||
// GetAllOmapValues fetches all the keys and their values from an omap and returns then as a map
|
||||
// `startAfter`: retrieve only the keys after this specified one
|
||||
// `filterPrefix`: retrieve only the keys beginning with this prefix
|
||||
// `iteratorSize`: internal number of keys to fetch during a read operation
|
||||
func (ioctx *IOContext) GetAllOmapValues(oid string, startAfter string, filterPrefix string, iteratorSize int64) (map[string][]byte, error) {
|
||||
omap := map[string][]byte{}
|
||||
omapSize := 0
|
||||
|
||||
for {
|
||||
err := ioctx.ListOmapValues(
|
||||
oid, startAfter, filterPrefix, iteratorSize,
|
||||
func(key string, value []byte) {
|
||||
omap[key] = value
|
||||
startAfter = key
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return omap, err
|
||||
}
|
||||
|
||||
// End of omap
|
||||
if len(omap) == omapSize {
|
||||
break
|
||||
}
|
||||
|
||||
omapSize = len(omap)
|
||||
}
|
||||
|
||||
return omap, nil
|
||||
}
|
||||
|
||||
// RmOmapKeys removes the specified `keys` from the omap `oid`
|
||||
func (ioctx *IOContext) RmOmapKeys(oid string, keys []string) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
var c *C.char
|
||||
ptrSize := unsafe.Sizeof(c)
|
||||
|
||||
c_keys := C.malloc(C.size_t(len(keys)) * C.size_t(ptrSize))
|
||||
defer C.free(unsafe.Pointer(c_keys))
|
||||
|
||||
i := 0
|
||||
for _, key := range keys {
|
||||
c_key_ptr := (**C.char)(unsafe.Pointer(uintptr(c_keys) + uintptr(i)*ptrSize))
|
||||
*c_key_ptr = C.CString(key)
|
||||
defer C.free(unsafe.Pointer(*c_key_ptr))
|
||||
i++
|
||||
}
|
||||
|
||||
op := C.rados_create_write_op()
|
||||
C.rados_write_op_omap_rm_keys(
|
||||
op,
|
||||
(**C.char)(c_keys),
|
||||
C.size_t(len(keys)))
|
||||
|
||||
ret := C.rados_write_op_operate(op, ioctx.ioctx, c_oid, nil, 0)
|
||||
C.rados_release_write_op(op)
|
||||
|
||||
return getRadosError(int(ret))
|
||||
}
|
||||
|
||||
// CleanOmap clears the omap `oid`
|
||||
func (ioctx *IOContext) CleanOmap(oid string) error {
|
||||
c_oid := C.CString(oid)
|
||||
defer C.free(unsafe.Pointer(c_oid))
|
||||
|
||||
op := C.rados_create_write_op()
|
||||
C.rados_write_op_omap_clear(op)
|
||||
|
||||
ret := C.rados_write_op_operate(op, ioctx.ioctx, c_oid, nil, 0)
|
||||
C.rados_release_write_op(op)
|
||||
|
||||
return getRadosError(int(ret))
|
||||
}
|
137
vendor/github.com/ceph/go-ceph/rados/rados.go
generated
vendored
Normal file
137
vendor/github.com/ceph/go-ceph/rados/rados.go
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
package rados
|
||||
|
||||
// #cgo LDFLAGS: -lrados
|
||||
// #include <errno.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <rados/librados.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ceph/go-ceph/errutil"
|
||||
)
|
||||
|
||||
// RadosError represents an error condition returned from the Ceph RADOS APIs.
|
||||
type RadosError int
|
||||
|
||||
// Error returns the error string for the RadosError type.
|
||||
func (e RadosError) Error() string {
|
||||
errno, s := errutil.FormatErrno(int(e))
|
||||
if s == "" {
|
||||
return fmt.Sprintf("rados: ret=%d", errno)
|
||||
}
|
||||
return fmt.Sprintf("rados: ret=%d, %s", errno, s)
|
||||
}
|
||||
|
||||
const (
|
||||
// AllNamespaces is used to reset a selected namespace to all
|
||||
// namespaces. See the IOContext SetNamespace function.
|
||||
AllNamespaces = C.LIBRADOS_ALL_NSPACES
|
||||
|
||||
// ErrNotFound indicates a missing resource.
|
||||
ErrNotFound = RadosError(-C.ENOENT)
|
||||
// ErrPermissionDenied indicates a permissions issue.
|
||||
ErrPermissionDenied = RadosError(-C.EPERM)
|
||||
// ErrObjectExists indicates that an exclusive object creation failed.
|
||||
ErrObjectExists = RadosError(-C.EEXIST)
|
||||
|
||||
// FIXME: for backwards compatibility
|
||||
|
||||
// RadosAllNamespaces is used to reset a selected namespace to all
|
||||
// namespaces. See the IOContext SetNamespace function.
|
||||
//
|
||||
// Deprecated: use AllNamespaces instead
|
||||
RadosAllNamespaces = AllNamespaces
|
||||
// RadosErrorNotFound indicates a missing resource.
|
||||
//
|
||||
// Deprecated: use ErrNotFound instead
|
||||
RadosErrorNotFound = ErrNotFound
|
||||
// RadosErrorPermissionDenied indicates a permissions issue.
|
||||
//
|
||||
// Deprecated: use ErrPermissionDenied instead
|
||||
RadosErrorPermissionDenied = ErrPermissionDenied
|
||||
)
|
||||
|
||||
func getRadosError(err int) error {
|
||||
if err == 0 {
|
||||
return nil
|
||||
}
|
||||
return RadosError(err)
|
||||
}
|
||||
|
||||
// Version returns the major, minor, and patch components of the version of
|
||||
// the RADOS library linked against.
|
||||
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 makeConn() *Conn {
|
||||
return &Conn{connected: false}
|
||||
}
|
||||
|
||||
func newConn(user *C.char) (*Conn, error) {
|
||||
conn := makeConn()
|
||||
ret := C.rados_create(&conn.cluster, user)
|
||||
|
||||
if ret != 0 {
|
||||
return nil, RadosError(int(ret))
|
||||
}
|
||||
|
||||
runtime.SetFinalizer(conn, freeConn)
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// NewConn creates a new connection object. It returns the connection and an
|
||||
// error, if any.
|
||||
func NewConn() (*Conn, error) {
|
||||
return newConn(nil)
|
||||
}
|
||||
|
||||
// NewConnWithUser creates a new connection object with a custom username.
|
||||
// It returns the connection and an error, if any.
|
||||
func NewConnWithUser(user string) (*Conn, error) {
|
||||
c_user := C.CString(user)
|
||||
defer C.free(unsafe.Pointer(c_user))
|
||||
return newConn(c_user)
|
||||
}
|
||||
|
||||
// NewConnWithClusterAndUser creates a new connection object for a specific cluster and username.
|
||||
// It returns the connection and an error, if any.
|
||||
func NewConnWithClusterAndUser(clusterName string, userName string) (*Conn, error) {
|
||||
c_cluster_name := C.CString(clusterName)
|
||||
defer C.free(unsafe.Pointer(c_cluster_name))
|
||||
|
||||
c_name := C.CString(userName)
|
||||
defer C.free(unsafe.Pointer(c_name))
|
||||
|
||||
conn := makeConn()
|
||||
ret := C.rados_create2(&conn.cluster, c_cluster_name, c_name, 0)
|
||||
if ret != 0 {
|
||||
return nil, RadosError(int(ret))
|
||||
}
|
||||
|
||||
runtime.SetFinalizer(conn, freeConn)
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// freeConn releases resources that are allocated while configuring the
|
||||
// connection to the cluster. rados_shutdown() should only be needed after a
|
||||
// successful call to rados_connect(), however if the connection has been
|
||||
// configured with non-default parameters, some of the parameters may be
|
||||
// allocated before connecting. rados_shutdown() will free the allocated
|
||||
// resources, even if there has not been a connection yet.
|
||||
//
|
||||
// This function is setup as a destructor/finalizer when rados_create() is
|
||||
// called.
|
||||
func freeConn(conn *Conn) {
|
||||
if conn.cluster != nil {
|
||||
C.rados_shutdown(conn.cluster)
|
||||
// prevent calling rados_shutdown() more than once
|
||||
conn.cluster = nil
|
||||
}
|
||||
}
|
4
vendor/github.com/ceph/go-ceph/rbd/doc.go
generated
vendored
Normal file
4
vendor/github.com/ceph/go-ceph/rbd/doc.go
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/*
|
||||
Package rbd contains a set of wrappers around Ceph's librbd API.
|
||||
*/
|
||||
package rbd
|
169
vendor/github.com/ceph/go-ceph/rbd/options.go
generated
vendored
Normal file
169
vendor/github.com/ceph/go-ceph/rbd/options.go
generated
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
package rbd
|
||||
|
||||
// #cgo LDFLAGS: -lrbd
|
||||
// #include <stdlib.h>
|
||||
// #include <rbd/librbd.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// RBD image options.
|
||||
RbdImageOptionFormat = C.RBD_IMAGE_OPTION_FORMAT
|
||||
RbdImageOptionFeatures = C.RBD_IMAGE_OPTION_FEATURES
|
||||
RbdImageOptionOrder = C.RBD_IMAGE_OPTION_ORDER
|
||||
RbdImageOptionStripeUnit = C.RBD_IMAGE_OPTION_STRIPE_UNIT
|
||||
RbdImageOptionStripeCount = C.RBD_IMAGE_OPTION_STRIPE_COUNT
|
||||
RbdImageOptionJournalOrder = C.RBD_IMAGE_OPTION_JOURNAL_ORDER
|
||||
RbdImageOptionJournalSplayWidth = C.RBD_IMAGE_OPTION_JOURNAL_SPLAY_WIDTH
|
||||
RbdImageOptionJournalPool = C.RBD_IMAGE_OPTION_JOURNAL_POOL
|
||||
RbdImageOptionFeaturesSet = C.RBD_IMAGE_OPTION_FEATURES_SET
|
||||
RbdImageOptionFeaturesClear = C.RBD_IMAGE_OPTION_FEATURES_CLEAR
|
||||
RbdImageOptionDataPool = C.RBD_IMAGE_OPTION_DATA_POOL
|
||||
// introduced with Ceph Mimic
|
||||
//RbdImageOptionFlatten = C.RBD_IMAGE_OPTION_FLATTEN
|
||||
)
|
||||
|
||||
type RbdImageOptions struct {
|
||||
options C.rbd_image_options_t
|
||||
}
|
||||
|
||||
type RbdImageOption C.int
|
||||
|
||||
// NewRbdImageOptions creates a new RbdImageOptions struct. Call
|
||||
// RbdImageOptions.Destroy() to free the resources.
|
||||
//
|
||||
// Implements:
|
||||
// void rbd_image_options_create(rbd_image_options_t* opts)
|
||||
func NewRbdImageOptions() *RbdImageOptions {
|
||||
rio := &RbdImageOptions{}
|
||||
C.rbd_image_options_create(&rio.options)
|
||||
return rio
|
||||
}
|
||||
|
||||
// Destroy a RbdImageOptions struct and free the associated resources.
|
||||
//
|
||||
// Implements:
|
||||
// void rbd_image_options_destroy(rbd_image_options_t opts);
|
||||
func (rio *RbdImageOptions) Destroy() {
|
||||
C.rbd_image_options_destroy(rio.options)
|
||||
}
|
||||
|
||||
// SetString sets the value of the RbdImageOption to the given string.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_image_options_set_string(rbd_image_options_t opts, int optname,
|
||||
// const char* optval);
|
||||
func (rio *RbdImageOptions) SetString(option RbdImageOption, value string) error {
|
||||
c_value := C.CString(value)
|
||||
defer C.free(unsafe.Pointer(c_value))
|
||||
|
||||
ret := C.rbd_image_options_set_string(rio.options, C.int(option), c_value)
|
||||
if ret != 0 {
|
||||
return fmt.Errorf("%v, could not set option %v to \"%v\"",
|
||||
getError(ret), option, value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetString returns the string value of the RbdImageOption.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_image_options_get_string(rbd_image_options_t opts, int optname,
|
||||
// char* optval, size_t maxlen);
|
||||
func (rio *RbdImageOptions) GetString(option RbdImageOption) (string, error) {
|
||||
value := make([]byte, 4096)
|
||||
|
||||
ret := C.rbd_image_options_get_string(rio.options, C.int(option),
|
||||
(*C.char)(unsafe.Pointer(&value[0])),
|
||||
C.size_t(len(value)))
|
||||
if ret != 0 {
|
||||
return "", fmt.Errorf("%v, could not get option %v", getError(ret), option)
|
||||
}
|
||||
|
||||
return C.GoString((*C.char)(unsafe.Pointer(&value[0]))), nil
|
||||
}
|
||||
|
||||
// SetUint64 sets the value of the RbdImageOption to the given uint64.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_image_options_set_uint64(rbd_image_options_t opts, int optname,
|
||||
// const uint64_t optval);
|
||||
func (rio *RbdImageOptions) SetUint64(option RbdImageOption, value uint64) error {
|
||||
c_value := C.uint64_t(value)
|
||||
|
||||
ret := C.rbd_image_options_set_uint64(rio.options, C.int(option), c_value)
|
||||
if ret != 0 {
|
||||
return fmt.Errorf("%v, could not set option %v to \"%v\"",
|
||||
getError(ret), option, value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUint64 returns the uint64 value of the RbdImageOption.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_image_options_get_uint64(rbd_image_options_t opts, int optname,
|
||||
// uint64_t* optval);
|
||||
func (rio *RbdImageOptions) GetUint64(option RbdImageOption) (uint64, error) {
|
||||
var c_value C.uint64_t
|
||||
|
||||
ret := C.rbd_image_options_get_uint64(rio.options, C.int(option), &c_value)
|
||||
if ret != 0 {
|
||||
return 0, fmt.Errorf("%v, could not get option %v", getError(ret), option)
|
||||
}
|
||||
|
||||
return uint64(c_value), nil
|
||||
}
|
||||
|
||||
// IsSet returns a true if the RbdImageOption is set, false otherwise.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_image_options_is_set(rbd_image_options_t opts, int optname,
|
||||
// bool* is_set);
|
||||
func (rio *RbdImageOptions) IsSet(option RbdImageOption) (bool, error) {
|
||||
var c_set C.bool
|
||||
|
||||
ret := C.rbd_image_options_is_set(rio.options, C.int(option), &c_set)
|
||||
if ret != 0 {
|
||||
return false, fmt.Errorf("%v, could not check option %v", getError(ret), option)
|
||||
}
|
||||
|
||||
return bool(c_set), nil
|
||||
}
|
||||
|
||||
// Unset a given RbdImageOption.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_image_options_unset(rbd_image_options_t opts, int optname)
|
||||
func (rio *RbdImageOptions) Unset(option RbdImageOption) error {
|
||||
ret := C.rbd_image_options_unset(rio.options, C.int(option))
|
||||
if ret != 0 {
|
||||
return fmt.Errorf("%v, could not unset option %v", getError(ret), option)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clear all options in the RbdImageOptions.
|
||||
//
|
||||
// Implements:
|
||||
// void rbd_image_options_clear(rbd_image_options_t opts)
|
||||
func (rio *RbdImageOptions) Clear() {
|
||||
C.rbd_image_options_clear(rio.options)
|
||||
}
|
||||
|
||||
// IsEmpty returns true if there are no options set in the RbdImageOptions,
|
||||
// false otherwise.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_image_options_is_empty(rbd_image_options_t opts)
|
||||
func (rio *RbdImageOptions) IsEmpty() bool {
|
||||
ret := C.rbd_image_options_is_empty(rio.options)
|
||||
return ret != 0
|
||||
}
|
1403
vendor/github.com/ceph/go-ceph/rbd/rbd.go
generated
vendored
Normal file
1403
vendor/github.com/ceph/go-ceph/rbd/rbd.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
43
vendor/github.com/ceph/go-ceph/rbd/rbd_mimic.go
generated
vendored
Normal file
43
vendor/github.com/ceph/go-ceph/rbd/rbd_mimic.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// +build luminous mimic
|
||||
// +build !nautilus
|
||||
//
|
||||
// Ceph Nautilus includes rbd_list2() and marked rbd_list() deprecated.
|
||||
|
||||
package rbd
|
||||
|
||||
// #cgo LDFLAGS: -lrbd
|
||||
// #include <rados/librados.h>
|
||||
// #include <rbd/librbd.h>
|
||||
// #include <errno.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ceph/go-ceph/rados"
|
||||
)
|
||||
|
||||
// GetImageNames returns the list of current RBD images.
|
||||
func GetImageNames(ioctx *rados.IOContext) (names []string, err error) {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
size := C.size_t(len(buf))
|
||||
ret := C.rbd_list(C.rados_ioctx_t(ioctx.Pointer()),
|
||||
(*C.char)(unsafe.Pointer(&buf[0])), &size)
|
||||
if ret == -C.ERANGE {
|
||||
buf = make([]byte, size)
|
||||
continue
|
||||
} else if ret < 0 {
|
||||
return nil, RBDError(ret)
|
||||
}
|
||||
tmp := bytes.Split(buf[:size-1], []byte{0})
|
||||
for _, s := range tmp {
|
||||
if len(s) > 0 {
|
||||
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
|
||||
names = append(names, name)
|
||||
}
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
}
|
45
vendor/github.com/ceph/go-ceph/rbd/rbd_nautilus.go
generated
vendored
Normal file
45
vendor/github.com/ceph/go-ceph/rbd/rbd_nautilus.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
// +build !luminous,!mimic
|
||||
//
|
||||
// Ceph Nautilus is the first release that includes rbd_list2().
|
||||
|
||||
package rbd
|
||||
|
||||
// #cgo LDFLAGS: -lrbd
|
||||
// #include <rados/librados.h>
|
||||
// #include <rbd/librbd.h>
|
||||
// #include <errno.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ceph/go-ceph/rados"
|
||||
)
|
||||
|
||||
// GetImageNames returns the list of current RBD images.
|
||||
func GetImageNames(ioctx *rados.IOContext) ([]string, error) {
|
||||
size := C.size_t(0)
|
||||
ret := C.rbd_list2(C.rados_ioctx_t(ioctx.Pointer()), nil, &size)
|
||||
if ret < 0 && ret != -C.ERANGE {
|
||||
return nil, RBDError(ret)
|
||||
} else if ret > 0 {
|
||||
return nil, fmt.Errorf("rbd_list2() returned %d names, expected 0", ret)
|
||||
} else if ret == 0 && size == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// expected: ret == -ERANGE, size contains number of image names
|
||||
images := make([]C.rbd_image_spec_t, size)
|
||||
ret = C.rbd_list2(C.rados_ioctx_t(ioctx.Pointer()), (*C.rbd_image_spec_t)(unsafe.Pointer(&images[0])), &size)
|
||||
if ret < 0 {
|
||||
return nil, RBDError(ret)
|
||||
}
|
||||
defer C.rbd_image_spec_list_cleanup((*C.rbd_image_spec_t)(unsafe.Pointer(&images[0])), size)
|
||||
|
||||
names := make([]string, size)
|
||||
for i, image := range images {
|
||||
names[i] = C.GoString(image.name)
|
||||
}
|
||||
return names, nil
|
||||
}
|
101
vendor/github.com/ceph/go-ceph/rbd/snapshot_mimic.go
generated
vendored
Normal file
101
vendor/github.com/ceph/go-ceph/rbd/snapshot_mimic.go
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
// +build luminous mimic
|
||||
// +build !nautilus
|
||||
//
|
||||
// Ceph Nautilus introduced rbd_get_parent() and deprecated rbd_get_parent_info().
|
||||
// Ceph Nautilus introduced rbd_list_children3() and deprecated rbd_list_children().
|
||||
|
||||
package rbd
|
||||
|
||||
// #cgo LDFLAGS: -lrbd
|
||||
// #include <rbd/librbd.h>
|
||||
// #include <errno.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// GetParentInfo looks for the parent of the image and stores the pool, name
|
||||
// and snapshot-name in the byte-arrays that are passed as arguments.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_get_parent_info(rbd_image_t image, char *parent_pool_name,
|
||||
// size_t ppool_namelen, char *parent_name,
|
||||
// size_t pnamelen, char *parent_snap_name,
|
||||
// size_t psnap_namelen)
|
||||
func (image *Image) GetParentInfo(p_pool, p_name, p_snapname []byte) error {
|
||||
if err := image.validate(imageIsOpen); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ret := C.rbd_get_parent_info(
|
||||
image.image,
|
||||
(*C.char)(unsafe.Pointer(&p_pool[0])),
|
||||
(C.size_t)(len(p_pool)),
|
||||
(*C.char)(unsafe.Pointer(&p_name[0])),
|
||||
(C.size_t)(len(p_name)),
|
||||
(*C.char)(unsafe.Pointer(&p_snapname[0])),
|
||||
(C.size_t)(len(p_snapname)))
|
||||
if ret == 0 {
|
||||
return nil
|
||||
} else {
|
||||
return RBDError(ret)
|
||||
}
|
||||
}
|
||||
|
||||
// ListChildren returns arrays with the pools and names of the images that are
|
||||
// children of the given image. The index of the pools and images arrays can be
|
||||
// used to link the two items together.
|
||||
//
|
||||
// Implements:
|
||||
// ssize_t rbd_list_children(rbd_image_t image, char *pools,
|
||||
// size_t *pools_len,
|
||||
// char *images, size_t *images_len);
|
||||
func (image *Image) ListChildren() (pools []string, images []string, err error) {
|
||||
if err := image.validate(imageIsOpen); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var c_pools_len, c_images_len C.size_t
|
||||
|
||||
ret := C.rbd_list_children(image.image,
|
||||
nil, &c_pools_len,
|
||||
nil, &c_images_len)
|
||||
if ret == 0 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
if ret < 0 && ret != -C.ERANGE {
|
||||
return nil, nil, RBDError(ret)
|
||||
}
|
||||
|
||||
pools_buf := make([]byte, c_pools_len)
|
||||
images_buf := make([]byte, c_images_len)
|
||||
|
||||
ret = C.rbd_list_children(image.image,
|
||||
(*C.char)(unsafe.Pointer(&pools_buf[0])),
|
||||
&c_pools_len,
|
||||
(*C.char)(unsafe.Pointer(&images_buf[0])),
|
||||
&c_images_len)
|
||||
if ret < 0 {
|
||||
return nil, nil, RBDError(ret)
|
||||
}
|
||||
|
||||
tmp := bytes.Split(pools_buf[:c_pools_len-1], []byte{0})
|
||||
for _, s := range tmp {
|
||||
if len(s) > 0 {
|
||||
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
|
||||
pools = append(pools, name)
|
||||
}
|
||||
}
|
||||
|
||||
tmp = bytes.Split(images_buf[:c_images_len-1], []byte{0})
|
||||
for _, s := range tmp {
|
||||
if len(s) > 0 {
|
||||
name := C.GoString((*C.char)(unsafe.Pointer(&s[0])))
|
||||
images = append(images, name)
|
||||
}
|
||||
}
|
||||
|
||||
return pools, images, nil
|
||||
}
|
104
vendor/github.com/ceph/go-ceph/rbd/snapshot_nautilus.go
generated
vendored
Normal file
104
vendor/github.com/ceph/go-ceph/rbd/snapshot_nautilus.go
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
// +build !luminous,!mimic
|
||||
//
|
||||
// Ceph Nautilus introduced rbd_get_parent() and deprecated rbd_get_parent_info().
|
||||
// Ceph Nautilus introduced rbd_list_children3() and deprecated rbd_list_children().
|
||||
|
||||
package rbd
|
||||
|
||||
// #cgo LDFLAGS: -lrbd
|
||||
// #include <rbd/librbd.h>
|
||||
// #include <errno.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// GetParentInfo looks for the parent of the image and stores the pool, name
|
||||
// and snapshot-name in the byte-arrays that are passed as arguments.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_get_parent(rbd_image_t image,
|
||||
// rbd_linked_image_spec_t *parent_image,
|
||||
// rbd_snap_spec_t *parent_snap)
|
||||
func (image *Image) GetParentInfo(pool, name, snapname []byte) error {
|
||||
if err := image.validate(imageIsOpen); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parentImage := C.rbd_linked_image_spec_t{}
|
||||
parentSnap := C.rbd_snap_spec_t{}
|
||||
ret := C.rbd_get_parent(image.image, &parentImage, &parentSnap)
|
||||
if ret != 0 {
|
||||
return RBDError(ret)
|
||||
}
|
||||
|
||||
defer C.rbd_linked_image_spec_cleanup(&parentImage)
|
||||
defer C.rbd_snap_spec_cleanup(&parentSnap)
|
||||
|
||||
strlen := int(C.strlen(parentImage.pool_name))
|
||||
if len(pool) < strlen {
|
||||
return RBDError(C.ERANGE)
|
||||
}
|
||||
if copy(pool, C.GoString(parentImage.pool_name)) != strlen {
|
||||
return RBDError(C.ERANGE)
|
||||
}
|
||||
|
||||
strlen = int(C.strlen(parentImage.image_name))
|
||||
if len(name) < strlen {
|
||||
return RBDError(C.ERANGE)
|
||||
}
|
||||
if copy(name, C.GoString(parentImage.image_name)) != strlen {
|
||||
return RBDError(C.ERANGE)
|
||||
}
|
||||
|
||||
strlen = int(C.strlen(parentSnap.name))
|
||||
if len(snapname) < strlen {
|
||||
return RBDError(C.ERANGE)
|
||||
}
|
||||
if copy(snapname, C.GoString(parentSnap.name)) != strlen {
|
||||
return RBDError(C.ERANGE)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListChildren returns arrays with the pools and names of the images that are
|
||||
// children of the given image. The index of the pools and images arrays can be
|
||||
// used to link the two items together.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_list_children3(rbd_image_t image, rbd_linked_image_spec_t *images,
|
||||
// size_t *max_images);
|
||||
func (image *Image) ListChildren() (pools []string, images []string, err error) {
|
||||
if err := image.validate(imageIsOpen); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
size := C.size_t(0)
|
||||
ret := C.rbd_list_children3(image.image, nil, &size)
|
||||
if ret < 0 && ret != -C.ERANGE {
|
||||
return nil, nil, RBDError(ret)
|
||||
} else if ret > 0 {
|
||||
return nil, nil, fmt.Errorf("rbd_list_children3() returned %d, expected 0", ret)
|
||||
} else if ret == 0 && size == 0 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
// expected: ret == -ERANGE, size contains number of image names
|
||||
children := make([]C.rbd_linked_image_spec_t, size)
|
||||
ret = C.rbd_list_children3(image.image, (*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])), &size)
|
||||
if ret < 0 {
|
||||
return nil, nil, RBDError(ret)
|
||||
}
|
||||
defer C.rbd_linked_image_spec_list_cleanup((*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])), size)
|
||||
|
||||
pools = make([]string, size)
|
||||
images = make([]string, size)
|
||||
for i, child := range children {
|
||||
pools[i] = C.GoString(child.pool_name)
|
||||
images[i] = C.GoString(child.image_name)
|
||||
}
|
||||
return pools, images, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user