Ceph C_GatherBuilder类使用简单理解

文章详细描述了在CephMDS客户端的mds_command函数中,如何使用C_GatherBuilder类创建和管理异步任务集合,包括C_GatherBuilderBase和C_GatherBase模板类的构造和方法,以及如何通过new_sub和finish方法实现任务的调度与完成条件的控制。
摘要由CSDN通过智能技术生成
1 使用流程

以ceph mds客户端mds_command中对C_GatherBuilder类类的具体使用为例,简单的流程概述为:C_GatherBuilder gather(cct, onfinish); 该类名为Builder,通过该类创建一个Gather(集合) 任务集合实例,通过new_sub方法为该集合实例添加子任务。当所有的子任务完成以后,返回入参的onfinsh指针的complete方法。

extern "C" int ceph_mds_command()
{
 
  C_SaferCond cond;
  int r = cmount->get_client()->mds_command(&cond);

  if (r != 0) {
    goto out;
  }
// Wait for completion
  r = cond.wait();

int Client::mds_command()
{
 //省略前文,直接从这里开始
  C_GatherBuilder gather(cct, onfinish); //建立一个堆栈变量gather
  for (const auto& target_gid : non_laggy) {
      .........
      op.on_finish = gather.new_sub(); //给每个异步任务新建一个context类实例。
      .........
  }
  gather.activate(); //激活异步任务。
     
  return 0;
}
2 C_GatherBuilderBase类
typedef C_GatherBase<Context, Context> C_Gather;
typedef C_GatherBuilderBase<Context, C_Gather > C_GatherBuilder;

1 C_GatherBuilderBase 和 C_GatherBase 都是模板类,首先这里, C_GatherBuilderBase的构造函数非常简单,传入一个ceph上下文cct,和一个继承Context的类C_SaferCond的类的指针。

typedef C_GatherBase<Context, Context> C_Gather;
typedef C_GatherBuilderBase<Context, C_Gather > C_GatherBuilder;

template <class ContextType, class GatherType>
class C_GatherBuilderBase
{
public:
  C_GatherBuilderBase(CephContext *cct_)
    : cct(cct_), c_gather(NULL), finisher(NULL), activated(false)
  {
  }
  C_GatherBuilderBase(CephContext *cct_, ContextType *finisher_)
    : cct(cct_), c_gather(NULL), finisher(finisher_), activated(false)
  {  //ContextType 是Context, GatherType 是C_Gather
  }

  ContextType *new_sub() {
    if (!c_gather) {  //c_gather 成员初始化为NULL,所以调用该函数时候会先构建一个堆内存(new)对象。
      c_gather = new GatherType(cct, finisher);//这里调用C_Gather 的构造函数,即GatherType
    }
    return c_gather->new_sub();
  }
3 C_GatherBase 类

C_GatherBase构造函数如下。

typedef C_GatherBase<Context, Context> C_Gather;
template <class ContextType, class ContextInstanceType>
class C_GatherBase {
private:
  CephContext *cct;
  int result = 0;
  ContextType *onfinish;
#ifdef DEBUG_GATHER
  std::set<ContextType*> waitfor; //子任务实例 的集合
#endif
  int sub_created_count = 0; //子任务计数
  int sub_existing_count = 0;//子任务计数
  bool activated = false; //任务开始标志
//中间省略部分代码
public:
  C_GatherBase(CephContext *cct_, ContextType *onfinish_)
    : cct(cct_), onfinish(onfinish_)
  {
  }
4 new_sub方法
 class C_GatherBuilderBase{ //Builder类是个C_Gather实例的构造器,行为透传到C_Gather实例的new_sub方法。
 ContextType *new_sub() {
    if (!c_gather) {
      c_gather = new GatherType(cct, finisher);
    }
    return c_gather->new_sub();
  }
}


class C_GatherBase {
  ContextType *new_sub() {
    std::lock_guard l{lock};
    ceph_assert(activated == false);
    sub_created_count++; //
    sub_existing_count++;//子任务计数+1
    ContextType *s = new C_GatherSub(this); //C_GatherSub类才是真正的子任务单独拥有的回调类。
    waitfor.insert(s);
    return s;
  }

  void sub_finish(ContextType* sub, int r) {
    lock.lock();

    ceph_assert(waitfor.count(sub));
    waitfor.erase(sub); //从waitfor中剔除已经完成的子任务
    --sub_existing_count; //计数-1
    if (r < 0 && result == 0)
      result = r;
    if ((activated == false) || (sub_existing_count != 0)) {
      lock.unlock();
      return;  //如果还有子任务没完成,只减少计数
    }
    lock.unlock();
    delete_me(); //如果子任务完成且 集合为激活。进入delete_me函数
  }


  void delete_me() {
    if (onfinish) { //这里是所有子任务完成后,使用最开始外部传入的类的complete方法,唤醒C_SafeCond的等待,然后ceph_mds_commmand执行完毕。
      onfinish->complete(result);
      onfinish = 0;
    }
    delete this;
  }

}

 class C_GatherSub : public ContextInstanceType {
    C_GatherBase *gather; //比context类多了一个成员变量,gather,即保存全部子任务信息的父类。C_Gather
  public:
    C_GatherSub(C_GatherBase *g) : gather(g) {}
    void complete(int r) override {
      Context::complete(r);
    }
    void finish(int r) override {
      gather->sub_finish(this, r); //引用计数-1
      gather = 0;
    }
    ~C_GatherSub() override {
      if (gather)
	gather->sub_finish(this, 0);
    }
  };
5 总结
extern "C" int ceph_mds_command()
{
 
  C_SaferCond cond;
  int r = cmount->get_client()->mds_command(&cond); //执行完毕以后,栈中的GatherBuilder的变量被释放,但是Gather类和 子任务的GatherSub类是new出来的堆变量,等任务完成以后依靠内部delete函数释放内存。

  if (r != 0) {
    goto out;
  }
// Wait for completion
  r = cond.wait(); //所有子任务执行完毕返回

int Client::mds_command()
{
 //省略前文,直接从这里开始
  C_GatherBuilder gather(cct, onfinish); //建立一个堆栈变量gather
  for (const auto& target_gid : non_laggy) {
      .........
      op.on_finish = gather.new_sub(); //给每个异步任务新建一个context类实例。
      .........
  }
  gather.activate(); //激活异步任务。
     
  return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值