mirror of https://github.com/ceph/go-ceph
rbd: add GroupSnapRollbackWithProgress function
* Add GroupSnapRollbackWithProgress implementing rbd_group_snap_rollback_with_progress This has supporting code basically the same as our other existing callback functions. Tests too. Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
8e6dfe4259
commit
1286e0d4d0
|
@ -2,14 +2,26 @@ 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"
|
||||
)
|
||||
|
@ -147,3 +159,65 @@ func GroupSnapRollback(ioctx *rados.IOContext, group, snap string) error {
|
|||
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))
|
||||
}
|
||||
|
|
|
@ -153,6 +153,69 @@ func TestGroupSnapshots(t *testing.T) {
|
|||
err = GroupSnapRemove(ioctx, gname, snapname)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("groupSnapRollbackWithProgress", func(t *testing.T) {
|
||||
img, err := OpenImage(ioctx, name1, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
_, err = img.WriteAt([]byte("SAY CHEESE"), 0)
|
||||
assert.NoError(t, err)
|
||||
_, err = img.WriteAt([]byte("AND SMILE_"), 10240)
|
||||
assert.NoError(t, err)
|
||||
err = img.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
snapname := "snap2r"
|
||||
err = GroupSnapCreate(ioctx, gname, snapname)
|
||||
assert.NoError(t, err)
|
||||
|
||||
img, err = OpenImage(ioctx, name1, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
_, err = img.WriteAt([]byte("GOODBYE WORLD"), 0)
|
||||
assert.NoError(t, err)
|
||||
_, err = img.WriteAt([]byte("_THIS_IS_ALL_"), 10240)
|
||||
assert.NoError(t, err)
|
||||
_, err = img.WriteAt([]byte("I_HAVE_TO_SAY"), 11240)
|
||||
assert.NoError(t, err)
|
||||
err = img.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
img, err = OpenImage(ioctx, name2, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
_, err = img.WriteAt([]byte("3333333333333"), 0)
|
||||
assert.NoError(t, err)
|
||||
err = img.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
cc := 0
|
||||
cb := func(offset, total uint64, v interface{}) int {
|
||||
cc++
|
||||
val := v.(int)
|
||||
assert.Equal(t, 0, val)
|
||||
assert.Equal(t, uint64(1), total)
|
||||
return 0
|
||||
}
|
||||
err = GroupSnapRollbackWithProgress(ioctx, gname, snapname, cb, 0)
|
||||
assert.NoError(t, err)
|
||||
assert.GreaterOrEqual(t, cc, 2)
|
||||
|
||||
b := make([]byte, 8)
|
||||
img, err = OpenImage(ioctx, name1, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
_, err = img.ReadAt(b, 0)
|
||||
assert.NoError(t, err)
|
||||
err = img.Close()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("SAY CHEE"), b)
|
||||
|
||||
img, err = OpenImage(ioctx, name2, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
_, err = img.ReadAt(b, 0)
|
||||
assert.NoError(t, err)
|
||||
err = img.Close()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), b)
|
||||
|
||||
err = GroupSnapRemove(ioctx, gname, snapname)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("invalidIOContext", func(t *testing.T) {
|
||||
assert.Panics(t, func() {
|
||||
|
@ -170,5 +233,13 @@ func TestGroupSnapshots(t *testing.T) {
|
|||
assert.Panics(t, func() {
|
||||
GroupSnapRollback(nil, gname, "foo")
|
||||
})
|
||||
assert.Panics(t, func() {
|
||||
cb := func(o, t uint64, v interface{}) int { return 0 }
|
||||
GroupSnapRollbackWithProgress(nil, gname, "foo", cb, nil)
|
||||
})
|
||||
})
|
||||
t.Run("invalidCallback", func(t *testing.T) {
|
||||
err := GroupSnapRollbackWithProgress(ioctx, gname, "foo", nil, nil)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue