From 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 20:24:20 +0200 Subject: Adding upstream version 14.2.21. Signed-off-by: Daniel Baumann --- src/test/librados_test_stub/LibradosTestStub.cc | 1498 +++++++++++++++++++++++ 1 file changed, 1498 insertions(+) create mode 100644 src/test/librados_test_stub/LibradosTestStub.cc (limited to 'src/test/librados_test_stub/LibradosTestStub.cc') diff --git a/src/test/librados_test_stub/LibradosTestStub.cc b/src/test/librados_test_stub/LibradosTestStub.cc new file mode 100644 index 00000000..f8464250 --- /dev/null +++ b/src/test/librados_test_stub/LibradosTestStub.cc @@ -0,0 +1,1498 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "test/librados_test_stub/LibradosTestStub.h" +#include "include/rados/librados.hpp" +#include "include/stringify.h" +#include "common/ceph_argparse.h" +#include "common/ceph_context.h" +#include "common/common_init.h" +#include "common/config.h" +#include "common/debug.h" +#include "common/snap_types.h" +#include "librados/AioCompletionImpl.h" +#include "log/Log.h" +#include "test/librados_test_stub/TestClassHandler.h" +#include "test/librados_test_stub/TestIoCtxImpl.h" +#include "test/librados_test_stub/TestRadosClient.h" +#include "test/librados_test_stub/TestMemCluster.h" +#include "test/librados_test_stub/TestMemRadosClient.h" +#include "objclass/objclass.h" +#include "osd/osd_types.h" +#include +#include +#include +#include +#include +#include +#include "include/ceph_assert.h" +#include "include/compat.h" + +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_rados + +namespace librados { + +MockTestMemIoCtxImpl &get_mock_io_ctx(IoCtx &ioctx) { + MockTestMemIoCtxImpl **mock = + reinterpret_cast(&ioctx); + return **mock; +} + +} // namespace librados + +namespace librados_test_stub { + +TestClusterRef &cluster() { + static TestClusterRef s_cluster; + return s_cluster; +} + +void set_cluster(TestClusterRef cluster_ref) { + cluster() = cluster_ref; +} + +TestClusterRef get_cluster() { + auto &cluster_ref = cluster(); + if (cluster_ref.get() == nullptr) { + cluster_ref.reset(new librados::TestMemCluster()); + } + return cluster_ref; +} + +} // namespace librados_test_stub + +namespace { + +librados::TestClassHandler *get_class_handler() { + static boost::shared_ptr s_class_handler; + if (!s_class_handler) { + s_class_handler.reset(new librados::TestClassHandler()); + s_class_handler->open_all_classes(); + } + return s_class_handler.get(); +} + +void do_out_buffer(bufferlist& outbl, char **outbuf, size_t *outbuflen) { + if (outbuf) { + if (outbl.length() > 0) { + *outbuf = (char *)malloc(outbl.length()); + memcpy(*outbuf, outbl.c_str(), outbl.length()); + } else { + *outbuf = NULL; + } + } + if (outbuflen) { + *outbuflen = outbl.length(); + } +} + +void do_out_buffer(string& outbl, char **outbuf, size_t *outbuflen) { + if (outbuf) { + if (outbl.length() > 0) { + *outbuf = (char *)malloc(outbl.length()); + memcpy(*outbuf, outbl.c_str(), outbl.length()); + } else { + *outbuf = NULL; + } + } + if (outbuflen) { + *outbuflen = outbl.length(); + } +} + +librados::TestRadosClient *create_rados_client() { + CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT); + CephContext *cct = common_preinit(iparams, CODE_ENVIRONMENT_LIBRARY, 0); + cct->_conf.parse_env(cct->get_module_type()); + cct->_conf.apply_changes(nullptr); + cct->_log->start(); + + auto rados_client = + librados_test_stub::get_cluster()->create_rados_client(cct); + cct->put(); + return rados_client; +} + +} // anonymous namespace + +extern "C" int rados_aio_create_completion(void *cb_arg, + rados_callback_t cb_complete, + rados_callback_t cb_safe, + rados_completion_t *pc) +{ + librados::AioCompletionImpl *c = new librados::AioCompletionImpl; + if (cb_complete) { + c->set_complete_callback(cb_arg, cb_complete); + } + if (cb_safe) { + c->set_safe_callback(cb_arg, cb_safe); + } + *pc = c; + return 0; +} + +extern "C" int rados_aio_get_return_value(rados_completion_t c) { + return reinterpret_cast(c)->get_return_value(); +} + +extern "C" rados_config_t rados_cct(rados_t cluster) +{ + librados::TestRadosClient *client = + reinterpret_cast(cluster); + return reinterpret_cast(client->cct()); +} + +extern "C" int rados_conf_set(rados_t cluster, const char *option, + const char *value) { + librados::TestRadosClient *impl = + reinterpret_cast(cluster); + CephContext *cct = impl->cct(); + return cct->_conf.set_val(option, value); +} + +extern "C" int rados_conf_parse_env(rados_t cluster, const char *var) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + auto& conf = client->cct()->_conf; + conf.parse_env(client->cct()->get_module_type(), var); + conf.apply_changes(NULL); + return 0; +} + +extern "C" int rados_conf_read_file(rados_t cluster, const char *path) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + auto& conf = client->cct()->_conf; + int ret = conf.parse_config_files(path, NULL, 0); + if (ret == 0) { + conf.parse_env(client->cct()->get_module_type()); + conf.apply_changes(NULL); + conf.complain_about_parse_errors(client->cct()); + } else if (ret == -ENOENT) { + // ignore missing client config + return 0; + } + return ret; +} + +extern "C" int rados_connect(rados_t cluster) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + return client->connect(); +} + +extern "C" int rados_create(rados_t *cluster, const char * const id) { + *cluster = create_rados_client(); + return 0; +} + +extern "C" int rados_create_with_context(rados_t *cluster, + rados_config_t cct_) { + auto cct = reinterpret_cast(cct_); + *cluster = librados_test_stub::get_cluster()->create_rados_client(cct); + return 0; +} + +extern "C" rados_config_t rados_ioctx_cct(rados_ioctx_t ioctx) +{ + librados::TestIoCtxImpl *ctx = + reinterpret_cast(ioctx); + return reinterpret_cast(ctx->get_rados_client()->cct()); +} + +extern "C" int rados_ioctx_create(rados_t cluster, const char *pool_name, + rados_ioctx_t *ioctx) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + + int64_t pool_id = client->pool_lookup(pool_name); + if (pool_id < 0) { + return static_cast(pool_id); + } + + *ioctx = reinterpret_cast( + client->create_ioctx(pool_id, pool_name)); + return 0; +} + +extern "C" int rados_ioctx_create2(rados_t cluster, int64_t pool_id, + rados_ioctx_t *ioctx) +{ + librados::TestRadosClient *client = + reinterpret_cast(cluster); + + std::list > pools; + int r = client->pool_list(pools); + if (r < 0) { + return r; + } + + for (std::list >::iterator it = + pools.begin(); it != pools.end(); ++it) { + if (it->first == pool_id) { + *ioctx = reinterpret_cast( + client->create_ioctx(pool_id, it->second)); + return 0; + } + } + return -ENOENT; +} + +extern "C" void rados_ioctx_destroy(rados_ioctx_t io) { + librados::TestIoCtxImpl *ctx = + reinterpret_cast(io); + ctx->put(); +} + +extern "C" rados_t rados_ioctx_get_cluster(rados_ioctx_t io) { + librados::TestIoCtxImpl *ctx = + reinterpret_cast(io); + return reinterpret_cast(ctx->get_rados_client()); +} + +extern "C" int rados_mon_command(rados_t cluster, const char **cmd, + size_t cmdlen, const char *inbuf, + size_t inbuflen, char **outbuf, + size_t *outbuflen, char **outs, + size_t *outslen) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + + vector cmdvec; + for (size_t i = 0; i < cmdlen; i++) { + cmdvec.push_back(cmd[i]); + } + + bufferlist inbl; + inbl.append(inbuf, inbuflen); + + bufferlist outbl; + string outstring; + int ret = client->mon_command(cmdvec, inbl, &outbl, &outstring); + + do_out_buffer(outbl, outbuf, outbuflen); + do_out_buffer(outstring, outs, outslen); + return ret; +} + +extern "C" int rados_nobjects_list_open(rados_ioctx_t io, + rados_list_ctx_t *ctx) { + librados::TestIoCtxImpl *io_ctx = + reinterpret_cast(io); + librados::TestRadosClient *client = io_ctx->get_rados_client(); + + std::list *list = + new std::list(); + + client->object_list(io_ctx->get_id(), list); + list->push_front(librados::TestRadosClient::Object()); + *ctx = reinterpret_cast(list); + return 0; +} + +extern "C" int rados_nobjects_list_next(rados_list_ctx_t ctx, + const char **entry, + const char **key, + const char **nspace) { + std::list *list = + reinterpret_cast *>(ctx); + if (!list->empty()) { + list->pop_front(); + } + if (list->empty()) { + return -ENOENT; + } + + librados::TestRadosClient::Object &obj = list->front(); + if (entry != NULL) { + *entry = obj.oid.c_str(); + } + if (key != NULL) { + *key = obj.locator.c_str(); + } + if (nspace != NULL) { + *nspace = obj.nspace.c_str(); + } + return 0; +} + +extern "C" void rados_nobjects_list_close(rados_list_ctx_t ctx) { + std::list *list = + reinterpret_cast *>(ctx); + delete list; +} + +extern "C" int rados_pool_create(rados_t cluster, const char *pool_name) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + return client->pool_create(pool_name); +} + +extern "C" int rados_pool_delete(rados_t cluster, const char *pool_name) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + return client->pool_delete(pool_name); +} + +extern "C" void rados_shutdown(rados_t cluster) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + client->put(); +} + +extern "C" int rados_wait_for_latest_osdmap(rados_t cluster) { + librados::TestRadosClient *client = + reinterpret_cast(cluster); + return client->wait_for_latest_osdmap(); +} + +namespace librados { + +void AioCompletion::release() { + AioCompletionImpl *c = reinterpret_cast(pc); + c->release(); + delete this; +} + +IoCtx::IoCtx() : io_ctx_impl(NULL) { +} + +IoCtx::~IoCtx() { + close(); +} + +IoCtx::IoCtx(const IoCtx& rhs) { + io_ctx_impl = rhs.io_ctx_impl; + if (io_ctx_impl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->get(); + } +} + +IoCtx::IoCtx(IoCtx&& rhs) noexcept : io_ctx_impl(std::exchange(rhs.io_ctx_impl, nullptr)) +{ +} + +IoCtx& IoCtx::operator=(const IoCtx& rhs) { + if (io_ctx_impl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->put(); + } + + io_ctx_impl = rhs.io_ctx_impl; + if (io_ctx_impl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->get(); + } + return *this; +} + +librados::IoCtx& librados::IoCtx::operator=(IoCtx&& rhs) noexcept +{ + if (io_ctx_impl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->put(); + } + + io_ctx_impl = std::exchange(rhs.io_ctx_impl, nullptr); + return *this; +} + +int IoCtx::aio_flush() { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->aio_flush(); + return 0; +} + +int IoCtx::aio_flush_async(AioCompletion *c) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->aio_flush_async(c->pc); + return 0; +} + +int IoCtx::aio_notify(const std::string& oid, AioCompletion *c, bufferlist& bl, + uint64_t timeout_ms, bufferlist *pbl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->aio_notify(oid, c->pc, bl, timeout_ms, pbl); + return 0; +} + +int IoCtx::aio_operate(const std::string& oid, AioCompletion *c, + ObjectReadOperation *op, bufferlist *pbl) { + return aio_operate(oid, c, op, 0, pbl); +} + +int IoCtx::aio_operate(const std::string& oid, AioCompletion *c, + ObjectReadOperation *op, int flags, + bufferlist *pbl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + TestObjectOperationImpl *ops = reinterpret_cast(op->impl); + return ctx->aio_operate_read(oid, *ops, c->pc, flags, pbl); +} + +int IoCtx::aio_operate(const std::string& oid, AioCompletion *c, + ObjectReadOperation *op, int flags, + bufferlist *pbl, const blkin_trace_info *trace_info) { + return aio_operate(oid, c, op, flags, pbl); +} + +int IoCtx::aio_operate(const std::string& oid, AioCompletion *c, + ObjectWriteOperation *op) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + TestObjectOperationImpl *ops = reinterpret_cast(op->impl); + return ctx->aio_operate(oid, *ops, c->pc, NULL, 0); +} + +int IoCtx::aio_operate(const std::string& oid, AioCompletion *c, + ObjectWriteOperation *op, snap_t seq, + std::vector& snaps, int flags, + const blkin_trace_info *trace_info) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + TestObjectOperationImpl *ops = reinterpret_cast(op->impl); + + std::vector snv; + snv.resize(snaps.size()); + for (size_t i = 0; i < snaps.size(); ++i) + snv[i] = snaps[i]; + SnapContext snapc(seq, snv); + + return ctx->aio_operate(oid, *ops, c->pc, &snapc, flags); +} + +int IoCtx::aio_operate(const std::string& oid, AioCompletion *c, + ObjectWriteOperation *op, snap_t seq, + std::vector& snaps) { + return aio_operate(oid, c, op, seq, snaps, 0, nullptr); +} + +int IoCtx::aio_operate(const std::string& oid, AioCompletion *c, + ObjectWriteOperation *op, snap_t seq, + std::vector& snaps, + const blkin_trace_info *trace_info) { + return aio_operate(oid, c, op, seq, snaps, 0, trace_info); +} + +int IoCtx::aio_remove(const std::string& oid, AioCompletion *c) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->aio_remove(oid, c->pc); +} + +int IoCtx::aio_remove(const std::string& oid, AioCompletion *c, int flags) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->aio_remove(oid, c->pc, flags); +} + +int IoCtx::aio_watch(const std::string& o, AioCompletion *c, uint64_t *handle, + librados::WatchCtx2 *watch_ctx) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->aio_watch(o, c->pc, handle, watch_ctx); +} + +int IoCtx::aio_unwatch(uint64_t handle, AioCompletion *c) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->aio_unwatch(handle, c->pc); +} + +config_t IoCtx::cct() { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return reinterpret_cast(ctx->get_rados_client()->cct()); +} + +void IoCtx::close() { + if (io_ctx_impl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->put(); + } + io_ctx_impl = NULL; +} + +int IoCtx::create(const std::string& oid, bool exclusive) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::create, _1, _2, exclusive)); +} + +void IoCtx::dup(const IoCtx& rhs) { + close(); + TestIoCtxImpl *ctx = reinterpret_cast(rhs.io_ctx_impl); + io_ctx_impl = reinterpret_cast(ctx->clone()); +} + +int IoCtx::exec(const std::string& oid, const char *cls, const char *method, + bufferlist& inbl, bufferlist& outbl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::exec, _1, _2, get_class_handler(), cls, + method, inbl, &outbl, ctx->get_snap_context())); +} + +void IoCtx::from_rados_ioctx_t(rados_ioctx_t p, IoCtx &io) { + TestIoCtxImpl *ctx = reinterpret_cast(p); + ctx->get(); + + io.close(); + io.io_ctx_impl = reinterpret_cast(ctx); +} + +uint64_t IoCtx::get_instance_id() const { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->get_instance_id(); +} + +int64_t IoCtx::get_id() { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->get_id(); +} + +uint64_t IoCtx::get_last_version() { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->get_last_version(); +} + +std::string IoCtx::get_pool_name() { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->get_pool_name(); +} + +int IoCtx::list_snaps(const std::string& o, snap_set_t *out_snaps) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + o, boost::bind(&TestIoCtxImpl::list_snaps, _1, _2, out_snaps)); +} + +int IoCtx::list_watchers(const std::string& o, + std::list *out_watchers) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + o, boost::bind(&TestIoCtxImpl::list_watchers, _1, _2, out_watchers)); +} + +int IoCtx::notify(const std::string& o, uint64_t ver, bufferlist& bl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->notify(o, bl, 0, NULL); +} + +int IoCtx::notify2(const std::string& o, bufferlist& bl, + uint64_t timeout_ms, bufferlist *pbl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->notify(o, bl, timeout_ms, pbl); +} + +void IoCtx::notify_ack(const std::string& o, uint64_t notify_id, + uint64_t handle, bufferlist& bl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->notify_ack(o, notify_id, handle, bl); +} + +int IoCtx::omap_get_vals(const std::string& oid, + const std::string& start_after, + uint64_t max_return, + std::map *out_vals) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::omap_get_vals, _1, _2, start_after, "", + max_return, out_vals)); +} + +int IoCtx::operate(const std::string& oid, ObjectWriteOperation *op) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + TestObjectOperationImpl *ops = reinterpret_cast(op->impl); + return ctx->operate(oid, *ops); +} + +int IoCtx::operate(const std::string& oid, ObjectReadOperation *op, + bufferlist *pbl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + TestObjectOperationImpl *ops = reinterpret_cast(op->impl); + return ctx->operate_read(oid, *ops, pbl); +} + +int IoCtx::read(const std::string& oid, bufferlist& bl, size_t len, + uint64_t off) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::read, _1, _2, len, off, &bl)); +} + +int IoCtx::remove(const std::string& oid) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::remove, _1, _2, ctx->get_snap_context())); +} + +int IoCtx::selfmanaged_snap_create(uint64_t *snapid) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->selfmanaged_snap_create(snapid); +} + +void IoCtx::aio_selfmanaged_snap_create(uint64_t *snapid, AioCompletion* c) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->aio_selfmanaged_snap_create(snapid, c->pc); +} + +int IoCtx::selfmanaged_snap_remove(uint64_t snapid) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->selfmanaged_snap_remove(snapid); +} + +void IoCtx::aio_selfmanaged_snap_remove(uint64_t snapid, AioCompletion* c) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->aio_selfmanaged_snap_remove(snapid, c->pc); +} + +int IoCtx::selfmanaged_snap_rollback(const std::string& oid, + uint64_t snapid) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->selfmanaged_snap_rollback(oid, snapid); +} + +int IoCtx::selfmanaged_snap_set_write_ctx(snap_t seq, + std::vector& snaps) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->selfmanaged_snap_set_write_ctx(seq, snaps); +} + +void IoCtx::snap_set_read(snap_t seq) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->set_snap_read(seq); +} + +int IoCtx::sparse_read(const std::string& oid, std::map& m, + bufferlist& bl, size_t len, uint64_t off) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::sparse_read, _1, _2, off, len, &m, &bl)); +} + +int IoCtx::stat(const std::string& oid, uint64_t *psize, time_t *pmtime) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::stat, _1, _2, psize, pmtime)); +} + +int IoCtx::tmap_update(const std::string& oid, bufferlist& cmdbl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::tmap_update, _1, _2, cmdbl)); +} + +int IoCtx::trunc(const std::string& oid, uint64_t off) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::truncate, _1, _2, off, + ctx->get_snap_context())); +} + +int IoCtx::unwatch2(uint64_t handle) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->unwatch(handle); +} + +int IoCtx::unwatch(const std::string& o, uint64_t handle) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->unwatch(handle); +} + +int IoCtx::watch(const std::string& o, uint64_t ver, uint64_t *handle, + librados::WatchCtx *wctx) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->watch(o, handle, wctx, NULL); +} + +int IoCtx::watch2(const std::string& o, uint64_t *handle, + librados::WatchCtx2 *wctx) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->watch(o, handle, NULL, wctx); +} + +int IoCtx::write(const std::string& oid, bufferlist& bl, size_t len, + uint64_t off) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::write, _1, _2, bl, len, off, + ctx->get_snap_context())); +} + +int IoCtx::write_full(const std::string& oid, bufferlist& bl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::write_full, _1, _2, bl, + ctx->get_snap_context())); +} + +int IoCtx::writesame(const std::string& oid, bufferlist& bl, size_t len, + uint64_t off) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::writesame, _1, _2, bl, len, off, + ctx->get_snap_context())); +} + +int IoCtx::cmpext(const std::string& oid, uint64_t off, bufferlist& cmp_bl) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->execute_operation( + oid, boost::bind(&TestIoCtxImpl::cmpext, _1, _2, off, cmp_bl)); +} + +int IoCtx::application_enable(const std::string& app_name, bool force) { + return 0; +} + +int IoCtx::application_enable_async(const std::string& app_name, + bool force, PoolAsyncCompletion *c) { + return -EOPNOTSUPP; +} + +int IoCtx::application_list(std::set *app_names) { + return -EOPNOTSUPP; +} + +int IoCtx::application_metadata_get(const std::string& app_name, + const std::string &key, + std::string *value) { + return -EOPNOTSUPP; +} + +int IoCtx::application_metadata_set(const std::string& app_name, + const std::string &key, + const std::string& value) { + return -EOPNOTSUPP; +} + +int IoCtx::application_metadata_remove(const std::string& app_name, + const std::string &key) { + return -EOPNOTSUPP; +} + +int IoCtx::application_metadata_list(const std::string& app_name, + std::map *values) { + return -EOPNOTSUPP; +} + +void IoCtx::set_namespace(const std::string& nspace) { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + ctx->set_namespace(nspace); +} + +std::string IoCtx::get_namespace() const { + TestIoCtxImpl *ctx = reinterpret_cast(io_ctx_impl); + return ctx->get_namespace(); +} + +static int save_operation_result(int result, int *pval) { + if (pval != NULL) { + *pval = result; + } + return result; +} + +ObjectOperation::ObjectOperation() { + TestObjectOperationImpl *o = new TestObjectOperationImpl(); + o->get(); + impl = reinterpret_cast(o); +} + +ObjectOperation::~ObjectOperation() { + TestObjectOperationImpl *o = reinterpret_cast(impl); + if (o) { + o->put(); + o = NULL; + } +} + +void ObjectOperation::assert_exists() { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::assert_exists, _1, _2)); +} + +void ObjectOperation::exec(const char *cls, const char *method, + bufferlist& inbl) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::exec, _1, _2, + get_class_handler(), cls, method, inbl, _3, _4)); +} + +void ObjectOperation::set_op_flags2(int flags) { +} + +size_t ObjectOperation::size() { + TestObjectOperationImpl *o = reinterpret_cast(impl); + return o->ops.size(); +} + +void ObjectOperation::cmpext(uint64_t off, const bufferlist& cmp_bl, + int *prval) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::cmpext, _1, _2, off, cmp_bl); + if (prval != NULL) { + op = boost::bind(save_operation_result, + boost::bind(op, _1, _2, _3, _4), prval); + } + o->ops.push_back(op); +} + +void ObjectReadOperation::list_snaps(snap_set_t *out_snaps, int *prval) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + + ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::list_snaps, _1, _2, + out_snaps); + if (prval != NULL) { + op = boost::bind(save_operation_result, + boost::bind(op, _1, _2, _3, _4), prval); + } + o->ops.push_back(op); +} + +void ObjectReadOperation::list_watchers(std::list *out_watchers, + int *prval) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + + ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::list_watchers, _1, + _2, out_watchers); + if (prval != NULL) { + op = boost::bind(save_operation_result, + boost::bind(op, _1, _2, _3, _4), prval); + } + o->ops.push_back(op); +} + +void ObjectReadOperation::read(size_t off, uint64_t len, bufferlist *pbl, + int *prval) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + + ObjectOperationTestImpl op; + if (pbl != NULL) { + op = boost::bind(&TestIoCtxImpl::read, _1, _2, len, off, pbl); + } else { + op = boost::bind(&TestIoCtxImpl::read, _1, _2, len, off, _3); + } + + if (prval != NULL) { + op = boost::bind(save_operation_result, + boost::bind(op, _1, _2, _3, _4), prval); + } + o->ops.push_back(op); +} + +void ObjectReadOperation::sparse_read(uint64_t off, uint64_t len, + std::map *m, + bufferlist *pbl, int *prval) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + + ObjectOperationTestImpl op; + if (pbl != NULL) { + op = boost::bind(&TestIoCtxImpl::sparse_read, _1, _2, off, len, m, pbl); + } else { + op = boost::bind(&TestIoCtxImpl::sparse_read, _1, _2, off, len, m, _3); + } + + if (prval != NULL) { + op = boost::bind(save_operation_result, + boost::bind(op, _1, _2, _3, _4), prval); + } + o->ops.push_back(op); +} + +void ObjectReadOperation::stat(uint64_t *psize, time_t *pmtime, int *prval) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + + ObjectOperationTestImpl op = boost::bind(&TestIoCtxImpl::stat, _1, _2, + psize, pmtime); + + if (prval != NULL) { + op = boost::bind(save_operation_result, + boost::bind(op, _1, _2, _3, _4), prval); + } + o->ops.push_back(op); +} + +void ObjectWriteOperation::append(const bufferlist &bl) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::append, _1, _2, bl, _4)); +} + +void ObjectWriteOperation::create(bool exclusive) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::create, _1, _2, exclusive)); +} + +void ObjectWriteOperation::omap_set(const std::map &map) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::omap_set, _1, _2, boost::ref(map))); +} + +void ObjectWriteOperation::remove() { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::remove, _1, _2, _4)); +} + +void ObjectWriteOperation::selfmanaged_snap_rollback(uint64_t snapid) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::selfmanaged_snap_rollback, + _1, _2, snapid)); +} + +void ObjectWriteOperation::set_alloc_hint(uint64_t expected_object_size, + uint64_t expected_write_size) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::set_alloc_hint, _1, _2, + expected_object_size, expected_write_size, 0, + _4)); +} + +void ObjectWriteOperation::set_alloc_hint2(uint64_t expected_object_size, + uint64_t expected_write_size, + uint32_t flags) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::set_alloc_hint, _1, _2, + expected_object_size, expected_write_size, flags, + _4)); +} + +void ObjectWriteOperation::tmap_update(const bufferlist& cmdbl) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::tmap_update, _1, _2, + cmdbl)); +} + +void ObjectWriteOperation::truncate(uint64_t off) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::truncate, _1, _2, off, _4)); +} + +void ObjectWriteOperation::write(uint64_t off, const bufferlist& bl) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::write, _1, _2, bl, bl.length(), + off, _4)); +} + +void ObjectWriteOperation::write_full(const bufferlist& bl) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::write_full, _1, _2, bl, _4)); +} + +void ObjectWriteOperation::writesame(uint64_t off, uint64_t len, const bufferlist& bl) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::writesame, _1, _2, bl, len, + off, _4)); +} + +void ObjectWriteOperation::zero(uint64_t off, uint64_t len) { + TestObjectOperationImpl *o = reinterpret_cast(impl); + o->ops.push_back(boost::bind(&TestIoCtxImpl::zero, _1, _2, off, len, _4)); +} + +Rados::Rados() : client(NULL) { +} + +Rados::Rados(IoCtx& ioctx) { + TestIoCtxImpl *ctx = reinterpret_cast(ioctx.io_ctx_impl); + TestRadosClient *impl = ctx->get_rados_client(); + impl->get(); + + client = reinterpret_cast(impl); + ceph_assert(client != NULL); +} + +Rados::~Rados() { + shutdown(); +} + +void Rados::from_rados_t(rados_t p, Rados &rados) { + if (rados.client != nullptr) { + reinterpret_cast(rados.client)->put(); + rados.client = nullptr; + } + + auto impl = reinterpret_cast(p); + if (impl) { + impl->get(); + rados.client = reinterpret_cast(impl); + } +} + +AioCompletion *Rados::aio_create_completion(void *cb_arg, + callback_t cb_complete, + callback_t cb_safe) { + AioCompletionImpl *c; + int r = rados_aio_create_completion(cb_arg, cb_complete, cb_safe, + reinterpret_cast(&c)); + ceph_assert(r == 0); + return new AioCompletion(c); +} + +int Rados::aio_watch_flush(AioCompletion* c) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->aio_watch_flush(c->pc); +} + +int Rados::blacklist_add(const std::string& client_address, + uint32_t expire_seconds) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->blacklist_add(client_address, expire_seconds); +} + +config_t Rados::cct() { + TestRadosClient *impl = reinterpret_cast(client); + return reinterpret_cast(impl->cct()); +} + +int Rados::cluster_fsid(std::string* fsid) { + *fsid = "00000000-1111-2222-3333-444444444444"; + return 0; +} + +int Rados::conf_set(const char *option, const char *value) { + return rados_conf_set(reinterpret_cast(client), option, value); +} + +int Rados::conf_get(const char *option, std::string &val) { + TestRadosClient *impl = reinterpret_cast(client); + CephContext *cct = impl->cct(); + + char *str = NULL; + int ret = cct->_conf.get_val(option, &str, -1); + if (ret != 0) { + free(str); + return ret; + } + + val = str; + free(str); + return 0; +} + +int Rados::conf_parse_env(const char *env) const { + return rados_conf_parse_env(reinterpret_cast(client), env); +} + +int Rados::conf_read_file(const char * const path) const { + return rados_conf_read_file(reinterpret_cast(client), path); +} + +int Rados::connect() { + return rados_connect(reinterpret_cast(client)); +} + +uint64_t Rados::get_instance_id() { + TestRadosClient *impl = reinterpret_cast(client); + return impl->get_instance_id(); +} + +int Rados::get_min_compatible_osd(int8_t* require_osd_release) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->get_min_compatible_osd(require_osd_release); +} + +int Rados::get_min_compatible_client(int8_t* min_compat_client, + int8_t* require_min_compat_client) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->get_min_compatible_client(min_compat_client, + require_min_compat_client); +} + +int Rados::init(const char * const id) { + return rados_create(reinterpret_cast(&client), id); +} + +int Rados::init_with_context(config_t cct_) { + return rados_create_with_context(reinterpret_cast(&client), cct_); +} + +int Rados::ioctx_create(const char *name, IoCtx &io) { + rados_ioctx_t p; + int ret = rados_ioctx_create(reinterpret_cast(client), name, &p); + if (ret) { + return ret; + } + + io.close(); + io.io_ctx_impl = reinterpret_cast(p); + return 0; +} + +int Rados::ioctx_create2(int64_t pool_id, IoCtx &io) +{ + rados_ioctx_t p; + int ret = rados_ioctx_create2(reinterpret_cast(client), pool_id, &p); + if (ret) { + return ret; + } + + io.close(); + io.io_ctx_impl = reinterpret_cast(p); + return 0; +} + +int Rados::mon_command(std::string cmd, const bufferlist& inbl, + bufferlist *outbl, std::string *outs) { + TestRadosClient *impl = reinterpret_cast(client); + + std::vector cmds; + cmds.push_back(cmd); + return impl->mon_command(cmds, inbl, outbl, outs); +} + +int Rados::service_daemon_register(const std::string& service, + const std::string& name, + const std::map& metadata) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->service_daemon_register(service, name, metadata); +} + +int Rados::service_daemon_update_status(std::map&& status) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->service_daemon_update_status(std::move(status)); +} + +int Rados::pool_create(const char *name) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->pool_create(name); +} + +int Rados::pool_delete(const char *name) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->pool_delete(name); +} + +int Rados::pool_get_base_tier(int64_t pool, int64_t* base_tier) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->pool_get_base_tier(pool, base_tier); +} + +int Rados::pool_list(std::list& v) { + TestRadosClient *impl = reinterpret_cast(client); + std::list > pools; + int r = impl->pool_list(pools); + if (r < 0) { + return r; + } + + v.clear(); + for (std::list >::iterator it = pools.begin(); + it != pools.end(); ++it) { + v.push_back(it->second); + } + return 0; +} + +int Rados::pool_list2(std::list >& v) +{ + TestRadosClient *impl = reinterpret_cast(client); + return impl->pool_list(v); +} + +int64_t Rados::pool_lookup(const char *name) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->pool_lookup(name); +} + +int Rados::pool_reverse_lookup(int64_t id, std::string *name) { + TestRadosClient *impl = reinterpret_cast(client); + return impl->pool_reverse_lookup(id, name); +} + +void Rados::shutdown() { + if (client == NULL) { + return; + } + TestRadosClient *impl = reinterpret_cast(client); + impl->put(); + client = NULL; +} + +void Rados::test_blacklist_self(bool set) { +} + +int Rados::wait_for_latest_osdmap() { + TestRadosClient *impl = reinterpret_cast(client); + return impl->wait_for_latest_osdmap(); +} + +int Rados::watch_flush() { + TestRadosClient *impl = reinterpret_cast(client); + return impl->watch_flush(); +} + +WatchCtx::~WatchCtx() { +} + +WatchCtx2::~WatchCtx2() { +} + +} // namespace librados + +int cls_cxx_create(cls_method_context_t hctx, bool exclusive) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->create(ctx->oid, exclusive); +} + +int cls_cxx_remove(cls_method_context_t hctx) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->remove(ctx->oid, ctx->io_ctx_impl->get_snap_context()); +} + +int cls_get_request_origin(cls_method_context_t hctx, entity_inst_t *origin) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + + librados::TestRadosClient *rados_client = + ctx->io_ctx_impl->get_rados_client(); + + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = 0; + inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr); + + entity_addr_t entity_addr(entity_addr_t::TYPE_DEFAULT, + rados_client->get_nonce()); + entity_addr.in4_addr() = sin; + + *origin = entity_inst_t( + entity_name_t::CLIENT(rados_client->get_instance_id()), + entity_addr); + return 0; +} + +int cls_cxx_getxattr(cls_method_context_t hctx, const char *name, + bufferlist *outbl) { + std::map attrs; + int r = cls_cxx_getxattrs(hctx, &attrs); + if (r < 0) { + return r; + } + + std::map::iterator it = attrs.find(name); + if (it == attrs.end()) { + return -ENODATA; + } + *outbl = it->second; + return 0; +} + +int cls_cxx_getxattrs(cls_method_context_t hctx, std::map *attrset) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->xattr_get(ctx->oid, attrset); +} + +int cls_cxx_map_get_keys(cls_method_context_t hctx, const string &start_obj, + uint64_t max_to_get, std::set *keys, bool *more) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + + keys->clear(); + std::map vals; + int r = ctx->io_ctx_impl->omap_get_vals2(ctx->oid, start_obj, "", max_to_get, + &vals, more); + if (r < 0) { + return r; + } + + for (std::map::iterator it = vals.begin(); + it != vals.end(); ++it) { + keys->insert(it->first); + } + return keys->size(); +} + +int cls_cxx_map_get_val(cls_method_context_t hctx, const string &key, + bufferlist *outbl) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + + std::map vals; + int r = ctx->io_ctx_impl->omap_get_vals(ctx->oid, "", key, 1024, &vals); + if (r < 0) { + return r; + } + + std::map::iterator it = vals.find(key); + if (it == vals.end()) { + return -ENOENT; + } + + *outbl = it->second; + return 0; +} + +int cls_cxx_map_get_vals(cls_method_context_t hctx, const string &start_obj, + const string &filter_prefix, uint64_t max_to_get, + std::map *vals, bool *more) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + int r = ctx->io_ctx_impl->omap_get_vals2(ctx->oid, start_obj, filter_prefix, + max_to_get, vals, more); + if (r < 0) { + return r; + } + return vals->size(); +} + +int cls_cxx_map_remove_key(cls_method_context_t hctx, const string &key) { + std::set keys; + keys.insert(key); + + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->omap_rm_keys(ctx->oid, keys); +} + +int cls_cxx_map_set_val(cls_method_context_t hctx, const string &key, + bufferlist *inbl) { + std::map m; + m[key] = *inbl; + return cls_cxx_map_set_vals(hctx, &m); +} + +int cls_cxx_map_set_vals(cls_method_context_t hctx, + const std::map *map) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->omap_set(ctx->oid, *map); +} + +int cls_cxx_read(cls_method_context_t hctx, int ofs, int len, + bufferlist *outbl) { + return cls_cxx_read2(hctx, ofs, len, outbl, 0); +} + +int cls_cxx_read2(cls_method_context_t hctx, int ofs, int len, + bufferlist *outbl, uint32_t op_flags) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->read(ctx->oid, len, ofs, outbl); +} + +int cls_cxx_setxattr(cls_method_context_t hctx, const char *name, + bufferlist *inbl) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->xattr_set(ctx->oid, name, *inbl); +} + +int cls_cxx_stat(cls_method_context_t hctx, uint64_t *size, time_t *mtime) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->stat(ctx->oid, size, mtime); +} + +int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, + bufferlist *inbl) { + return cls_cxx_write2(hctx, ofs, len, inbl, 0); +} + +int cls_cxx_write2(cls_method_context_t hctx, int ofs, int len, + bufferlist *inbl, uint32_t op_flags) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->write(ctx->oid, *inbl, len, ofs, ctx->snapc); +} + +int cls_cxx_write_full(cls_method_context_t hctx, bufferlist *inbl) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + return ctx->io_ctx_impl->write_full(ctx->oid, *inbl, ctx->snapc); +} + +int cls_cxx_replace(cls_method_context_t hctx, int ofs, int len, + bufferlist *inbl) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + int r = ctx->io_ctx_impl->truncate(ctx->oid, 0, ctx->snapc); + if (r < 0) { + return r; + } + return ctx->io_ctx_impl->write(ctx->oid, *inbl, len, ofs, ctx->snapc); +} + +int cls_cxx_list_watchers(cls_method_context_t hctx, + obj_list_watch_response_t *watchers) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + + std::list obj_watchers; + int r = ctx->io_ctx_impl->list_watchers(ctx->oid, &obj_watchers); + if (r < 0) { + return r; + } + + for (auto &w : obj_watchers) { + watch_item_t watcher; + watcher.name = entity_name_t::CLIENT(w.watcher_id); + watcher.cookie = w.cookie; + watcher.timeout_seconds = w.timeout_seconds; + watcher.addr.parse(w.addr, 0); + watchers->entries.push_back(watcher); + } + + return 0; +} + +uint64_t cls_get_features(cls_method_context_t hctx) { + return CEPH_FEATURES_SUPPORTED_DEFAULT; +} + +uint64_t cls_get_client_features(cls_method_context_t hctx) { + return CEPH_FEATURES_SUPPORTED_DEFAULT; +} + +int cls_get_snapset_seq(cls_method_context_t hctx, uint64_t *snap_seq) { + librados::TestClassHandler::MethodContext *ctx = + reinterpret_cast(hctx); + librados::snap_set_t snapset; + int r = ctx->io_ctx_impl->list_snaps(ctx->oid, &snapset); + if (r < 0) { + return r; + } + + *snap_seq = snapset.seq; + return 0; +} + +int cls_log(int level, const char *format, ...) { + int size = 256; + va_list ap; + while (1) { + char buf[size]; + va_start(ap, format); + int n = vsnprintf(buf, size, format, ap); + va_end(ap); + if ((n > -1 && n < size) || size > 8196) { + dout(ceph::dout::need_dynamic(level)) << buf << dendl; + return n; + } + size *= 2; + } + return 0; +} + +int cls_register(const char *name, cls_handle_t *handle) { + librados::TestClassHandler *cls = get_class_handler(); + return cls->create(name, handle); +} + +int cls_register_cxx_method(cls_handle_t hclass, const char *method, + int flags, + cls_method_cxx_call_t class_call, + cls_method_handle_t *handle) { + librados::TestClassHandler *cls = get_class_handler(); + return cls->create_method(hclass, method, class_call, handle); +} + +int cls_register_cxx_filter(cls_handle_t hclass, + const std::string &filter_name, + cls_cxx_filter_factory_t fn, + cls_filter_handle_t *) +{ + librados::TestClassHandler *cls = get_class_handler(); + return cls->create_filter(hclass, filter_name, fn); +} + +int8_t cls_get_required_osd_release(cls_handle_t hclass) { + return CEPH_FEATURE_SERVER_NAUTILUS; +} -- cgit v1.2.3