X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Flibrbd%2FUtils.h;fp=src%2Fceph%2Fsrc%2Flibrbd%2FUtils.h;h=19c634479433988903960f0edfa4c5df019df3e0;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/librbd/Utils.h b/src/ceph/src/librbd/Utils.h new file mode 100644 index 0000000..19c6344 --- /dev/null +++ b/src/ceph/src/librbd/Utils.h @@ -0,0 +1,215 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_UTILS_H +#define CEPH_LIBRBD_UTILS_H + +#include "include/rados/librados.hpp" +#include "include/rbd_types.h" +#include "include/Context.h" +#include "common/zipkin_trace.h" + +#include +#include + +namespace librbd { + +class ImageCtx; + +namespace util { + +namespace detail { + +template +void rados_callback(rados_completion_t c, void *arg) { + reinterpret_cast(arg)->complete(rados_aio_get_return_value(c)); +} + +template +void rados_callback(rados_completion_t c, void *arg) { + T *obj = reinterpret_cast(arg); + int r = rados_aio_get_return_value(c); + (obj->*MF)(r); +} + +template +void rados_state_callback(rados_completion_t c, void *arg) { + T *obj = reinterpret_cast(arg); + int r = rados_aio_get_return_value(c); + Context *on_finish = (obj->*MF)(&r); + if (on_finish != nullptr) { + on_finish->complete(r); + if (destroy) { + delete obj; + } + } +} + +template +class C_CallbackAdapter : public Context { + T *obj; +public: + C_CallbackAdapter(T *obj) : obj(obj) { + } + +protected: + void finish(int r) override { + (obj->*MF)(r); + } +}; + +template +class C_StateCallbackAdapter : public Context { + T *obj; +public: + C_StateCallbackAdapter(T *obj) : obj(obj){ + } + +protected: + void complete(int r) override { + Context *on_finish = (obj->*MF)(&r); + if (on_finish != nullptr) { + on_finish->complete(r); + if (destroy) { + delete obj; + } + } + Context::complete(r); + } + void finish(int r) override { + } +}; + +template +struct C_AsyncCallback : public Context { + WQ *op_work_queue; + Context *on_finish; + + C_AsyncCallback(WQ *op_work_queue, Context *on_finish) + : op_work_queue(op_work_queue), on_finish(on_finish) { + } + void finish(int r) override { + op_work_queue->queue(on_finish, r); + } +}; + +} // namespace detail + +std::string generate_image_id(librados::IoCtx &ioctx); + +template +inline std::string generate_image_id(librados::IoCtx &ioctx) { + return generate_image_id(ioctx); +} + +const std::string group_header_name(const std::string &group_id); +const std::string id_obj_name(const std::string &name); +const std::string header_name(const std::string &image_id); +const std::string old_header_name(const std::string &image_name); +std::string unique_lock_name(const std::string &name, void *address); + +librados::AioCompletion *create_rados_callback(Context *on_finish); + +template +librados::AioCompletion *create_rados_callback(T *obj) { + return librados::Rados::aio_create_completion( + obj, &detail::rados_callback, nullptr); +} + +template +librados::AioCompletion *create_rados_callback(T *obj) { + return librados::Rados::aio_create_completion( + obj, &detail::rados_callback, nullptr); +} + +template +librados::AioCompletion *create_rados_callback(T *obj) { + return librados::Rados::aio_create_completion( + obj, &detail::rados_state_callback, nullptr); +} + +template +Context *create_context_callback(T *obj) { + return new detail::C_CallbackAdapter(obj); +} + +template +Context *create_context_callback(T *obj) { + return new detail::C_StateCallbackAdapter(obj); +} + +template +Context *create_async_context_callback(I &image_ctx, Context *on_finish) { + // use async callback to acquire a clean lock context + return new detail::C_AsyncCallback< + typename std::decay::type>( + image_ctx.op_work_queue, on_finish); +} + +template +Context *create_async_context_callback(WQ *work_queue, Context *on_finish) { + // use async callback to acquire a clean lock context + return new detail::C_AsyncCallback(work_queue, on_finish); +} + +// TODO: temporary until AioCompletion supports templated ImageCtx +inline ImageCtx *get_image_ctx(ImageCtx *image_ctx) { + return image_ctx; +} + +/// helper for tracking in-flight async ops when coordinating +/// a shut down of the invoking class instance +class AsyncOpTracker { +public: + void start_op() { + m_refs++; + } + + void finish_op() { + if (--m_refs == 0 && m_on_finish != nullptr) { + Context *on_finish = nullptr; + std::swap(on_finish, m_on_finish); + on_finish->complete(0); + } + } + + template + void wait(I &image_ctx, Context *on_finish) { + assert(m_on_finish == nullptr); + + on_finish = create_async_context_callback(image_ctx, on_finish); + if (m_refs == 0) { + on_finish->complete(0); + return; + } + m_on_finish = on_finish; + } + +private: + std::atomic m_refs = { 0 }; + Context *m_on_finish = nullptr; +}; + +uint64_t get_rbd_default_features(CephContext* cct); + +bool calc_sparse_extent(const bufferptr &bp, + size_t sparse_size, + uint64_t length, + size_t *write_offset, + size_t *write_length, + size_t *offset); + +template +inline ZTracer::Trace create_trace(const I &image_ctx, const char *trace_name, + const ZTracer::Trace &parent_trace) { + if (parent_trace.valid()) { + return ZTracer::Trace(trace_name, &image_ctx.trace_endpoint, &parent_trace); + } + return ZTracer::Trace(); +} + +} // namespace util + +} // namespace librbd + +#endif // CEPH_LIBRBD_UTILS_H