mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-22 22:30:23 +00:00
rebase: update go-ceph to v0.8.0
Updating go-ceph to v0.8.0. Signed-off-by: Mudit Agarwal <muagarwa@redhat.com>
This commit is contained in:
parent
e6098520d1
commit
32d78c4f7f
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module github.com/ceph/ceph-csi
|
|||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ceph/go-ceph v0.7.0
|
github.com/ceph/go-ceph v0.8.0
|
||||||
github.com/container-storage-interface/spec v1.3.0
|
github.com/container-storage-interface/spec v1.3.0
|
||||||
github.com/go-logr/logr v0.2.1 // indirect
|
github.com/go-logr/logr v0.2.1 // indirect
|
||||||
github.com/golang/protobuf v1.4.3
|
github.com/golang/protobuf v1.4.3
|
||||||
|
4
go.sum
4
go.sum
@ -203,8 +203,8 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
|
|||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU=
|
github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f h1:gJzxrodnNd/CtPXjO3WYiakyNzHg3rtAi7rO74ejHYU=
|
||||||
github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f/go.mod h1:C0rtzmGXgN78pYR0tGJFhtHgkbAs0lIbHwkB81VxDQE=
|
github.com/centrify/cloud-golang-sdk v0.0.0-20190214225812-119110094d0f/go.mod h1:C0rtzmGXgN78pYR0tGJFhtHgkbAs0lIbHwkB81VxDQE=
|
||||||
github.com/ceph/go-ceph v0.7.0 h1:+4oWZCuvh9B7/kZVJVw/DSuk9Qby38KWY1pMQ5gYGyY=
|
github.com/ceph/go-ceph v0.8.0 h1:d+VP0eyconBl9RrvKVUq7S0npyK969ErLkCt5pg2fp0=
|
||||||
github.com/ceph/go-ceph v0.7.0/go.mod h1:wd+keAOqrcsN//20VQnHBGtnBnY0KHl0PA024Ng8HfQ=
|
github.com/ceph/go-ceph v0.8.0/go.mod h1:wd+keAOqrcsN//20VQnHBGtnBnY0KHl0PA024Ng8HfQ=
|
||||||
github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY=
|
github.com/cespare/prettybench v0.0.0-20150116022406-03b8cfe5406c/go.mod h1:Xe6ZsFhtM8HrDku0pxJ3/Lr51rwykrzgFwpmTzleatY=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
2
vendor/github.com/ceph/go-ceph/cephfs/admin/flags.go
generated
vendored
2
vendor/github.com/ceph/go-ceph/cephfs/admin/flags.go
generated
vendored
@ -41,7 +41,7 @@ func (f SubVolRmFlags) flags() map[string]bool {
|
|||||||
o["force"] = true
|
o["force"] = true
|
||||||
}
|
}
|
||||||
if f.RetainSnapshots {
|
if f.RetainSnapshots {
|
||||||
o["retain-snapshots"] = true
|
o["retain_snapshots"] = true
|
||||||
}
|
}
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
25
vendor/github.com/ceph/go-ceph/cephfs/admin/subvolume.go
generated
vendored
25
vendor/github.com/ceph/go-ceph/cephfs/admin/subvolume.go
generated
vendored
@ -197,10 +197,35 @@ const (
|
|||||||
SnapshotRetentionFeature = Feature("snapshot-retention")
|
SnapshotRetentionFeature = Feature("snapshot-retention")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SubVolumeState is used to define constant value for the state of
|
||||||
|
// a subvolume.
|
||||||
|
type SubVolumeState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StateUnset indicates a subvolume without any state.
|
||||||
|
StateUnset = SubVolumeState("")
|
||||||
|
// StateInit indicates that the subvolume is in initializing state.
|
||||||
|
StateInit = SubVolumeState("init")
|
||||||
|
// StatePending indicates that the subvolume is in pending state.
|
||||||
|
StatePending = SubVolumeState("pending")
|
||||||
|
// StateInProgress indicates that the subvolume is in in-progress state.
|
||||||
|
StateInProgress = SubVolumeState("in-progress")
|
||||||
|
// StateFailed indicates that the subvolume is in failed state.
|
||||||
|
StateFailed = SubVolumeState("failed")
|
||||||
|
// StateComplete indicates that the subvolume is in complete state.
|
||||||
|
StateComplete = SubVolumeState("complete")
|
||||||
|
// StateCanceled indicates that the subvolume is in canceled state.
|
||||||
|
StateCanceled = SubVolumeState("canceled")
|
||||||
|
// StateSnapRetained indicates that the subvolume is in
|
||||||
|
// snapshot-retained state.
|
||||||
|
StateSnapRetained = SubVolumeState("snapshot-retained")
|
||||||
|
)
|
||||||
|
|
||||||
// SubVolumeInfo reports various informational values about a subvolume.
|
// SubVolumeInfo reports various informational values about a subvolume.
|
||||||
type SubVolumeInfo struct {
|
type SubVolumeInfo struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
|
State SubVolumeState `json:"state"`
|
||||||
Uid int `json:"uid"`
|
Uid int `json:"uid"`
|
||||||
Gid int `json:"gid"`
|
Gid int `json:"gid"`
|
||||||
Mode int `json:"mode"`
|
Mode int `json:"mode"`
|
||||||
|
62
vendor/github.com/ceph/go-ceph/internal/cutil/aliases.go
generated
vendored
Normal file
62
vendor/github.com/ceph/go-ceph/internal/cutil/aliases.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package cutil
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
typedef void* voidptr;
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MaxIdx is the maximum index on 32 bit systems
|
||||||
|
MaxIdx = 1<<31 - 1 // 2GB, max int32 value, should be safe
|
||||||
|
|
||||||
|
// PtrSize is the size of a pointer
|
||||||
|
PtrSize = C.sizeof_voidptr
|
||||||
|
|
||||||
|
// SizeTSize is the size of C.size_t
|
||||||
|
SizeTSize = C.sizeof_size_t
|
||||||
|
)
|
||||||
|
|
||||||
|
// SizeT wraps size_t from C.
|
||||||
|
type SizeT C.size_t
|
||||||
|
|
||||||
|
// This section contains a bunch of types that are basically just
|
||||||
|
// unsafe.Pointer but have specific types to help "self document" what the
|
||||||
|
// underlying pointer is really meant to represent.
|
||||||
|
|
||||||
|
// CPtr is an unsafe.Pointer to C allocated memory
|
||||||
|
type CPtr unsafe.Pointer
|
||||||
|
|
||||||
|
// CharPtrPtr is an unsafe pointer wrapping C's `char**`.
|
||||||
|
type CharPtrPtr unsafe.Pointer
|
||||||
|
|
||||||
|
// CharPtr is an unsafe pointer wrapping C's `char*`.
|
||||||
|
type CharPtr unsafe.Pointer
|
||||||
|
|
||||||
|
// SizeTPtr is an unsafe pointer wrapping C's `size_t*`.
|
||||||
|
type SizeTPtr unsafe.Pointer
|
||||||
|
|
||||||
|
// FreeFunc is a wrapper around calls to, or act like, C's free function.
|
||||||
|
type FreeFunc func(unsafe.Pointer)
|
||||||
|
|
||||||
|
// Malloc is C.malloc
|
||||||
|
func Malloc(s SizeT) CPtr { return CPtr(C.malloc(C.size_t(s))) }
|
||||||
|
|
||||||
|
// Free is C.free
|
||||||
|
func Free(p CPtr) { C.free(unsafe.Pointer(p)) }
|
||||||
|
|
||||||
|
// CString is C.CString
|
||||||
|
func CString(s string) CharPtr { return CharPtr((C.CString(s))) }
|
||||||
|
|
||||||
|
// CBytes is C.CBytes
|
||||||
|
func CBytes(b []byte) CPtr { return CPtr(C.CBytes(b)) }
|
||||||
|
|
||||||
|
// Memcpy is C.memcpy
|
||||||
|
func Memcpy(dst, src CPtr, n SizeT) {
|
||||||
|
C.memcpy(unsafe.Pointer(dst), unsafe.Pointer(src), C.size_t(n))
|
||||||
|
}
|
78
vendor/github.com/ceph/go-ceph/internal/cutil/iovec.go
generated
vendored
78
vendor/github.com/ceph/go-ceph/internal/cutil/iovec.go
generated
vendored
@ -5,74 +5,56 @@ package cutil
|
|||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var iovecSize uintptr
|
// Iovec is a slice of iovec structs. Might have allocated C memory, so it must
|
||||||
|
// be freed with the Free() method.
|
||||||
// StructIovecPtr is an unsafe pointer wrapping C's `*struct iovec`.
|
|
||||||
type StructIovecPtr unsafe.Pointer
|
|
||||||
|
|
||||||
// Iovec helps manage struct iovec arrays needed by some C functions.
|
|
||||||
type Iovec struct {
|
type Iovec struct {
|
||||||
// cvec represents an array of struct iovec C memory
|
iovec []C.struct_iovec
|
||||||
cvec unsafe.Pointer
|
sbs []*SyncBuffer
|
||||||
// length of the array (in elements)
|
|
||||||
length int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIovec creates an Iovec, and underlying C memory, of the specified size.
|
const iovecSize = C.sizeof_struct_iovec
|
||||||
func NewIovec(l int) *Iovec {
|
|
||||||
r := &Iovec{
|
// ByteSlicesToIovec creates an Iovec and links it to Go buffers in data.
|
||||||
cvec: C.malloc(C.size_t(l) * C.size_t(iovecSize)),
|
func ByteSlicesToIovec(data [][]byte) (v Iovec) {
|
||||||
length: l,
|
n := len(data)
|
||||||
|
iovecMem := C.malloc(iovecSize * C.size_t(n))
|
||||||
|
v.iovec = (*[MaxIdx]C.struct_iovec)(iovecMem)[:n:n]
|
||||||
|
for i, b := range data {
|
||||||
|
sb := NewSyncBuffer(CPtr(&v.iovec[i].iov_base), b)
|
||||||
|
v.sbs = append(v.sbs, sb)
|
||||||
|
v.iovec[i].iov_len = C.size_t(len(b))
|
||||||
}
|
}
|
||||||
return r
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByteSlicesToIovec takes a slice of byte slices and returns a new iovec that
|
// Sync makes sure the slices contain the same as the C buffers
|
||||||
// maps the slice data to struct iovec entries.
|
func (v *Iovec) Sync() {
|
||||||
func ByteSlicesToIovec(data [][]byte) *Iovec {
|
for _, sb := range v.sbs {
|
||||||
iov := NewIovec(len(data))
|
sb.Sync()
|
||||||
for i := range data {
|
|
||||||
iov.Set(i, data[i])
|
|
||||||
}
|
}
|
||||||
return iov
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointer returns a StructIovecPtr that represents the C memory of the
|
// Pointer returns a pointer to the iovec
|
||||||
// underlying array.
|
func (v *Iovec) Pointer() unsafe.Pointer {
|
||||||
func (v *Iovec) Pointer() StructIovecPtr {
|
return unsafe.Pointer(&v.iovec[0])
|
||||||
return StructIovecPtr(unsafe.Pointer(v.cvec))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the number of entries in the Iovec.
|
// Len returns a pointer to the iovec
|
||||||
func (v *Iovec) Len() int {
|
func (v *Iovec) Len() int {
|
||||||
return v.length
|
return len(v.iovec)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the C memory in the Iovec.
|
// Free the C memory in the Iovec.
|
||||||
func (v *Iovec) Free() {
|
func (v *Iovec) Free() {
|
||||||
if v.cvec != nil {
|
for _, sb := range v.sbs {
|
||||||
C.free(v.cvec)
|
sb.Release()
|
||||||
v.cvec = nil
|
|
||||||
v.length = 0
|
|
||||||
}
|
}
|
||||||
|
if len(v.iovec) != 0 {
|
||||||
|
C.free(unsafe.Pointer(&v.iovec[0]))
|
||||||
}
|
}
|
||||||
|
v.iovec = nil
|
||||||
// Set will map the memory of the given byte slice to the iovec at the
|
|
||||||
// specified position.
|
|
||||||
func (v *Iovec) Set(i int, buf []byte) {
|
|
||||||
offset := uintptr(i) * iovecSize
|
|
||||||
iov := (*C.struct_iovec)(unsafe.Pointer(
|
|
||||||
uintptr(unsafe.Pointer(v.cvec)) + offset))
|
|
||||||
iov.iov_base = unsafe.Pointer(&buf[0])
|
|
||||||
iov.iov_len = C.size_t(len(buf))
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var iovec C.struct_iovec
|
|
||||||
iovecSize = unsafe.Sizeof(iovec)
|
|
||||||
}
|
}
|
||||||
|
79
vendor/github.com/ceph/go-ceph/internal/cutil/ptrguard.go
generated
vendored
Normal file
79
vendor/github.com/ceph/go-ceph/internal/cutil/ptrguard.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package cutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PtrGuard respresents a guarded Go pointer (pointing to memory allocated by Go
|
||||||
|
// runtime) stored in C memory (allocated by C)
|
||||||
|
type PtrGuard struct {
|
||||||
|
// These mutexes will be used as binary semaphores for signalling events from
|
||||||
|
// one thread to another, which - in contrast to other languages like C++ - is
|
||||||
|
// possible in Go, that is a Mutex can be locked in one thread and unlocked in
|
||||||
|
// another.
|
||||||
|
stored, release sync.Mutex
|
||||||
|
released bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// WARNING: using binary semaphores (mutexes) for signalling like this is quite
|
||||||
|
// a delicate task in order to avoid deadlocks or panics. Whenever changing the
|
||||||
|
// code logic, please review at least three times that there is no unexpected
|
||||||
|
// state possible. Usually the natural choice would be to use channels instead,
|
||||||
|
// but these can not easily passed to C code because of the pointer-to-pointer
|
||||||
|
// cgo rule, and would require the use of a Go object registry.
|
||||||
|
|
||||||
|
// NewPtrGuard writes the goPtr (pointing to Go memory) into C memory at the
|
||||||
|
// position cPtr, and returns a PtrGuard object.
|
||||||
|
func NewPtrGuard(cPtr CPtr, goPtr unsafe.Pointer) *PtrGuard {
|
||||||
|
var v PtrGuard
|
||||||
|
// Since the mutexes are used for signalling, they have to be initialized to
|
||||||
|
// locked state, so that following lock attempts will block.
|
||||||
|
v.release.Lock()
|
||||||
|
v.stored.Lock()
|
||||||
|
// Start a background go routine that lives until Release is called. This
|
||||||
|
// calls a special function that makes sure the garbage collector doesn't touch
|
||||||
|
// goPtr, stores it into C memory at position cPtr and then waits until it
|
||||||
|
// reveices the "release" signal, after which it nulls out the C memory at
|
||||||
|
// cPtr and then exits.
|
||||||
|
go func() {
|
||||||
|
storeUntilRelease(&v, (*CPtr)(cPtr), uintptr(goPtr))
|
||||||
|
}()
|
||||||
|
// Wait for the "stored" signal from the go routine when the Go pointer has
|
||||||
|
// been stored to the C memory. <--(1)
|
||||||
|
v.stored.Lock()
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release removes the guarded Go pointer from the C memory by overwriting it
|
||||||
|
// with NULL.
|
||||||
|
func (v *PtrGuard) Release() {
|
||||||
|
if !v.released {
|
||||||
|
v.released = true
|
||||||
|
v.release.Unlock() // Send the "release" signal to the go routine. -->(2)
|
||||||
|
v.stored.Lock() // Wait for the second "stored" signal when the C memory
|
||||||
|
// has been nulled out. <--(3)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:uintptrescapes
|
||||||
|
|
||||||
|
// From https://golang.org/src/cmd/compile/internal/gc/lex.go:
|
||||||
|
// For the next function declared in the file any uintptr arguments may be
|
||||||
|
// pointer values converted to uintptr. This directive ensures that the
|
||||||
|
// referenced allocated object, if any, is retained and not moved until the call
|
||||||
|
// completes, even though from the types alone it would appear that the object
|
||||||
|
// is no longer needed during the call. The conversion to uintptr must appear in
|
||||||
|
// the argument list.
|
||||||
|
// Also see https://golang.org/cmd/compile/#hdr-Compiler_Directives
|
||||||
|
|
||||||
|
func storeUntilRelease(v *PtrGuard, cPtr *CPtr, goPtr uintptr) {
|
||||||
|
uip := (*uintptr)(unsafe.Pointer(cPtr))
|
||||||
|
*uip = goPtr // store Go pointer in C memory at c_ptr
|
||||||
|
v.stored.Unlock() // send "stored" signal to main thread -->(1)
|
||||||
|
v.release.Lock() // wait for "release" signal from main thread when
|
||||||
|
// Release() has been called. <--(2)
|
||||||
|
*uip = 0 // reset C memory to NULL
|
||||||
|
v.stored.Unlock() // send second "stored" signal to main thread -->(3)
|
||||||
|
}
|
28
vendor/github.com/ceph/go-ceph/internal/cutil/sync_buffer.go
generated
vendored
Normal file
28
vendor/github.com/ceph/go-ceph/internal/cutil/sync_buffer.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// +build ptrguard
|
||||||
|
|
||||||
|
package cutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SyncBuffer is a C buffer connected to a data slice
|
||||||
|
type SyncBuffer struct {
|
||||||
|
pg *PtrGuard
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSyncBuffer creates a C buffer from a data slice and stores it at CPtr
|
||||||
|
func NewSyncBuffer(cPtr CPtr, data []byte) *SyncBuffer {
|
||||||
|
var v SyncBuffer
|
||||||
|
v.pg = NewPtrGuard(cPtr, unsafe.Pointer(&data[0]))
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release releases the C buffer and nulls its stored pointer
|
||||||
|
func (v *SyncBuffer) Release() {
|
||||||
|
v.pg.Release()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync asserts that changes in the C buffer are available in the data
|
||||||
|
// slice
|
||||||
|
func (v *SyncBuffer) Sync() {}
|
37
vendor/github.com/ceph/go-ceph/internal/cutil/sync_buffer_memcpy.go
generated
vendored
Normal file
37
vendor/github.com/ceph/go-ceph/internal/cutil/sync_buffer_memcpy.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// +build !ptrguard
|
||||||
|
|
||||||
|
package cutil
|
||||||
|
|
||||||
|
// SyncBuffer is a C buffer connected to a data slice
|
||||||
|
type SyncBuffer struct {
|
||||||
|
data []byte
|
||||||
|
cPtr *CPtr
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSyncBuffer creates a C buffer from a data slice and stores it at CPtr
|
||||||
|
func NewSyncBuffer(cPtr CPtr, data []byte) *SyncBuffer {
|
||||||
|
var v SyncBuffer
|
||||||
|
v.data = data
|
||||||
|
v.cPtr = (*CPtr)(cPtr)
|
||||||
|
*v.cPtr = CBytes(data)
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release releases the C buffer and nulls its stored pointer
|
||||||
|
func (v *SyncBuffer) Release() {
|
||||||
|
if v.cPtr != nil {
|
||||||
|
Free(*v.cPtr)
|
||||||
|
*v.cPtr = nil
|
||||||
|
v.cPtr = nil
|
||||||
|
}
|
||||||
|
v.data = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync asserts that changes in the C buffer are available in the data
|
||||||
|
// slice
|
||||||
|
func (v *SyncBuffer) Sync() {
|
||||||
|
if v.cPtr == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Memcpy(CPtr(&v.data[0]), CPtr(*v.cPtr), SizeT(len(v.data)))
|
||||||
|
}
|
28
vendor/github.com/ceph/go-ceph/internal/cutil/type_aliases.go
generated
vendored
28
vendor/github.com/ceph/go-ceph/internal/cutil/type_aliases.go
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
package cutil
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Basic types from C that we can make "public" without too much fuss.
|
|
||||||
|
|
||||||
// SizeT wraps size_t from C.
|
|
||||||
type SizeT C.size_t
|
|
||||||
|
|
||||||
// This section contains a bunch of types that are basically just
|
|
||||||
// unsafe.Pointer but have specific types to help "self document" what the
|
|
||||||
// underlying pointer is really meant to represent.
|
|
||||||
|
|
||||||
// CharPtrPtr is an unsafe pointer wrapping C's `char**`.
|
|
||||||
type CharPtrPtr unsafe.Pointer
|
|
||||||
|
|
||||||
// CharPtr is an unsafe pointer wrapping C's `char*`.
|
|
||||||
type CharPtr unsafe.Pointer
|
|
||||||
|
|
||||||
// SizeTPtr is an unsafe pointer wrapping C's `size_t*`.
|
|
||||||
type SizeTPtr unsafe.Pointer
|
|
||||||
|
|
||||||
// FreeFunc is a wrapper around calls to, or act like, C's free function.
|
|
||||||
type FreeFunc func(unsafe.Pointer)
|
|
9
vendor/github.com/ceph/go-ceph/internal/timespec/timespec.go
generated
vendored
9
vendor/github.com/ceph/go-ceph/internal/timespec/timespec.go
generated
vendored
@ -28,3 +28,12 @@ func CStructToTimespec(cts CTimespecPtr) Timespec {
|
|||||||
Nsec: int64(t.tv_nsec),
|
Nsec: int64(t.tv_nsec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CopyToCStruct copies the time values from a Timespec to a previously
|
||||||
|
// allocated C `struct timespec`. Due to restrictions on Cgo the C pointer
|
||||||
|
// must be passed via the CTimespecPtr wrapper.
|
||||||
|
func CopyToCStruct(ts Timespec, cts CTimespecPtr) {
|
||||||
|
t := (*C.struct_timespec)(cts)
|
||||||
|
t.tv_sec = C.time_t(ts.Sec)
|
||||||
|
t.tv_nsec = C.long(ts.Nsec)
|
||||||
|
}
|
||||||
|
3
vendor/github.com/ceph/go-ceph/rados/errors.go
generated
vendored
3
vendor/github.com/ceph/go-ceph/rados/errors.go
generated
vendored
@ -52,6 +52,9 @@ var (
|
|||||||
// ErrInvalidIOContext may be returned if an api call requires an IOContext
|
// ErrInvalidIOContext may be returned if an api call requires an IOContext
|
||||||
// but IOContext is not ready for use.
|
// but IOContext is not ready for use.
|
||||||
ErrInvalidIOContext = errors.New("IOContext is not ready for use")
|
ErrInvalidIOContext = errors.New("IOContext is not ready for use")
|
||||||
|
// ErrOperationIncomplete is returned from write op or read op steps for
|
||||||
|
// which the operation has not been performed yet.
|
||||||
|
ErrOperationIncomplete = errors.New("Operation has not been performed yet")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Public radosErrors:
|
// Public radosErrors:
|
||||||
|
13
vendor/github.com/ceph/go-ceph/rados/ioctx.go
generated
vendored
13
vendor/github.com/ceph/go-ceph/rados/ioctx.go
generated
vendored
@ -128,15 +128,10 @@ func (ioctx *IOContext) SetNamespace(namespace string) {
|
|||||||
// void rados_write_op_create(rados_write_op_t write_op, int exclusive,
|
// void rados_write_op_create(rados_write_op_t write_op, int exclusive,
|
||||||
// const char* category)
|
// const char* category)
|
||||||
func (ioctx *IOContext) Create(oid string, exclusive CreateOption) error {
|
func (ioctx *IOContext) Create(oid string, exclusive CreateOption) error {
|
||||||
c_oid := C.CString(oid)
|
op := CreateWriteOp()
|
||||||
defer C.free(unsafe.Pointer(c_oid))
|
defer op.Release()
|
||||||
|
op.Create(exclusive)
|
||||||
op := C.rados_create_write_op()
|
return op.operateCompat(ioctx, oid)
|
||||||
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 getError(ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes len(data) bytes to the object with key oid starting at byte
|
// Write writes len(data) bytes to the object with key oid starting at byte
|
||||||
|
357
vendor/github.com/ceph/go-ceph/rados/omap.go
generated
vendored
357
vendor/github.com/ceph/go-ceph/rados/omap.go
generated
vendored
@ -1,69 +1,230 @@
|
|||||||
package rados
|
package rados
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lrados
|
/*
|
||||||
// #include <stdlib.h>
|
#cgo LDFLAGS: -lrados
|
||||||
// #include <rados/librados.h>
|
#include <stdlib.h>
|
||||||
//
|
#include <rados/librados.h>
|
||||||
|
|
||||||
|
typedef void* voidptr;
|
||||||
|
|
||||||
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetOmap appends the map `pairs` to the omap `oid`
|
const (
|
||||||
func (ioctx *IOContext) SetOmap(oid string, pairs map[string][]byte) error {
|
ptrSize = C.sizeof_voidptr
|
||||||
c_oid := C.CString(oid)
|
sizeTSize = C.sizeof_size_t
|
||||||
defer C.free(unsafe.Pointer(c_oid))
|
)
|
||||||
|
|
||||||
var s C.size_t
|
// setOmapStep is a write op step. It holds C memory used in the operation.
|
||||||
var c *C.char
|
type setOmapStep struct {
|
||||||
ptrSize := unsafe.Sizeof(c)
|
withRefs
|
||||||
|
withoutUpdate
|
||||||
|
|
||||||
c_keys := C.malloc(C.size_t(len(pairs)) * C.size_t(ptrSize))
|
// C arguments
|
||||||
c_values := C.malloc(C.size_t(len(pairs)) * C.size_t(ptrSize))
|
cKeys **C.char
|
||||||
c_lengths := C.malloc(C.size_t(len(pairs)) * C.size_t(unsafe.Sizeof(s)))
|
cValues **C.char
|
||||||
|
cLengths *C.size_t
|
||||||
defer C.free(unsafe.Pointer(c_keys))
|
cNum C.size_t
|
||||||
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))
|
func newSetOmapStep(pairs map[string][]byte) *setOmapStep {
|
||||||
*c_length_ptr = c_length
|
|
||||||
|
maplen := C.size_t(len(pairs))
|
||||||
|
cKeys := C.malloc(maplen * ptrSize)
|
||||||
|
cValues := C.malloc(maplen * ptrSize)
|
||||||
|
cLengths := C.malloc(maplen * sizeTSize)
|
||||||
|
|
||||||
|
sos := &setOmapStep{
|
||||||
|
cKeys: (**C.char)(cKeys),
|
||||||
|
cValues: (**C.char)(cValues),
|
||||||
|
cLengths: (*C.size_t)(cLengths),
|
||||||
|
cNum: C.size_t(len(pairs)),
|
||||||
|
}
|
||||||
|
sos.add(cKeys)
|
||||||
|
sos.add(cValues)
|
||||||
|
sos.add(cLengths)
|
||||||
|
|
||||||
|
var i uintptr
|
||||||
|
for key, value := range pairs {
|
||||||
|
// key
|
||||||
|
ck := C.CString(key)
|
||||||
|
sos.add(unsafe.Pointer(ck))
|
||||||
|
ckp := (**C.char)(unsafe.Pointer(uintptr(cKeys) + i*ptrSize))
|
||||||
|
*ckp = ck
|
||||||
|
|
||||||
|
// value and its length
|
||||||
|
cvp := (**C.char)(unsafe.Pointer(uintptr(cValues) + i*ptrSize))
|
||||||
|
vlen := C.size_t(len(value))
|
||||||
|
if vlen > 0 {
|
||||||
|
cv := C.CBytes(value)
|
||||||
|
sos.add(cv)
|
||||||
|
*cvp = (*C.char)(cv)
|
||||||
|
} else {
|
||||||
|
*cvp = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
clp := (*C.size_t)(unsafe.Pointer(uintptr(cLengths) + i*ptrSize))
|
||||||
|
*clp = vlen
|
||||||
|
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
op := C.rados_create_write_op()
|
runtime.SetFinalizer(sos, opStepFinalizer)
|
||||||
C.rados_write_op_omap_set(
|
return sos
|
||||||
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)
|
func (sos *setOmapStep) free() {
|
||||||
C.rados_release_write_op(op)
|
sos.cKeys = nil
|
||||||
|
sos.cValues = nil
|
||||||
|
sos.cLengths = nil
|
||||||
|
sos.withRefs.free()
|
||||||
|
}
|
||||||
|
|
||||||
return getError(ret)
|
// OmapKeyValue items are returned by the GetOmapStep's Next call.
|
||||||
|
type OmapKeyValue struct {
|
||||||
|
Key string
|
||||||
|
Value []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOmapStep values are used to get the results of an GetOmapValues call
|
||||||
|
// on a WriteOp. Until the Operate method of the WriteOp is called the Next
|
||||||
|
// call will return an error. After Operate is called, the Next call will
|
||||||
|
// return valid results.
|
||||||
|
//
|
||||||
|
// The life cycle of the GetOmapStep is bound to the ReadOp, if the ReadOp
|
||||||
|
// Release method is called the public methods of the step must no longer be
|
||||||
|
// used and may return errors.
|
||||||
|
type GetOmapStep struct {
|
||||||
|
// inputs:
|
||||||
|
startAfter string
|
||||||
|
filterPrefix string
|
||||||
|
maxReturn uint64
|
||||||
|
|
||||||
|
// arguments:
|
||||||
|
cStartAfter *C.char
|
||||||
|
cFilterPrefix *C.char
|
||||||
|
|
||||||
|
// C returned data:
|
||||||
|
iter C.rados_omap_iter_t
|
||||||
|
more C.uchar
|
||||||
|
rval C.int
|
||||||
|
|
||||||
|
// internal state:
|
||||||
|
|
||||||
|
// canIterate is only set after the operation is performed and is
|
||||||
|
// intended to prevent premature fetching of data
|
||||||
|
canIterate bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGetOmapStep(startAfter, filterPrefix string, maxReturn uint64) *GetOmapStep {
|
||||||
|
gos := &GetOmapStep{
|
||||||
|
startAfter: startAfter,
|
||||||
|
filterPrefix: filterPrefix,
|
||||||
|
maxReturn: maxReturn,
|
||||||
|
cStartAfter: C.CString(startAfter),
|
||||||
|
cFilterPrefix: C.CString(filterPrefix),
|
||||||
|
}
|
||||||
|
runtime.SetFinalizer(gos, opStepFinalizer)
|
||||||
|
return gos
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gos *GetOmapStep) free() {
|
||||||
|
gos.canIterate = false
|
||||||
|
if gos.iter != nil {
|
||||||
|
C.rados_omap_get_end(gos.iter)
|
||||||
|
}
|
||||||
|
gos.iter = nil
|
||||||
|
gos.more = 0
|
||||||
|
gos.rval = 0
|
||||||
|
C.free(unsafe.Pointer(gos.cStartAfter))
|
||||||
|
gos.cStartAfter = nil
|
||||||
|
C.free(unsafe.Pointer(gos.cFilterPrefix))
|
||||||
|
gos.cFilterPrefix = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gos *GetOmapStep) update() error {
|
||||||
|
err := getError(gos.rval)
|
||||||
|
gos.canIterate = (err == nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next key value pair or nil if iteration is exhausted.
|
||||||
|
func (gos *GetOmapStep) Next() (*OmapKeyValue, error) {
|
||||||
|
if !gos.canIterate {
|
||||||
|
return nil, ErrOperationIncomplete
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
cKey *C.char
|
||||||
|
cVal *C.char
|
||||||
|
cLen C.size_t
|
||||||
|
)
|
||||||
|
ret := C.rados_omap_get_next(gos.iter, &cKey, &cVal, &cLen)
|
||||||
|
if ret != 0 {
|
||||||
|
return nil, getError(ret)
|
||||||
|
}
|
||||||
|
if cKey == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return &OmapKeyValue{
|
||||||
|
Key: C.GoString(cKey),
|
||||||
|
Value: C.GoBytes(unsafe.Pointer(cVal), C.int(cLen)),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// More returns true if there are more matching keys available.
|
||||||
|
func (gos *GetOmapStep) More() bool {
|
||||||
|
// tad bit hacky, but go can't automatically convert from
|
||||||
|
// unsigned char to bool
|
||||||
|
return gos.more != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeOmapKeysStep is a write operation step used to track state, especially
|
||||||
|
// C memory, across the setup and use of a WriteOp.
|
||||||
|
type removeOmapKeysStep struct {
|
||||||
|
withRefs
|
||||||
|
withoutUpdate
|
||||||
|
|
||||||
|
// arguments:
|
||||||
|
cKeys **C.char
|
||||||
|
cNum C.size_t
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRemoveOmapKeysStep(keys []string) *removeOmapKeysStep {
|
||||||
|
cKeys := C.malloc(C.size_t(len(keys)) * ptrSize)
|
||||||
|
roks := &removeOmapKeysStep{
|
||||||
|
cKeys: (**C.char)(cKeys),
|
||||||
|
cNum: C.size_t(len(keys)),
|
||||||
|
}
|
||||||
|
roks.add(cKeys)
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, key := range keys {
|
||||||
|
ckp := (**C.char)(unsafe.Pointer(uintptr(cKeys) + uintptr(i)*ptrSize))
|
||||||
|
*ckp = C.CString(key)
|
||||||
|
roks.add(unsafe.Pointer(*ckp))
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.SetFinalizer(roks, opStepFinalizer)
|
||||||
|
return roks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (roks *removeOmapKeysStep) free() {
|
||||||
|
roks.cKeys = nil
|
||||||
|
roks.withRefs.free()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOmap appends the map `pairs` to the omap `oid`
|
||||||
|
func (ioctx *IOContext) SetOmap(oid string, pairs map[string][]byte) error {
|
||||||
|
op := CreateWriteOp()
|
||||||
|
defer op.Release()
|
||||||
|
op.SetOmap(pairs)
|
||||||
|
return op.operateCompat(ioctx, oid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OmapListFunc is the type of the function called for each omap key
|
// OmapListFunc is the type of the function called for each omap key
|
||||||
@ -78,58 +239,25 @@ type OmapListFunc func(key string, value []byte)
|
|||||||
// `maxReturn`: iterate no more than `maxReturn` key/value pairs
|
// `maxReturn`: iterate no more than `maxReturn` key/value pairs
|
||||||
// `listFn`: the function called at each iteration
|
// `listFn`: the function called at each iteration
|
||||||
func (ioctx *IOContext) ListOmapValues(oid string, startAfter string, filterPrefix string, maxReturn int64, listFn OmapListFunc) error {
|
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))
|
op := CreateReadOp()
|
||||||
defer C.free(unsafe.Pointer(c_start_after))
|
defer op.Release()
|
||||||
defer C.free(unsafe.Pointer(c_filter_prefix))
|
gos := op.GetOmapValues(startAfter, filterPrefix, uint64(maxReturn))
|
||||||
|
err := op.operateCompat(ioctx, oid)
|
||||||
op := C.rados_create_read_op()
|
if err != nil {
|
||||||
|
return err
|
||||||
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 getError(ret)
|
|
||||||
} else if int(c_prval) != 0 {
|
|
||||||
return getError(c_prval)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var c_key *C.char
|
kv, err := gos.Next()
|
||||||
var c_val *C.char
|
if err != nil {
|
||||||
var c_len C.size_t
|
return err
|
||||||
|
|
||||||
ret = C.rados_omap_get_next(c_iter, &c_key, &c_val, &c_len)
|
|
||||||
|
|
||||||
if int(ret) != 0 {
|
|
||||||
return getError(ret)
|
|
||||||
}
|
}
|
||||||
|
if kv == nil {
|
||||||
if c_key == nil {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
listFn(kv.Key, kv.Value)
|
||||||
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,45 +312,16 @@ func (ioctx *IOContext) GetAllOmapValues(oid string, startAfter string, filterPr
|
|||||||
|
|
||||||
// RmOmapKeys removes the specified `keys` from the omap `oid`
|
// RmOmapKeys removes the specified `keys` from the omap `oid`
|
||||||
func (ioctx *IOContext) RmOmapKeys(oid string, keys []string) error {
|
func (ioctx *IOContext) RmOmapKeys(oid string, keys []string) error {
|
||||||
c_oid := C.CString(oid)
|
op := CreateWriteOp()
|
||||||
defer C.free(unsafe.Pointer(c_oid))
|
defer op.Release()
|
||||||
|
op.RmOmapKeys(keys)
|
||||||
var c *C.char
|
return op.operateCompat(ioctx, oid)
|
||||||
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 getError(ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanOmap clears the omap `oid`
|
// CleanOmap clears the omap `oid`
|
||||||
func (ioctx *IOContext) CleanOmap(oid string) error {
|
func (ioctx *IOContext) CleanOmap(oid string) error {
|
||||||
c_oid := C.CString(oid)
|
op := CreateWriteOp()
|
||||||
defer C.free(unsafe.Pointer(c_oid))
|
defer op.Release()
|
||||||
|
op.CleanOmap()
|
||||||
op := C.rados_create_write_op()
|
return op.operateCompat(ioctx, oid)
|
||||||
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 getError(ret)
|
|
||||||
}
|
}
|
||||||
|
151
vendor/github.com/ceph/go-ceph/rados/operation.go
generated
vendored
Normal file
151
vendor/github.com/ceph/go-ceph/rados/operation.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package rados
|
||||||
|
|
||||||
|
// #include <stdlib.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The file operation.go exists to support both read op and write op types that
|
||||||
|
// have some pretty common behaviors between them. In C/C++ its assumed that
|
||||||
|
// the buffer types and other pointers will not be freed between passing them
|
||||||
|
// to the action setup calls (things like rados_write_op_write or
|
||||||
|
// rados_read_op_omap_get_vals2) and the call to Operate(...). Since there's
|
||||||
|
// nothing stopping one from sleeping for hours between these calls, or passing
|
||||||
|
// the op to other functions and calling Operate there, we want a mechanism
|
||||||
|
// that's (fairly) simple to understand and won't run afoul of Go's garbage
|
||||||
|
// collection. That's one reason the operation type tracks the steps (the
|
||||||
|
// parts that track complex inputs and outputs) so that as long as the op
|
||||||
|
// exists it will have a reference to the step, which will have references
|
||||||
|
// to the C language types.
|
||||||
|
|
||||||
|
type opKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
readOp opKind = "read"
|
||||||
|
writeOp opKind = "write"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OperationError is an error type that may be returned by an Operate call.
|
||||||
|
// It captures the error from the operate call itself and any errors from
|
||||||
|
// steps that can return an error.
|
||||||
|
type OperationError struct {
|
||||||
|
kind opKind
|
||||||
|
OpError error
|
||||||
|
StepErrors map[int]error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e OperationError) Error() string {
|
||||||
|
subErrors := []string{}
|
||||||
|
if e.OpError != nil {
|
||||||
|
subErrors = append(subErrors,
|
||||||
|
fmt.Sprintf("op=%s", e.OpError))
|
||||||
|
}
|
||||||
|
for idx, es := range e.StepErrors {
|
||||||
|
subErrors = append(subErrors,
|
||||||
|
fmt.Sprintf("Step#%d=%s", idx, es))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"%s operation error: %s",
|
||||||
|
e.kind,
|
||||||
|
strings.Join(subErrors, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// opStep provides an interface for types that are tied to the management of
|
||||||
|
// data being input or output from write ops and read ops. The steps are
|
||||||
|
// meant to simplify the internals of the ops themselves and be exportable when
|
||||||
|
// appropriate. If a step is not being exported it should not be returned
|
||||||
|
// from an ops action function. If the step is exported it should be
|
||||||
|
// returned from an ops action function.
|
||||||
|
//
|
||||||
|
// Not all types implementing opStep are expected to need all the functions
|
||||||
|
// in the interface. However, for the sake of simplicity on the op side, we use
|
||||||
|
// the same interface for all cases and expect those implementing opStep
|
||||||
|
// just embed the without* types that provide no-op implementation of
|
||||||
|
// functions that make up this interface.
|
||||||
|
type opStep interface {
|
||||||
|
// update the state of the step after the call to Operate.
|
||||||
|
// It can be used to convert values from C and cache them and/or
|
||||||
|
// communicate a failure of the action associated with the step. The
|
||||||
|
// update call will only be made once. Implementations are not required to
|
||||||
|
// handle this call being made more than once.
|
||||||
|
update() error
|
||||||
|
// free will be called to free any resources, especially C memory, that
|
||||||
|
// the step is managing. The behavior of free should be idempotent and
|
||||||
|
// handle being called more than once.
|
||||||
|
free()
|
||||||
|
}
|
||||||
|
|
||||||
|
// operation represents some of the shared underlying mechanisms for
|
||||||
|
// both read and write op types.
|
||||||
|
type operation struct {
|
||||||
|
steps []opStep
|
||||||
|
}
|
||||||
|
|
||||||
|
// free will call the free method of all the steps this operation
|
||||||
|
// contains.
|
||||||
|
func (o *operation) free() {
|
||||||
|
for i := range o.steps {
|
||||||
|
o.steps[i].free()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the operation and the steps it contains. The top-level result
|
||||||
|
// of the rados call is passed in as ret and used to construct errors.
|
||||||
|
// The update call of each step is used to update the contents of each
|
||||||
|
// step and gather any errors from those steps.
|
||||||
|
func (o *operation) update(kind opKind, ret C.int) error {
|
||||||
|
stepErrors := map[int]error{}
|
||||||
|
for i := range o.steps {
|
||||||
|
if err := o.steps[i].update(); err != nil {
|
||||||
|
stepErrors[i] = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ret == 0 && len(stepErrors) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return OperationError{
|
||||||
|
kind: kind,
|
||||||
|
OpError: getError(ret),
|
||||||
|
StepErrors: stepErrors,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func opStepFinalizer(s opStep) {
|
||||||
|
if s != nil {
|
||||||
|
s.free()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// withoutUpdate can be embedded in a struct to help indicate
|
||||||
|
// the type implements the opStep interface but has a no-op
|
||||||
|
// update function.
|
||||||
|
type withoutUpdate struct{}
|
||||||
|
|
||||||
|
func (*withoutUpdate) update() error { return nil }
|
||||||
|
|
||||||
|
// withoutFree can be embedded in a struct to help indicate
|
||||||
|
// the type implements the opStep interface but has a no-op
|
||||||
|
// free function.
|
||||||
|
type withoutFree struct{}
|
||||||
|
|
||||||
|
func (*withoutFree) free() {}
|
||||||
|
|
||||||
|
// withRefs is a embeddable type to help track and free C memory.
|
||||||
|
type withRefs struct {
|
||||||
|
refs []unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *withRefs) free() {
|
||||||
|
for i := range w.refs {
|
||||||
|
C.free(w.refs[i])
|
||||||
|
}
|
||||||
|
w.refs = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *withRefs) add(ptr unsafe.Pointer) {
|
||||||
|
w.refs = append(w.refs, ptr)
|
||||||
|
}
|
37
vendor/github.com/ceph/go-ceph/rados/operation_flags.go
generated
vendored
Normal file
37
vendor/github.com/ceph/go-ceph/rados/operation_flags.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package rados
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lrados
|
||||||
|
// #include <errno.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include <rados/librados.h>
|
||||||
|
//
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// OperationFlags control the behavior of read and write operations.
|
||||||
|
type OperationFlags int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// OperationNoFlag indicates no special behavior is requested.
|
||||||
|
OperationNoFlag = OperationFlags(C.LIBRADOS_OPERATION_NOFLAG)
|
||||||
|
// OperationBalanceReads TODO
|
||||||
|
OperationBalanceReads = OperationFlags(C.LIBRADOS_OPERATION_BALANCE_READS)
|
||||||
|
// OperationLocalizeReads TODO
|
||||||
|
OperationLocalizeReads = OperationFlags(C.LIBRADOS_OPERATION_LOCALIZE_READS)
|
||||||
|
// OperationOrderReadsWrites TODO
|
||||||
|
OperationOrderReadsWrites = OperationFlags(C.LIBRADOS_OPERATION_ORDER_READS_WRITES)
|
||||||
|
// OperationIgnoreCache TODO
|
||||||
|
OperationIgnoreCache = OperationFlags(C.LIBRADOS_OPERATION_IGNORE_CACHE)
|
||||||
|
// OperationSkipRWLocks TODO
|
||||||
|
OperationSkipRWLocks = OperationFlags(C.LIBRADOS_OPERATION_SKIPRWLOCKS)
|
||||||
|
// OperationIgnoreOverlay TODO
|
||||||
|
OperationIgnoreOverlay = OperationFlags(C.LIBRADOS_OPERATION_IGNORE_OVERLAY)
|
||||||
|
// OperationFullTry send request to a full cluster or pool, ops such as delete
|
||||||
|
// can succeed while other ops will return out-of-space errors.
|
||||||
|
OperationFullTry = OperationFlags(C.LIBRADOS_OPERATION_FULL_TRY)
|
||||||
|
// OperationFullForce TODO
|
||||||
|
OperationFullForce = OperationFlags(C.LIBRADOS_OPERATION_FULL_FORCE)
|
||||||
|
// OperationIgnoreRedirect TODO
|
||||||
|
OperationIgnoreRedirect = OperationFlags(C.LIBRADOS_OPERATION_IGNORE_REDIRECT)
|
||||||
|
// OperationOrderSnap TODO
|
||||||
|
OperationOrderSnap = OperationFlags(C.LIBRADOS_OPERATION_ORDERSNAP)
|
||||||
|
)
|
84
vendor/github.com/ceph/go-ceph/rados/read_op.go
generated
vendored
Normal file
84
vendor/github.com/ceph/go-ceph/rados/read_op.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package rados
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lrados
|
||||||
|
// #include <errno.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include <rados/librados.h>
|
||||||
|
//
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReadOp manages a set of discrete object read actions that will be performed
|
||||||
|
// together atomically.
|
||||||
|
type ReadOp struct {
|
||||||
|
operation
|
||||||
|
op C.rados_read_op_t
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateReadOp returns a newly constructed read operation.
|
||||||
|
func CreateReadOp() *ReadOp {
|
||||||
|
return &ReadOp{
|
||||||
|
op: C.rados_create_read_op(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the resources associated with this read operation.
|
||||||
|
func (r *ReadOp) Release() {
|
||||||
|
C.rados_release_read_op(r.op)
|
||||||
|
r.op = nil
|
||||||
|
r.free()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operate will perform the operation(s).
|
||||||
|
func (r *ReadOp) Operate(ioctx *IOContext, oid string, flags OperationFlags) error {
|
||||||
|
if err := ioctx.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cOid := C.CString(oid)
|
||||||
|
defer C.free(unsafe.Pointer(cOid))
|
||||||
|
|
||||||
|
ret := C.rados_read_op_operate(r.op, ioctx.ioctx, cOid, C.int(flags))
|
||||||
|
return r.update(readOp, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ReadOp) operateCompat(ioctx *IOContext, oid string) error {
|
||||||
|
switch err := r.Operate(ioctx, oid, OperationNoFlag).(type) {
|
||||||
|
case nil:
|
||||||
|
return nil
|
||||||
|
case OperationError:
|
||||||
|
return err.OpError
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssertExists assures the object targeted by the read op exists.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// void rados_read_op_assert_exists(rados_read_op_t read_op);
|
||||||
|
func (r *ReadOp) AssertExists() {
|
||||||
|
C.rados_read_op_assert_exists(r.op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOmapValues is used to iterate over a set, or sub-set, of omap keys
|
||||||
|
// as part of a read operation. An GetOmapStep is returned from this
|
||||||
|
// function. The GetOmapStep may be used to iterate over the key-value
|
||||||
|
// pairs after the Operate call has been performed.
|
||||||
|
func (r *ReadOp) GetOmapValues(startAfter, filterPrefix string, maxReturn uint64) *GetOmapStep {
|
||||||
|
gos := newGetOmapStep(startAfter, filterPrefix, maxReturn)
|
||||||
|
r.steps = append(r.steps, gos)
|
||||||
|
C.rados_read_op_omap_get_vals2(
|
||||||
|
r.op,
|
||||||
|
gos.cStartAfter,
|
||||||
|
gos.cFilterPrefix,
|
||||||
|
C.uint64_t(gos.maxReturn),
|
||||||
|
&gos.iter,
|
||||||
|
&gos.more,
|
||||||
|
&gos.rval,
|
||||||
|
)
|
||||||
|
return gos
|
||||||
|
}
|
179
vendor/github.com/ceph/go-ceph/rados/write_op.go
generated
vendored
Normal file
179
vendor/github.com/ceph/go-ceph/rados/write_op.go
generated
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
package rados
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lrados
|
||||||
|
// #include <errno.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include <rados/librados.h>
|
||||||
|
//
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
ts "github.com/ceph/go-ceph/internal/timespec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Timespec is a public type for the internal C 'struct timespec'
|
||||||
|
type Timespec ts.Timespec
|
||||||
|
|
||||||
|
// WriteOp manages a set of discrete actions that will be performed together
|
||||||
|
// atomically.
|
||||||
|
type WriteOp struct {
|
||||||
|
operation
|
||||||
|
op C.rados_write_op_t
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateWriteOp returns a newly constructed write operation.
|
||||||
|
func CreateWriteOp() *WriteOp {
|
||||||
|
return &WriteOp{
|
||||||
|
op: C.rados_create_write_op(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the resources associated with this write operation.
|
||||||
|
func (w *WriteOp) Release() {
|
||||||
|
C.rados_release_write_op(w.op)
|
||||||
|
w.op = nil
|
||||||
|
w.free()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WriteOp) operate2(
|
||||||
|
ioctx *IOContext, oid string, mtime *Timespec, flags OperationFlags) error {
|
||||||
|
|
||||||
|
if err := ioctx.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cOid := C.CString(oid)
|
||||||
|
defer C.free(unsafe.Pointer(cOid))
|
||||||
|
var cMtime *C.struct_timespec
|
||||||
|
if mtime != nil {
|
||||||
|
cMtime = &C.struct_timespec{}
|
||||||
|
ts.CopyToCStruct(
|
||||||
|
ts.Timespec(*mtime),
|
||||||
|
ts.CTimespecPtr(cMtime))
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := C.rados_write_op_operate2(
|
||||||
|
w.op, ioctx.ioctx, cOid, cMtime, C.int(flags))
|
||||||
|
return w.update(writeOp, ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operate will perform the operation(s).
|
||||||
|
func (w *WriteOp) Operate(ioctx *IOContext, oid string, flags OperationFlags) error {
|
||||||
|
return w.operate2(ioctx, oid, nil, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperateWithMtime will perform the operation while setting the modification
|
||||||
|
// time stamp to the supplied value.
|
||||||
|
func (w *WriteOp) OperateWithMtime(
|
||||||
|
ioctx *IOContext, oid string, mtime Timespec, flags OperationFlags) error {
|
||||||
|
|
||||||
|
return w.operate2(ioctx, oid, &mtime, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WriteOp) operateCompat(ioctx *IOContext, oid string) error {
|
||||||
|
switch err := w.Operate(ioctx, oid, OperationNoFlag).(type) {
|
||||||
|
case nil:
|
||||||
|
return nil
|
||||||
|
case OperationError:
|
||||||
|
return err.OpError
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a rados object.
|
||||||
|
func (w *WriteOp) Create(exclusive CreateOption) {
|
||||||
|
// category, the 3rd param, is deprecated and has no effect so we do not
|
||||||
|
// implement it in go-ceph
|
||||||
|
C.rados_write_op_create(w.op, C.int(exclusive), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOmap appends the map `pairs` to the omap `oid`.
|
||||||
|
func (w *WriteOp) SetOmap(pairs map[string][]byte) {
|
||||||
|
sos := newSetOmapStep(pairs)
|
||||||
|
w.steps = append(w.steps, sos)
|
||||||
|
C.rados_write_op_omap_set(
|
||||||
|
w.op,
|
||||||
|
sos.cKeys,
|
||||||
|
sos.cValues,
|
||||||
|
sos.cLengths,
|
||||||
|
sos.cNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RmOmapKeys removes the specified `keys` from the omap `oid`.
|
||||||
|
func (w *WriteOp) RmOmapKeys(keys []string) {
|
||||||
|
roks := newRemoveOmapKeysStep(keys)
|
||||||
|
w.steps = append(w.steps, roks)
|
||||||
|
C.rados_write_op_omap_rm_keys(
|
||||||
|
w.op,
|
||||||
|
roks.cKeys,
|
||||||
|
roks.cNum)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanOmap clears the omap `oid`.
|
||||||
|
func (w *WriteOp) CleanOmap() {
|
||||||
|
C.rados_write_op_omap_clear(w.op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssertExists assures the object targeted by the write op exists.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// void rados_write_op_assert_exists(rados_write_op_t write_op);
|
||||||
|
func (w *WriteOp) AssertExists() {
|
||||||
|
C.rados_write_op_assert_exists(w.op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a given byte slice at the supplied offset.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// void rados_write_op_write(rados_write_op_t write_op,
|
||||||
|
// const char *buffer,
|
||||||
|
// size_t len,
|
||||||
|
// uint64_t offset);
|
||||||
|
func (w *WriteOp) Write(b []byte, offset uint64) {
|
||||||
|
oe := newWriteStep(b, 0, offset)
|
||||||
|
w.steps = append(w.steps, oe)
|
||||||
|
C.rados_write_op_write(
|
||||||
|
w.op,
|
||||||
|
oe.cBuffer,
|
||||||
|
oe.cDataLen,
|
||||||
|
oe.cOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteFull writes a given byte slice as the whole object,
|
||||||
|
// atomically replacing it.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// void rados_write_op_write_full(rados_write_op_t write_op,
|
||||||
|
// const char *buffer,
|
||||||
|
// size_t len);
|
||||||
|
func (w *WriteOp) WriteFull(b []byte) {
|
||||||
|
oe := newWriteStep(b, 0, 0)
|
||||||
|
w.steps = append(w.steps, oe)
|
||||||
|
C.rados_write_op_write_full(
|
||||||
|
w.op,
|
||||||
|
oe.cBuffer,
|
||||||
|
oe.cDataLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteSame write a given byte slice to the object multiple times, until
|
||||||
|
// writeLen is satisfied.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// void rados_write_op_writesame(rados_write_op_t write_op,
|
||||||
|
// const char *buffer,
|
||||||
|
// size_t data_len,
|
||||||
|
// size_t write_len,
|
||||||
|
// uint64_t offset);
|
||||||
|
func (w *WriteOp) WriteSame(b []byte, writeLen, offset uint64) {
|
||||||
|
oe := newWriteStep(b, writeLen, offset)
|
||||||
|
w.steps = append(w.steps, oe)
|
||||||
|
C.rados_write_op_writesame(
|
||||||
|
w.op,
|
||||||
|
oe.cBuffer,
|
||||||
|
oe.cDataLen,
|
||||||
|
oe.cWriteLen,
|
||||||
|
oe.cOffset)
|
||||||
|
}
|
33
vendor/github.com/ceph/go-ceph/rados/write_step.go
generated
vendored
Normal file
33
vendor/github.com/ceph/go-ceph/rados/write_step.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package rados
|
||||||
|
|
||||||
|
// #include <stdint.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type writeStep struct {
|
||||||
|
withoutUpdate
|
||||||
|
withoutFree
|
||||||
|
// the c pointer utilizes the Go byteslice data and no free is needed
|
||||||
|
|
||||||
|
// inputs:
|
||||||
|
b []byte
|
||||||
|
|
||||||
|
// arguments:
|
||||||
|
cBuffer *C.char
|
||||||
|
cDataLen C.size_t
|
||||||
|
cWriteLen C.size_t
|
||||||
|
cOffset C.uint64_t
|
||||||
|
}
|
||||||
|
|
||||||
|
func newWriteStep(b []byte, writeLen, offset uint64) *writeStep {
|
||||||
|
return &writeStep{
|
||||||
|
b: b,
|
||||||
|
cBuffer: (*C.char)(unsafe.Pointer(&b[0])),
|
||||||
|
cDataLen: C.size_t(len(b)),
|
||||||
|
cWriteLen: C.size_t(writeLen),
|
||||||
|
cOffset: C.uint64_t(offset),
|
||||||
|
}
|
||||||
|
}
|
258
vendor/github.com/ceph/go-ceph/rbd/group.go
generated
vendored
Normal file
258
vendor/github.com/ceph/go-ceph/rbd/group.go
generated
vendored
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
package rbd
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -lrbd
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rbd/librbd.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/ceph/go-ceph/internal/cutil"
|
||||||
|
"github.com/ceph/go-ceph/internal/retry"
|
||||||
|
"github.com/ceph/go-ceph/rados"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupCreate is used to create an image group.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_create(rados_ioctx_t p, const char *name);
|
||||||
|
func GroupCreate(ioctx *rados.IOContext, name string) error {
|
||||||
|
cName := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cName))
|
||||||
|
|
||||||
|
ret := C.rbd_group_create(cephIoctx(ioctx), cName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupRemove is used to remove an image group.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_remove(rados_ioctx_t p, const char *name);
|
||||||
|
func GroupRemove(ioctx *rados.IOContext, name string) error {
|
||||||
|
cName := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cName))
|
||||||
|
|
||||||
|
ret := C.rbd_group_remove(cephIoctx(ioctx), cName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupRename will rename an existing image group.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_rename(rados_ioctx_t p, const char *src_name,
|
||||||
|
// const char *dest_name);
|
||||||
|
func GroupRename(ioctx *rados.IOContext, src, dest string) error {
|
||||||
|
cSrc := C.CString(src)
|
||||||
|
defer C.free(unsafe.Pointer(cSrc))
|
||||||
|
cDest := C.CString(dest)
|
||||||
|
defer C.free(unsafe.Pointer(cDest))
|
||||||
|
|
||||||
|
ret := C.rbd_group_rename(cephIoctx(ioctx), cSrc, cDest)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupList returns a slice of image group names.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_list(rados_ioctx_t p, char *names, size_t *size);
|
||||||
|
func GroupList(ioctx *rados.IOContext) ([]string, error) {
|
||||||
|
var (
|
||||||
|
buf []byte
|
||||||
|
err error
|
||||||
|
ret C.int
|
||||||
|
)
|
||||||
|
retry.WithSizes(1024, 262144, func(size int) retry.Hint {
|
||||||
|
cSize := C.size_t(size)
|
||||||
|
buf = make([]byte, cSize)
|
||||||
|
ret = C.rbd_group_list(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||||
|
&cSize)
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.Size(int(cSize)).If(err == errRange)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// cSize is not set to the expected size when it is sufficiently large
|
||||||
|
// but ret will be set to the size in a non-error condition.
|
||||||
|
groups := cutil.SplitBuffer(buf[:ret])
|
||||||
|
return groups, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupImageAdd will add the specified image to the named group.
|
||||||
|
// An io context must be supplied for both the group and image.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_image_add(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// rados_ioctx_t image_p,
|
||||||
|
// const char *image_name);
|
||||||
|
func GroupImageAdd(groupIoctx *rados.IOContext, groupName string,
|
||||||
|
imageIoctx *rados.IOContext, imageName string) error {
|
||||||
|
|
||||||
|
cGroupName := C.CString(groupName)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
cImageName := C.CString(imageName)
|
||||||
|
defer C.free(unsafe.Pointer(cImageName))
|
||||||
|
|
||||||
|
ret := C.rbd_group_image_add(
|
||||||
|
cephIoctx(groupIoctx),
|
||||||
|
cGroupName,
|
||||||
|
cephIoctx(imageIoctx),
|
||||||
|
cImageName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupImageRemove will remove the specified image from the named group.
|
||||||
|
// An io context must be supplied for both the group and image.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_image_remove(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// rados_ioctx_t image_p,
|
||||||
|
// const char *image_name);
|
||||||
|
func GroupImageRemove(groupIoctx *rados.IOContext, groupName string,
|
||||||
|
imageIoctx *rados.IOContext, imageName string) error {
|
||||||
|
|
||||||
|
cGroupName := C.CString(groupName)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
cImageName := C.CString(imageName)
|
||||||
|
defer C.free(unsafe.Pointer(cImageName))
|
||||||
|
|
||||||
|
ret := C.rbd_group_image_remove(
|
||||||
|
cephIoctx(groupIoctx),
|
||||||
|
cGroupName,
|
||||||
|
cephIoctx(imageIoctx),
|
||||||
|
cImageName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupImageRemoveByID will remove the specified image from the named group.
|
||||||
|
// An io context must be supplied for both the group and image.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// CEPH_RBD_API int rbd_group_image_remove_by_id(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// rados_ioctx_t image_p,
|
||||||
|
// const char *image_id);
|
||||||
|
func GroupImageRemoveByID(groupIoctx *rados.IOContext, groupName string,
|
||||||
|
imageIoctx *rados.IOContext, imageID string) error {
|
||||||
|
|
||||||
|
cGroupName := C.CString(groupName)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
cid := C.CString(imageID)
|
||||||
|
defer C.free(unsafe.Pointer(cid))
|
||||||
|
|
||||||
|
ret := C.rbd_group_image_remove_by_id(
|
||||||
|
cephIoctx(groupIoctx),
|
||||||
|
cGroupName,
|
||||||
|
cephIoctx(imageIoctx),
|
||||||
|
cid)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupImageState indicates an image's state in a group.
|
||||||
|
type GroupImageState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// GroupImageStateAttached is equivalent to RBD_GROUP_IMAGE_STATE_ATTACHED
|
||||||
|
GroupImageStateAttached = GroupImageState(C.RBD_GROUP_IMAGE_STATE_ATTACHED)
|
||||||
|
// GroupImageStateIncomplete is equivalent to RBD_GROUP_IMAGE_STATE_INCOMPLETE
|
||||||
|
GroupImageStateIncomplete = GroupImageState(C.RBD_GROUP_IMAGE_STATE_INCOMPLETE)
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupImageInfo reports on images within a group.
|
||||||
|
type GroupImageInfo struct {
|
||||||
|
Name string
|
||||||
|
PoolID int64
|
||||||
|
State GroupImageState
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupImageList returns a slice of GroupImageInfo types based on the
|
||||||
|
// images that are part of the named group.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_image_list(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// rbd_group_image_info_t *images,
|
||||||
|
// size_t group_image_info_size,
|
||||||
|
// size_t *num_entries);
|
||||||
|
func GroupImageList(ioctx *rados.IOContext, name string) ([]GroupImageInfo, error) {
|
||||||
|
cName := C.CString(name)
|
||||||
|
defer C.free(unsafe.Pointer(cName))
|
||||||
|
|
||||||
|
var (
|
||||||
|
cImages []C.rbd_group_image_info_t
|
||||||
|
cSize C.size_t
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
retry.WithSizes(1024, 262144, func(size int) retry.Hint {
|
||||||
|
cSize = C.size_t(size)
|
||||||
|
cImages = make([]C.rbd_group_image_info_t, cSize)
|
||||||
|
ret := C.rbd_group_image_list(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
cName,
|
||||||
|
(*C.rbd_group_image_info_t)(unsafe.Pointer(&cImages[0])),
|
||||||
|
C.sizeof_rbd_group_image_info_t,
|
||||||
|
&cSize)
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.Size(int(cSize)).If(err == errRange)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
images := make([]GroupImageInfo, cSize)
|
||||||
|
for i := range images {
|
||||||
|
images[i].Name = C.GoString(cImages[i].name)
|
||||||
|
images[i].PoolID = int64(cImages[i].pool)
|
||||||
|
images[i].State = GroupImageState(cImages[i].state)
|
||||||
|
}
|
||||||
|
|
||||||
|
// free C memory allocated by C.rbd_group_image_list call
|
||||||
|
ret := C.rbd_group_image_list_cleanup(
|
||||||
|
(*C.rbd_group_image_info_t)(unsafe.Pointer(&cImages[0])),
|
||||||
|
C.sizeof_rbd_group_image_info_t,
|
||||||
|
cSize)
|
||||||
|
return images, getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupInfo contains the name and pool id of a RBD group.
|
||||||
|
type GroupInfo struct {
|
||||||
|
Name string
|
||||||
|
PoolID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGroup returns group info for the group this image is part of.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_get_group(rbd_image_t image, rbd_group_info_t *group_info,
|
||||||
|
// size_t group_info_size);
|
||||||
|
func (image *Image) GetGroup() (GroupInfo, error) {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return GroupInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var cgi C.rbd_group_info_t
|
||||||
|
ret := C.rbd_get_group(
|
||||||
|
image.image,
|
||||||
|
&cgi,
|
||||||
|
C.sizeof_rbd_group_info_t)
|
||||||
|
if err := getErrorIfNegative(ret); err != nil {
|
||||||
|
return GroupInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gi := GroupInfo{
|
||||||
|
Name: C.GoString(cgi.name),
|
||||||
|
PoolID: int64(cgi.pool),
|
||||||
|
}
|
||||||
|
ret = C.rbd_group_info_cleanup(&cgi, C.sizeof_rbd_group_info_t)
|
||||||
|
return gi, getError(ret)
|
||||||
|
}
|
223
vendor/github.com/ceph/go-ceph/rbd/group_snap.go
generated
vendored
Normal file
223
vendor/github.com/ceph/go-ceph/rbd/group_snap.go
generated
vendored
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
package rbd
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -lrbd
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rbd/librbd.h>
|
||||||
|
|
||||||
|
extern int snapRollbackCallback(uint64_t, uint64_t, uintptr_t);
|
||||||
|
|
||||||
|
// inline wrapper to cast uintptr_t to void*
|
||||||
|
static inline int wrap_rbd_group_snap_rollback_with_progress(
|
||||||
|
rados_ioctx_t group_p, const char *group_name,
|
||||||
|
const char *snap_name, uintptr_t arg) {
|
||||||
|
return rbd_group_snap_rollback_with_progress(
|
||||||
|
group_p, group_name, snap_name, (librbd_progress_fn_t)snapRollbackCallback, (void*)arg);
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/ceph/go-ceph/internal/callbacks"
|
||||||
|
"github.com/ceph/go-ceph/internal/retry"
|
||||||
|
"github.com/ceph/go-ceph/rados"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupSnapCreate will create a group snapshot.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_snap_create(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// const char *snap_name);
|
||||||
|
func GroupSnapCreate(ioctx *rados.IOContext, group, snap string) error {
|
||||||
|
cGroupName := C.CString(group)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
cSnapName := C.CString(snap)
|
||||||
|
defer C.free(unsafe.Pointer(cSnapName))
|
||||||
|
|
||||||
|
ret := C.rbd_group_snap_create(cephIoctx(ioctx), cGroupName, cSnapName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupSnapRemove removes an existing group snapshot.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_snap_remove(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// const char *snap_name);
|
||||||
|
func GroupSnapRemove(ioctx *rados.IOContext, group, snap string) error {
|
||||||
|
cGroupName := C.CString(group)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
cSnapName := C.CString(snap)
|
||||||
|
defer C.free(unsafe.Pointer(cSnapName))
|
||||||
|
|
||||||
|
ret := C.rbd_group_snap_remove(cephIoctx(ioctx), cGroupName, cSnapName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupSnapRename will rename an existing group snapshot.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_snap_rename(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// const char *old_snap_name,
|
||||||
|
// const char *new_snap_name);
|
||||||
|
func GroupSnapRename(ioctx *rados.IOContext, group, src, dest string) error {
|
||||||
|
cGroupName := C.CString(group)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
cOldSnapName := C.CString(src)
|
||||||
|
defer C.free(unsafe.Pointer(cOldSnapName))
|
||||||
|
cNewSnapName := C.CString(dest)
|
||||||
|
defer C.free(unsafe.Pointer(cNewSnapName))
|
||||||
|
|
||||||
|
ret := C.rbd_group_snap_rename(
|
||||||
|
cephIoctx(ioctx), cGroupName, cOldSnapName, cNewSnapName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupSnapState represents the state of a group snapshot in GroupSnapInfo.
|
||||||
|
type GroupSnapState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// GroupSnapStateIncomplete is equivalent to RBD_GROUP_SNAP_STATE_INCOMPLETE.
|
||||||
|
GroupSnapStateIncomplete = GroupSnapState(C.RBD_GROUP_SNAP_STATE_INCOMPLETE)
|
||||||
|
// GroupSnapStateComplete is equivalent to RBD_GROUP_SNAP_STATE_COMPLETE.
|
||||||
|
GroupSnapStateComplete = GroupSnapState(C.RBD_GROUP_SNAP_STATE_COMPLETE)
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupSnapInfo values are returned by GroupSnapList, representing the
|
||||||
|
// snapshots that are part of an rbd group.
|
||||||
|
type GroupSnapInfo struct {
|
||||||
|
Name string
|
||||||
|
State GroupSnapState
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupSnapList returns a slice of snapshots in a group.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_snap_list(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// rbd_group_snap_info_t *snaps,
|
||||||
|
// size_t group_snap_info_size,
|
||||||
|
// size_t *num_entries);
|
||||||
|
func GroupSnapList(ioctx *rados.IOContext, group string) ([]GroupSnapInfo, error) {
|
||||||
|
cGroupName := C.CString(group)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
|
||||||
|
var (
|
||||||
|
cSnaps []C.rbd_group_snap_info_t
|
||||||
|
cSize C.size_t
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
retry.WithSizes(1024, 262144, func(size int) retry.Hint {
|
||||||
|
cSize = C.size_t(size)
|
||||||
|
cSnaps = make([]C.rbd_group_snap_info_t, cSize)
|
||||||
|
ret := C.rbd_group_snap_list(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
cGroupName,
|
||||||
|
(*C.rbd_group_snap_info_t)(unsafe.Pointer(&cSnaps[0])),
|
||||||
|
C.sizeof_rbd_group_snap_info_t,
|
||||||
|
&cSize)
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.Size(int(cSize)).If(err == errRange)
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
snaps := make([]GroupSnapInfo, cSize)
|
||||||
|
for i := range snaps {
|
||||||
|
snaps[i].Name = C.GoString(cSnaps[i].name)
|
||||||
|
snaps[i].State = GroupSnapState(cSnaps[i].state)
|
||||||
|
}
|
||||||
|
|
||||||
|
// free C memory allocated by C.rbd_group_snap_list call
|
||||||
|
ret := C.rbd_group_snap_list_cleanup(
|
||||||
|
(*C.rbd_group_snap_info_t)(unsafe.Pointer(&cSnaps[0])),
|
||||||
|
C.sizeof_rbd_group_snap_info_t,
|
||||||
|
cSize)
|
||||||
|
return snaps, getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupSnapRollback will roll back the images in the group to that of the
|
||||||
|
// given snapshot.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_snap_rollback(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// const char *snap_name);
|
||||||
|
func GroupSnapRollback(ioctx *rados.IOContext, group, snap string) error {
|
||||||
|
cGroupName := C.CString(group)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
cSnapName := C.CString(snap)
|
||||||
|
defer C.free(unsafe.Pointer(cSnapName))
|
||||||
|
|
||||||
|
ret := C.rbd_group_snap_rollback(cephIoctx(ioctx), cGroupName, cSnapName)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupSnapRollbackCallback defines the function signature needed for the
|
||||||
|
// GroupSnapRollbackWithProgress callback.
|
||||||
|
//
|
||||||
|
// This callback will be called by GroupSnapRollbackWithProgress when it
|
||||||
|
// wishes to report progress rolling back a group snapshot.
|
||||||
|
type GroupSnapRollbackCallback func(uint64, uint64, interface{}) int
|
||||||
|
|
||||||
|
var groupSnapRollbackCallbacks = callbacks.New()
|
||||||
|
|
||||||
|
// GroupSnapRollbackWithProgress will roll back the images in the group
|
||||||
|
// to that of given snapshot. The given progress callback will be called
|
||||||
|
// to report on the progress of the snapshot rollback.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_group_snap_rollback_with_progress(rados_ioctx_t group_p,
|
||||||
|
// const char *group_name,
|
||||||
|
// const char *snap_name,
|
||||||
|
// librbd_progress_fn_t cb,
|
||||||
|
// void *cbdata);
|
||||||
|
func GroupSnapRollbackWithProgress(
|
||||||
|
ioctx *rados.IOContext, group, snap string,
|
||||||
|
cb GroupSnapRollbackCallback, data interface{}) error {
|
||||||
|
// the provided callback must be a real function
|
||||||
|
if cb == nil {
|
||||||
|
return rbdError(C.EINVAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
cGroupName := C.CString(group)
|
||||||
|
defer C.free(unsafe.Pointer(cGroupName))
|
||||||
|
cSnapName := C.CString(snap)
|
||||||
|
defer C.free(unsafe.Pointer(cSnapName))
|
||||||
|
|
||||||
|
ctx := gsnapRollbackCallbackCtx{
|
||||||
|
callback: cb,
|
||||||
|
data: data,
|
||||||
|
}
|
||||||
|
cbIndex := groupSnapRollbackCallbacks.Add(ctx)
|
||||||
|
defer diffIterateCallbacks.Remove(cbIndex)
|
||||||
|
|
||||||
|
ret := C.wrap_rbd_group_snap_rollback_with_progress(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
cGroupName,
|
||||||
|
cSnapName,
|
||||||
|
C.uintptr_t(cbIndex))
|
||||||
|
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
type gsnapRollbackCallbackCtx struct {
|
||||||
|
callback GroupSnapRollbackCallback
|
||||||
|
data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export snapRollbackCallback
|
||||||
|
func snapRollbackCallback(
|
||||||
|
offset, total C.uint64_t, index uintptr) C.int {
|
||||||
|
|
||||||
|
v := groupSnapRollbackCallbacks.Lookup(index)
|
||||||
|
ctx := v.(gsnapRollbackCallbackCtx)
|
||||||
|
return C.int(ctx.callback(uint64(offset), uint64(total), ctx.data))
|
||||||
|
}
|
235
vendor/github.com/ceph/go-ceph/rbd/mirror.go
generated
vendored
Normal file
235
vendor/github.com/ceph/go-ceph/rbd/mirror.go
generated
vendored
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
// +build !nautilus
|
||||||
|
|
||||||
|
// Initially, we're only providing mirroring related functions for octopus as
|
||||||
|
// that version of ceph deprecated a number of the functions in nautilus. If
|
||||||
|
// you need mirroring on an earlier supported version of ceph please file an
|
||||||
|
// issue in our tracker.
|
||||||
|
|
||||||
|
package rbd
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lrbd
|
||||||
|
// #include <stdlib.h>
|
||||||
|
// #include <rbd/librbd.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/ceph/go-ceph/internal/retry"
|
||||||
|
"github.com/ceph/go-ceph/rados"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MirrorMode is used to indicate an approach used for RBD mirroring.
|
||||||
|
type MirrorMode int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MirrorModeDisabled disables mirroring.
|
||||||
|
MirrorModeDisabled = MirrorMode(C.RBD_MIRROR_MODE_DISABLED)
|
||||||
|
// MirrorModeImage enables mirroring on a per-image basis.
|
||||||
|
MirrorModeImage = MirrorMode(C.RBD_MIRROR_MODE_IMAGE)
|
||||||
|
// MirrorModePool enables mirroring on all journaled images.
|
||||||
|
MirrorModePool = MirrorMode(C.RBD_MIRROR_MODE_POOL)
|
||||||
|
)
|
||||||
|
|
||||||
|
// ImageMirrorMode is used to indicate the mirroring approach for an RBD image.
|
||||||
|
type ImageMirrorMode int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ImageMirrorModeJournal uses journaling to propagate RBD images between
|
||||||
|
// ceph clusters.
|
||||||
|
ImageMirrorModeJournal = ImageMirrorMode(C.RBD_MIRROR_IMAGE_MODE_JOURNAL)
|
||||||
|
// ImageMirrorModeSnapshot uses snapshots to propagate RBD images between
|
||||||
|
// ceph clusters.
|
||||||
|
ImageMirrorModeSnapshot = ImageMirrorMode(C.RBD_MIRROR_IMAGE_MODE_SNAPSHOT)
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetMirrorMode is used to enable or disable pool level mirroring with either
|
||||||
|
// an automatic or per-image behavior.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_mode_set(rados_ioctx_t io_ctx,
|
||||||
|
// rbd_mirror_mode_t mirror_mode);
|
||||||
|
func SetMirrorMode(ioctx *rados.IOContext, mode MirrorMode) error {
|
||||||
|
ret := C.rbd_mirror_mode_set(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
C.rbd_mirror_mode_t(mode))
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMirrorMode is used to fetch the current mirroring mode for a pool.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_mode_get(rados_ioctx_t io_ctx,
|
||||||
|
// rbd_mirror_mode_t *mirror_mode);
|
||||||
|
func GetMirrorMode(ioctx *rados.IOContext) (MirrorMode, error) {
|
||||||
|
var mode C.rbd_mirror_mode_t
|
||||||
|
|
||||||
|
ret := C.rbd_mirror_mode_get(
|
||||||
|
cephIoctx(ioctx),
|
||||||
|
&mode)
|
||||||
|
if err := getError(ret); err != nil {
|
||||||
|
return MirrorModeDisabled, err
|
||||||
|
}
|
||||||
|
return MirrorMode(mode), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorEnable will enable mirroring for an image using the specified mode.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_enable2(rbd_image_t image,
|
||||||
|
// rbd_mirror_image_mode_t mode);
|
||||||
|
func (image *Image) MirrorEnable(mode ImageMirrorMode) error {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ret := C.rbd_mirror_image_enable2(image.image, C.rbd_mirror_image_mode_t(mode))
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorDisable will disable mirroring for the image.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_disable(rbd_image_t image, bool force);
|
||||||
|
func (image *Image) MirrorDisable(force bool) error {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ret := C.rbd_mirror_image_disable(image.image, C.bool(force))
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorPromote will promote the image to primary status.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_promote(rbd_image_t image, bool force);
|
||||||
|
func (image *Image) MirrorPromote(force bool) error {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ret := C.rbd_mirror_image_promote(image.image, C.bool(force))
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorDemote will demote the image to secondary status.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_demote(rbd_image_t image);
|
||||||
|
func (image *Image) MirrorDemote() error {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ret := C.rbd_mirror_image_demote(image.image)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorResync is used to manually resolve split-brain status by triggering
|
||||||
|
// resynchronization.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_resync(rbd_image_t image);
|
||||||
|
func (image *Image) MirrorResync() error {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ret := C.rbd_mirror_image_resync(image.image)
|
||||||
|
return getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorInstanceID returns a string naming the instance id for the image.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_get_instance_id(rbd_image_t image,
|
||||||
|
// char *instance_id,
|
||||||
|
// size_t *id_max_length);
|
||||||
|
func (image *Image) MirrorInstanceID() (string, error) {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
buf []byte
|
||||||
|
cSize C.size_t
|
||||||
|
)
|
||||||
|
retry.WithSizes(1024, 1<<16, func(size int) retry.Hint {
|
||||||
|
cSize = C.size_t(size)
|
||||||
|
buf = make([]byte, cSize)
|
||||||
|
ret := C.rbd_mirror_image_get_instance_id(
|
||||||
|
image.image,
|
||||||
|
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||||
|
&cSize)
|
||||||
|
err = getErrorIfNegative(ret)
|
||||||
|
return retry.Size(int(cSize)).If(err == errRange)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(buf[:cSize]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorImageState represents the mirroring state of a RBD image.
|
||||||
|
type MirrorImageState C.rbd_mirror_image_state_t
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MirrorImageDisabling is the representation of
|
||||||
|
// RBD_MIRROR_IMAGE_DISABLING from librbd.
|
||||||
|
MirrorImageDisabling = MirrorImageState(C.RBD_MIRROR_IMAGE_DISABLING)
|
||||||
|
// MirrorImageEnabled is the representation of
|
||||||
|
// RBD_MIRROR_IMAGE_ENABLED from librbd.
|
||||||
|
MirrorImageEnabled = MirrorImageState(C.RBD_MIRROR_IMAGE_ENABLED)
|
||||||
|
// MirrorImageDisabled is the representation of
|
||||||
|
// RBD_MIRROR_IMAGE_DISABLED from librbd.
|
||||||
|
MirrorImageDisabled = MirrorImageState(C.RBD_MIRROR_IMAGE_DISABLED)
|
||||||
|
)
|
||||||
|
|
||||||
|
// MirrorImageInfo represents the mirroring status information of a RBD image.
|
||||||
|
type MirrorImageInfo struct {
|
||||||
|
GlobalID string
|
||||||
|
State MirrorImageState
|
||||||
|
Primary bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMirrorImageInfo fetches the mirroring status information of a RBD image.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_get_info(rbd_image_t image,
|
||||||
|
// rbd_mirror_image_info_t *mirror_image_info,
|
||||||
|
// size_t info_size)
|
||||||
|
func (image *Image) GetMirrorImageInfo() (*MirrorImageInfo, error) {
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var cInfo C.rbd_mirror_image_info_t
|
||||||
|
|
||||||
|
ret := C.rbd_mirror_image_get_info(
|
||||||
|
image.image,
|
||||||
|
&cInfo,
|
||||||
|
C.sizeof_rbd_mirror_image_info_t)
|
||||||
|
if ret < 0 {
|
||||||
|
return nil, getError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
mii := MirrorImageInfo{
|
||||||
|
GlobalID: C.GoString(cInfo.global_id),
|
||||||
|
State: MirrorImageState(cInfo.state),
|
||||||
|
Primary: bool(cInfo.primary),
|
||||||
|
}
|
||||||
|
|
||||||
|
// free C memory allocated by C.rbd_mirror_image_get_info call
|
||||||
|
C.rbd_mirror_image_get_info_cleanup(&cInfo)
|
||||||
|
return &mii, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetImageMirrorMode fetches the mirroring approach for an RBD image.
|
||||||
|
//
|
||||||
|
// Implements:
|
||||||
|
// int rbd_mirror_image_get_mode(rbd_image_t image, rbd_mirror_image_mode_t *mode);
|
||||||
|
func (image *Image) GetImageMirrorMode() (ImageMirrorMode, error) {
|
||||||
|
var mode C.rbd_mirror_image_mode_t
|
||||||
|
if err := image.validate(imageIsOpen); err != nil {
|
||||||
|
return ImageMirrorMode(mode), err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := C.rbd_mirror_image_get_mode(image.image, &mode)
|
||||||
|
return ImageMirrorMode(mode), getError(ret)
|
||||||
|
}
|
6
vendor/github.com/ceph/go-ceph/rbd/rbd.go
generated
vendored
6
vendor/github.com/ceph/go-ceph/rbd/rbd.go
generated
vendored
@ -95,7 +95,11 @@ type TrashInfo struct {
|
|||||||
|
|
||||||
// cephIoctx returns a ceph rados_ioctx_t given a go-ceph rados IOContext.
|
// cephIoctx returns a ceph rados_ioctx_t given a go-ceph rados IOContext.
|
||||||
func cephIoctx(radosIoctx *rados.IOContext) C.rados_ioctx_t {
|
func cephIoctx(radosIoctx *rados.IOContext) C.rados_ioctx_t {
|
||||||
return C.rados_ioctx_t(radosIoctx.Pointer())
|
p := radosIoctx.Pointer()
|
||||||
|
if p == nil {
|
||||||
|
panic("invalid IOContext pointer")
|
||||||
|
}
|
||||||
|
return C.rados_ioctx_t(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// test if a bit is set in the given value
|
// test if a bit is set in the given value
|
||||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -26,7 +26,7 @@ github.com/aws/aws-sdk-go/service/ec2
|
|||||||
github.com/beorn7/perks/quantile
|
github.com/beorn7/perks/quantile
|
||||||
# github.com/blang/semver v3.5.1+incompatible
|
# github.com/blang/semver v3.5.1+incompatible
|
||||||
github.com/blang/semver
|
github.com/blang/semver
|
||||||
# github.com/ceph/go-ceph v0.7.0
|
# github.com/ceph/go-ceph v0.8.0
|
||||||
github.com/ceph/go-ceph/cephfs/admin
|
github.com/ceph/go-ceph/cephfs/admin
|
||||||
github.com/ceph/go-ceph/internal/callbacks
|
github.com/ceph/go-ceph/internal/callbacks
|
||||||
github.com/ceph/go-ceph/internal/cutil
|
github.com/ceph/go-ceph/internal/cutil
|
||||||
|
Loading…
Reference in New Issue
Block a user