ceph RBD中用到的回调函数和回调类

在看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中的回调函数和回调类有所了解。

  1. 回调类和回调函数
    这里需要着重关注的是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);
           }
     };
}

猜你喜欢

转载自www.cnblogs.com/powerrailgun/p/12342343.html