typedef void *image_ctx_t;
typedef void *completion_t;
typedef void (*callback_t)(completion_t cb, void *arg);
- typedef void (*copy_progress_fn_t)(uint64_t offset, uint64_t src_size,
- void *data);
typedef struct {
uint64_t id;
typedef rbd_image_info_t image_info_t;
+class ProgressContext
+{
+public:
+ virtual ~ProgressContext();
+ virtual int update_progress(uint64_t offset, uint64_t src_size) = 0;
+};
+
class RBD
{
public:
int stat(image_info_t &info, size_t infosize);
int copy(IoCtx& dest_io_ctx, const char *destname);
int copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
- copy_progress_fn_t fn, void *data);
+ ProgressContext &prog_ctx);
/* snapshots */
int snap_list(std::vector<snap_info_t>& snaps);
}
struct CopyProgressCtx {
+ CopyProgressCtx(ProgressContext &p)
+ : prog_ctx(p)
+ {
+ }
ImageCtx *destictx;
uint64_t src_size;
- copy_progress_fn_t fn;
- void *data;
+ ProgressContext &prog_ctx;
};
int do_copy_extent(uint64_t offset, size_t len, const char *buf, void *data)
return ret;
}
}
- if (cp->fn)
- cp->fn(offset, cp->src_size, cp->data);
- return 0;
+ return cp->prog_ctx.update_progress(offset, cp->src_size);
+}
+
+ProgressContext::~ProgressContext()
+{
}
+class NoOpProgressContext : public librbd::ProgressContext
+{
+public:
+ NoOpProgressContext()
+ {
+ }
+ int update_progress(uint64_t offset, uint64_t src_size)
+ {
+ return 0;
+ }
+};
+
+class CProgressContext : public librbd::ProgressContext
+{
+public:
+ CProgressContext(librbd_copy_progress_fn_t fn, void *data)
+ : m_fn(fn), m_data(data)
+ {
+ }
+ int update_progress(uint64_t offset, uint64_t src_size)
+ {
+ return m_fn(offset, src_size, m_data);
+ }
+private:
+ librbd_copy_progress_fn_t m_fn;
+ void *m_data;
+};
+
int copy(ImageCtx& ictx, IoCtx& dest_md_ctx, const char *destname,
- copy_progress_fn_t fn, void *data)
+ ProgressContext &prog_ctx)
{
CephContext *cct = dest_md_ctx.cct();
- CopyProgressCtx cp;
+ CopyProgressCtx cp(prog_ctx);
uint64_t src_size = ictx.get_image_size();
cp.destictx = new librbd::ImageCtx(destname, dest_md_ctx);
cp.src_size = src_size;
- cp.fn = fn;
- cp.data = data;
r = open_image(dest_md_ctx, cp.destictx, destname, NULL);
if (r < 0) {
lderr(cct) << "failed to read newly created header" << dendl;
}
r = read_iterate(&ictx, 0, src_size, do_copy_extent, &cp);
- if ((r >= 0) && (cp.fn)) {
- cp.fn(cp.src_size, cp.src_size, cp.data);
+
+ if (r >= 0) {
+ prog_ctx.update_progress(cp.src_size, cp.src_size);
}
close_image(cp.destictx);
return r;
int Image::copy(IoCtx& dest_io_ctx, const char *destname)
{
ImageCtx *ictx = (ImageCtx *)ctx;
- int r = librbd::copy(*ictx, dest_io_ctx, destname, NULL, NULL);
+ librbd::NoOpProgressContext prog_ctx;
+ int r = librbd::copy(*ictx, dest_io_ctx, destname, prog_ctx);
return r;
}
int Image::copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
- copy_progress_fn_t fn, void *data)
+ librbd::ProgressContext &pctx)
{
ImageCtx *ictx = (ImageCtx *)ctx;
- int r = librbd::copy(*ictx, dest_io_ctx, destname, fn, data);
+ int r = librbd::copy(*ictx, dest_io_ctx, destname, pctx);
return r;
}
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
librados::IoCtx dest_io_ctx;
librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
- return librbd::copy(*ictx, dest_io_ctx, destname, NULL, NULL);
+ librbd::NoOpProgressContext prog_ctx;
+ return librbd::copy(*ictx, dest_io_ctx, destname, prog_ctx);
}
extern "C" int rbd_copy_with_progress(rbd_image_t image, rados_ioctx_t dest_p,
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
librados::IoCtx dest_io_ctx;
librados::IoCtx::from_rados_ioctx_t(dest_p, dest_io_ctx);
- return librbd::copy(*ictx, dest_io_ctx, destname, fn, data);
+ librbd::CProgressContext prog_ctx(fn, data);
+ int ret = librbd::copy(*ictx, dest_io_ctx, destname, prog_ctx);
+ return ret;
}
extern "C" int rbd_rename(rados_ioctx_t src_p, const char *srcname, const char *destname)
#include <unistd.h>
#define TEST_IMAGE "testimg"
+#define TEST_IMAGE2 "testimg2"
#define TEST_POOL "librbdtest"
#define TEST_SNAP "testsnap"
#define TEST_IO_SIZE 512
test_ls_snaps(image, 0);
}
+void test_rbd_copy(rados_ioctx_t io_ctx, rbd_image_t image)
+{
+ int ret;
+ ret = rbd_copy(image, io_ctx, TEST_IMAGE2);
+ if (ret < 0) {
+ fprintf(stderr, "rbd_copy returned %d!\n", ret);
+ abort();
+ }
+}
+
+static int print_progress_percent(uint64_t offset, uint64_t src_size,
+ void *data)
+{
+ float percent = ((float)offset * 100) / src_size;
+ printf("%3.2f%% done\n", percent);
+ return 0;
+}
+
+void test_rbd_copy_with_progress(rados_ioctx_t io_ctx, rbd_image_t image)
+{
+ int ret;
+ ret = rbd_copy_with_progress(image, io_ctx, TEST_IMAGE2,
+ print_progress_percent, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "rbd_copy_with_progress returned %d!\n", ret);
+ abort();
+ }
+}
+
int main(int argc, const char **argv)
{
rados_t cluster;
test_delete(io_ctx, TEST_IMAGE "1");
test_ls(io_ctx, 0);
+ test_rbd_copy(io_ctx, image);
+ test_delete(io_ctx, TEST_IMAGE2);
+ test_rbd_copy_with_progress(io_ctx, image);
+
rados_ioctx_destroy(io_ctx);
rados_shutdown(cluster);
}
}
-static void print_progress_percent(uint64_t offset, uint64_t src_size,
- void *data)
+class PrintProgress : public librbd::ProgressContext
{
- float percent = ((float)offset * 100) / src_size;
- printf("%3.2f%% done\n", percent);
-}
+public:
+ int update_progress(uint64_t offset, uint64_t src_size)
+ {
+ float percent = ((float)offset * 100) / src_size;
+ printf("%3.2f%% done\n", percent);
+ return 0;
+ }
+};
+
void test_rbd_copy_with_progress(librados::IoCtx& io_ctx, librbd::Image& image)
{
int ret;
- ret = image.copy_with_progress(io_ctx, TEST_IMAGE2,
- print_progress_percent, NULL);
+ PrintProgress prog_ctx;
+ ret = image.copy_with_progress(io_ctx, TEST_IMAGE2, prog_ctx);
if (ret < 0) {
fprintf(stderr, "image.copy returned %d!\n", ret);
abort();