]>
git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/Utils.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_LIBRBD_UTILS_H
5 #define CEPH_LIBRBD_UTILS_H
7 #include "include/rados/librados.hpp"
8 #include "include/rbd_types.h"
9 #include "include/Context.h"
10 #include "common/zipkin_trace.h"
13 #include <type_traits>
24 void rados_callback(rados_completion_t c
, void *arg
) {
25 reinterpret_cast<T
*>(arg
)->complete(rados_aio_get_return_value(c
));
28 template <typename T
, void(T::*MF
)(int)>
29 void rados_callback(rados_completion_t c
, void *arg
) {
30 T
*obj
= reinterpret_cast<T
*>(arg
);
31 int r
= rados_aio_get_return_value(c
);
35 template <typename T
, Context
*(T::*MF
)(int*), bool destroy
>
36 void rados_state_callback(rados_completion_t c
, void *arg
) {
37 T
*obj
= reinterpret_cast<T
*>(arg
);
38 int r
= rados_aio_get_return_value(c
);
39 Context
*on_finish
= (obj
->*MF
)(&r
);
40 if (on_finish
!= nullptr) {
41 on_finish
->complete(r
);
48 template <typename T
, void (T::*MF
)(int)>
49 class C_CallbackAdapter
: public Context
{
52 C_CallbackAdapter(T
*obj
) : obj(obj
) {
56 void finish(int r
) override
{
61 template <typename T
, Context
*(T::*MF
)(int*), bool destroy
>
62 class C_StateCallbackAdapter
: public Context
{
65 C_StateCallbackAdapter(T
*obj
) : obj(obj
){
69 void complete(int r
) override
{
70 Context
*on_finish
= (obj
->*MF
)(&r
);
71 if (on_finish
!= nullptr) {
72 on_finish
->complete(r
);
79 void finish(int r
) override
{
83 template <typename WQ
>
84 struct C_AsyncCallback
: public Context
{
88 C_AsyncCallback(WQ
*op_work_queue
, Context
*on_finish
)
89 : op_work_queue(op_work_queue
), on_finish(on_finish
) {
91 void finish(int r
) override
{
92 op_work_queue
->queue(on_finish
, r
);
98 std::string
generate_image_id(librados::IoCtx
&ioctx
);
100 const std::string
group_header_name(const std::string
&group_id
);
101 const std::string
id_obj_name(const std::string
&name
);
102 const std::string
header_name(const std::string
&image_id
);
103 const std::string
old_header_name(const std::string
&image_name
);
104 std::string
unique_lock_name(const std::string
&name
, void *address
);
106 librados::AioCompletion
*create_rados_callback(Context
*on_finish
);
108 template <typename T
>
109 librados::AioCompletion
*create_rados_callback(T
*obj
) {
110 return librados::Rados::aio_create_completion(
111 obj
, &detail::rados_callback
<T
>, nullptr);
114 template <typename T
, void(T::*MF
)(int)>
115 librados::AioCompletion
*create_rados_callback(T
*obj
) {
116 return librados::Rados::aio_create_completion(
117 obj
, &detail::rados_callback
<T
, MF
>, nullptr);
120 template <typename T
, Context
*(T::*MF
)(int*), bool destroy
=true>
121 librados::AioCompletion
*create_rados_callback(T
*obj
) {
122 return librados::Rados::aio_create_completion(
123 obj
, &detail::rados_state_callback
<T
, MF
, destroy
>, nullptr);
126 template <typename T
, void(T::*MF
)(int) = &T::complete
>
127 Context
*create_context_callback(T
*obj
) {
128 return new detail::C_CallbackAdapter
<T
, MF
>(obj
);
131 template <typename T
, Context
*(T::*MF
)(int*), bool destroy
=true>
132 Context
*create_context_callback(T
*obj
) {
133 return new detail::C_StateCallbackAdapter
<T
, MF
, destroy
>(obj
);
136 template <typename I
>
137 Context
*create_async_context_callback(I
&image_ctx
, Context
*on_finish
) {
138 // use async callback to acquire a clean lock context
139 return new detail::C_AsyncCallback
<
140 typename
std::decay
<decltype(*image_ctx
.op_work_queue
)>::type
>(
141 image_ctx
.op_work_queue
, on_finish
);
144 template <typename WQ
>
145 Context
*create_async_context_callback(WQ
*work_queue
, Context
*on_finish
) {
146 // use async callback to acquire a clean lock context
147 return new detail::C_AsyncCallback
<WQ
>(work_queue
, on_finish
);
150 // TODO: temporary until AioCompletion supports templated ImageCtx
151 inline ImageCtx
*get_image_ctx(ImageCtx
*image_ctx
) {
155 /// helper for tracking in-flight async ops when coordinating
156 /// a shut down of the invoking class instance
157 class AsyncOpTracker
{
164 if (--m_refs
== 0 && m_on_finish
!= nullptr) {
165 Context
*on_finish
= nullptr;
166 std::swap(on_finish
, m_on_finish
);
167 on_finish
->complete(0);
171 template <typename I
>
172 void wait(I
&image_ctx
, Context
*on_finish
) {
173 assert(m_on_finish
== nullptr);
175 on_finish
= create_async_context_callback(image_ctx
, on_finish
);
177 on_finish
->complete(0);
180 m_on_finish
= on_finish
;
184 std::atomic
<uint64_t> m_refs
= { 0 };
185 Context
*m_on_finish
= nullptr;
188 uint64_t get_rbd_default_features(CephContext
* cct
);
190 bool calc_sparse_extent(const bufferptr
&bp
,
193 size_t *write_offset
,
194 size_t *write_length
,
197 template <typename I
>
198 inline ZTracer::Trace
create_trace(const I
&image_ctx
, const char *trace_name
,
199 const ZTracer::Trace
&parent_trace
) {
200 if (parent_trace
.valid()) {
201 return ZTracer::Trace(trace_name
, &image_ctx
.trace_endpoint
, &parent_trace
);
203 return ZTracer::Trace();
208 } // namespace librbd
210 #endif // CEPH_LIBRBD_UTILS_H