在看rbd-mirror的代码中,出现了以下的代码逻辑:
template <typename I>
void ImageReplayer<I>::wait_for_deletion() {
dout(20) << dendl;
Context *ctx = create_context_callback<
ImageReplayer, &ImageReplayer<I>::handle_wait_for_deletion>(this);
m_image_deleter->wait_for_scheduled_deletion(
m_local_pool_id, m_global_image_id, ctx, false);
}
template <typename I>
void ImageReplayer<I>::handle_wait_for_deletion(int r) {
dout(20) << "r=" << r << dendl;
if (r == -ECANCELED) {
on_start_fail(0, "");
return;
} else if (r < 0) {
on_start_fail(r, "error waiting for image deletion");
return;
}
prepare_local_image();
}
template <typename I>
void ImageReplayer<I>::prepare_local_image() {
dout(20) << dendl;
m_local_image_id = "";
Context *ctx = create_context_callback<
ImageReplayer, &ImageReplayer<I>::handle_prepare_local_image>(this);
auto req = PrepareLocalImageRequest<I>::create(
m_local_ioctx, m_global_image_id, &m_local_image_id, &m_local_image_name,
&m_local_image_tag_owner, m_threads->work_queue, ctx);
req->send();
}
template <typename I>
void ImageReplayer<I>::handle_prepare_local_image(int r) {
dout(20) << "r=" << r << dendl;
if (r == -ENOENT) {
dout(20) << "local image does not exist" << dendl;
} else if (r < 0) {
on_start_fail(r, "error preparing local image for replay");
return;
} else {
reregister_admin_socket_hook();
}
// local image doesn't exist or is non-primary
prepare_remote_image();
}
首先说明下以上代码的逻辑,以prepare_local_image
为例,在这个函数中,使用了create_context_callback
注册了一个回调函数handle_prepare_local_image
(后面可以看到很多以handle开头的函数,都可以视为回调函数),注册好了后就继续执行req->send();
当send()
函数返回时,那么就会调用handle_prepare_local_image
函数了,接着执行handle_prepare_local_image
中的逻辑。以此类推,如果进入到req->send()
,可以发现在send()
函数中也是有同样的逻辑(即就是注册回调函数,然后执行一个任务,执行结束后调用回调函数)
下面再来详细分析。
要看懂这两部分的代码逻辑需要对ceph rbd中的回调函数和回调类有所了解。
create_context_callback
这个函数。src/librbd/Utils.h
:template <typename T, void(T::*MF)(int) = &T::complete>
Context *create_context_callback(T *obj) {
return new detail::C_CallbackAdapter<T, MF>(obj);
}
还会牵涉到一个回调函数适配器C_CallbackAdapter
:
namespace detail
{
........
template <typename T, void (T::*MF)(int)>
class C_CallbackAdapter : public Context {
T *obj;
public:
C_CallbackAdapter(T *obj) : obj(obj) {
}
protected:
void finish(int r) override {
(obj->*MF)(r);
}
};
}
原文:https://www.cnblogs.com/powerrailgun/p/12342343.html