Ceph Bufferlist: buffer::ptr的设计与

2020-05-27  本文已影响0人  圣地亚哥_SVIP

上一篇文章介绍了raw

class ptr数据结构:

迭代器的结构,定义在ptr结构中:

/*
* is_const: 表示是否const类型,const_iterator、iterator
*/
template<bool is_const>
class iterator_impl {
  /*
  * *bp: 指向ptr,ptr构造函数中使用this指针初始化;*bp = ptr
  * *start: 指向bp->c_str()
  */
  const ptr *bp; 
  const char *start; ///< starting pointer into bp->c_str()
  const char *pos;   ///< pointer into bp->c_str()
  const char *end_ptr;   ///< pointer to bp->end_c_str()
  const bool deep;   ///< if true, do not allow shallow ptr copies

  iterator_impl(typename std::conditional<is_const, const ptr*, ptr*>::type p,
    size_t offset, bool d)
  : bp(p),
    start(p->c_str() + offset),
    pos(start),
    end_ptr(p->end_c_str()),
    deep(d)
  {}

  friend class ptr;

public:
  using pointer = typename std::conditional<is_const, const char*, char *>::type;
  pointer get_pos_add(size_t n) {
    auto r = pos;
    *this += n;
    return r;
  }
  ptr get_ptr(size_t len) {
    if (deep) {
      return buffer::copy(get_pos_add(len), len);
    } else {
      size_t off = pos - bp->c_str();
      *this += len;
      return ptr(*bp, off, len);
    }
  }

  iterator_impl& operator+=(size_t len) {
    pos += len;
    if (pos > end_ptr)
      throw end_of_buffer();
          return *this;
  }

  const char *get_pos() {
    return pos;
  }
  const char *get_end() {
    return end_ptr;
  }

  size_t get_offset() {
    return pos - start;
  }

  bool end() const {
    return pos == end_ptr;
  }
};
class ptr {
    friend class list;
  protected:
    raw *_raw;
    unsigned _off, _len;
  private:
    template<bool is_const>
    /*
    * iterator_impl: 简易迭代器的定义与实现
    */
    class iterator_impl{...};
    /*资源释放*/
    void release();
  public:
    /*
    * 定义两类迭代器
    */
    using const_iterator = iterator_impl<true>;
    using iterator = iterator_impl<false>;
    /*
    * ptr相关的构造函数
    */
    ptr() : _raw(nullptr), _off(0), _len(0) {}
    /*
    * 使用新的数据块初始化此ptr
    */
    ptr(ceph::unique_leakable_ptr<raw> r);
    /*
    * 创建一个大小为l的数据块,并初始化此ptr
    */
    ptr(unsigned l);
    ptr(const char *d, unsigned l);
    ptr(const ptr& p);
    ptr(ptr&& p) noexcept;
    ptr(const ptr& p, unsigned o, unsigned l);
    ptr(const ptr& p, ceph::unique_leakable_ptr<raw> r);
    ptr& operator= (const ptr& p);
    ptr& operator= (ptr&& p) noexcept;
    ~ptr() {
      release();
    }

    bool have_raw() const { return _raw ? true:false; }

    ceph::unique_leakable_ptr<raw> clone();
    void swap(ptr& other) noexcept;

    /*
    * 返回迭代器
    */
    iterator begin(size_t offset=0) {
      return iterator(this, offset, false);
    }
    const_iterator begin(size_t offset=0) const {
      return const_iterator(this, offset, false);
    }
    const_iterator cbegin() const {
      return begin();
    }
    const_iterator begin_deep(size_t offset=0) const {
      return const_iterator(this, offset, true);
    }

    /*
    * 判断对齐相关操作
    */
    bool is_aligned(unsigned align) const {
      return ((long)c_str() & (align-1)) == 0;
    }
    bool is_page_aligned() const { return is_aligned(CEPH_PAGE_SIZE); }
    bool is_n_align_sized(unsigned align) const
    {
      return (length() % align) == 0;
    }
    bool is_n_page_sized() const { return is_n_align_sized(CEPH_PAGE_SIZE); }
    bool is_partial() const {
      return have_raw() && (start() > 0 || end() < raw_length());
    }
    /*
    * mempool相关操作
    */
    int get_mempool() const;
    void reassign_to_mempool(int pool);
    void try_assign_to_mempool(int pool);

    /*
    * 数据及属性相关的操作
    */
    const char *c_str() const{
      assert(_raw);
      return _raw->get_data() + _off;
    }
    char *c_str(){
      assert(_raw);
      return _raw->get_data() + _off;
    }
    const char *end_c_str() const{
      assert(_raw);
      return _raw->get_data() + _off + _len;
    }
    char *end_c_str(){assert(_raw);return _raw->get_data() + _off + _len;}
    unsigned length() const { return _len; }
    unsigned offset() const { return _off; }
    unsigned start() const { return _off; }
    unsigned end() const { return _off + _len; }
    /* raw尾部剩余空间 */
    unsigned unused_tail_length() const{
    {
      if (_raw)
        return _raw->len - (_off+_len);
      else
        return 0;
    }
    const char& operator[](unsigned n) const{return _raw->get_data()[_off + n];}
    char& operator[](unsigned n){return _raw->get_data()[_off + n];}

    const char *raw_c_str() const{return _raw->data;}
    unsigned raw_length() const{return _raw->len;}
    int raw_nref() const{return _raw->nref; }

    void copy_out(unsigned o, unsigned l, char *dest) const;

    unsigned wasted() const;

    int cmp(const ptr& o) const;
    bool is_zero() const;

    // modifiers
    void set_offset(unsigned o) {
      assert(raw_length() >= o);
      _off = o;
    }
    void set_length(unsigned l) {
      assert(raw_length() >= l);
      _len = l;
    }

    unsigned append(char c);
    unsigned append(const char *p, unsigned l);
    inline unsigned append(std::string_view s) {
      return append(s.data(), s.length());
    }
    void copy_in(unsigned o, unsigned l, const char *src, bool crc_reset = true);
    void zero(bool crc_reset = true);
    void zero(unsigned o, unsigned l, bool crc_reset = true);
    unsigned append_zeros(unsigned l);

  };

release():

/*
* 资源释放函数:判断raw的引用计数是否有它引:
* 引用计数为1: 减少引用计数,delete raw
* 引用计数>1: 减少引用计数,_raw = nullptr;
*/
void ptr::release(){
 if (_raw) {
   const bool last_one = (1 == _raw->nref.load(std::memory_order_acquire));
   if (likely(last_one) || --_raw->nref == 0) {
     const auto* delete_raw = _raw;
     _raw = nullptr;
     delete delete_raw; 
   } else {
     _raw = nullptr;
   }
 }
}

构造函数ptr(raw):

/*
* _raw(r.release()): 使用的r的裸指针初始化_raw,清理unique_leakable_ptr
* 初始化_off, _len
* 初始化raw的引用计数为1
*/
ptr::ptr(ceph::unique_leakable_ptr<raw> r)
  : _raw(r.release()),
    _off(0),
    _len(_raw->len)
{
  _raw->nref.store(1, std::memory_order_release);
}

以下是构造及拷贝复制构造函数的实现:

/* 创建大小为l的数据块 */
buffer::ptr::ptr(unsigned l) : _off(0), _len(l)
{
 _raw = buffer::create(l).release();
 _raw->nref.store(1, std::memory_order_release);
}
/* 创建一个新的数据块,并使用d初始化 */
buffer::ptr::ptr(const char *d, unsigned l) : _off(0), _len(l) 
{
 _raw = buffer::copy(d, l).release();
 _raw->nref.store(1, std::memory_order_release);
}
/* 拷贝构造函数,共享一个数据块 */
buffer::ptr::ptr(const ptr& p) : _raw(p._raw), _off(p._off), _len(p._len)
{
 if (_raw) {
   _raw->nref++;
 }
}
/* 移动拷贝构造函数,清理p的数据,数据块的控制权转移至本ptr */
buffer::ptr::ptr(ptr&& p) noexcept : _raw(p._raw), _off(p._off), _len(p._len)
{
 p._raw = nullptr;
 p._off = p._len = 0;
}
/* 共享p的部分数据块,共享的内容: [p._off+o,l] */
buffer::ptr::ptr(const ptr& p, unsigned o, unsigned l)
 : _raw(p._raw), _off(p._off + o), _len(l)
{
 assert(o+l <= p._len);
 assert(_raw);
 _raw->nref++;
}

/* 利用新的数据块初始化ptr,实际使用数据地址与p相同 */
buffer::ptr::ptr(const ptr& p, ceph::unique_leakable_ptr<raw> r)
 : _raw(r.release()),
   _off(p._off),
   _len(p._len)
{
 _raw->nref.store(1, std::memory_order_release);
}

/* 赋值构造函数,ptr指向p的数据块,添加引用计数,释放本地数据块,此处代码考虑了数据块同一个的情况 */
buffer::ptr& buffer::ptr::operator= (const ptr& p)
{
 if (p._raw) {
   p._raw->nref++;
 }
 buffer::raw *raw = p._raw; 
 release();
 if (raw) {
   _raw = raw;
   _off = p._off;
   _len = p._len;
 } else {
   _off = _len = 0;
 }
 return *this;
}

/* 移动赋值构造函数,释放本地数据块,指向新的数据块 */
buffer::ptr& buffer::ptr::operator= (ptr&& p) noexcept
{
 release();
 buffer::raw *raw = p._raw;
 if (raw) {
   _raw = raw;
   _off = p._off;
   _len = p._len;
   p._raw = nullptr;
   p._off = p._len = 0;
 } else {
   _off = _len = 0;
 }
 return *this;
}

/* clone一份本地的数据块数据 */
ceph::unique_leakable_ptr<buffer::raw> buffer::ptr::clone()
{
 return _raw->clone();
}

/* 交换ptr */
void buffer::ptr::swap(ptr& other) noexcept
{
 raw *r = _raw;
 unsigned o = _off;
 unsigned l = _len;
 _raw = other._raw;
 _off = other._off;
 _len = other._len;
 other._raw = r;
 other._off = o;
 other._len = l;
}

/* 从ptr中拷贝数据至dest,数据范围为:start: _off+o, Len: l */
void buffer::ptr::copy_out(unsigned o, unsigned l, char *dest) const {
 assert(_raw);
 if (o+l > _len)
     throw end_of_buffer();
 char* src =  _raw->data + _off + o;
 maybe_inline_memcpy(dest, src, l, 8);
}
/* 未被此ptr使用的空间大小 */
unsigned buffer::ptr::wasted() const
{
 return _raw->len - _len;
}

/* ptr比较函数 */
int buffer::ptr::cmp(const ptr& o) const
{
 int l = _len < o._len ? _len : o._len;
 if (l) {
   int r = memcmp(c_str(), o.c_str(), l);
   if (r)
return r;
 }
 if (_len < o._len)
   return -1;
 if (_len > o._len)
   return 1;
 return 0;
}

/* 判断内容是否为0 */
bool buffer::ptr::is_zero() const
{
 return mem_is_zero(c_str(), _len);
}

/* 
* ptr append一个字符 
* 注:append的所有操作,末尾追加,使用unused_tail_length,不改变raw实际大小
*/
unsigned buffer::ptr::append(char c)
{
 assert(_raw);
 assert(1 <= unused_tail_length());
 char* ptr = _raw->data + _off + _len;
 *ptr = c;
 _len++;
 return _len + _off;
}

unsigned buffer::ptr::append(const char *p, unsigned l)
{
 assert(_raw);
 assert(l <= unused_tail_length());
 char* c = _raw->data + _off + _len;
 maybe_inline_memcpy(c, p, l, 32);
 _len += l;
 return _len + _off;
}

unsigned buffer::ptr::append_zeros(unsigned l)
{
 assert(_raw);
 assert(l <= unused_tail_length());
 char* c = _raw->data + _off + _len;
 // FIPS zeroization audit 20191115: this memset is not security related.
 memset(c, 0, l);
 _len += l;
 return _len + _off;
}

/*
* 从src中拷贝数据至raw
*/
void buffer::ptr::copy_in(unsigned o, unsigned l, const char *src, bool crc_reset)
{
 assert(_raw);
 assert(o <= _len);
 assert(o+l <= _len);
 char* dest = _raw->data + _off + o;
 if (crc_reset)
     _raw->invalidate_crc();
 maybe_inline_memcpy(dest, src, l, 64);
}
/*
* 重置动作
*/
void buffer::ptr::zero(bool crc_reset)
{
 if (crc_reset)
     _raw->invalidate_crc();
 // FIPS zeroization audit 20191115: this memset is not security related.
 memset(c_str(), 0, _len);
}

void buffer::ptr::zero(unsigned o, unsigned l, bool crc_reset)
{
 assert(o+l <= _len);
 if (crc_reset)
     _raw->invalidate_crc();
 // FIPS zeroization audit 20191115: this memset is not security related.
 memset(c_str()+o, 0, l);
}

ptr_hook
用于连接ptr_node:

struct ptr_hook {
  mutable ptr_hook* next;

  ptr_hook() = default;
  ptr_hook(ptr_hook* const next)
    : next(next) {
  }
};

ptr_node:
ptr_node的定义:

/*
* 继承ptr_hook:主要用于buffer::list中,next链表
*/
class ptr_node : public ptr_hook, public ptr {
public:
  struct cloner {
    ptr_node* operator()(const ptr_node& clone_this);
  };
  /*
  * 自定义unique_ptr的资源释放函数,主要释放ptr_node本身,raw的释放ptr的析构函数处理
  */
  struct disposer {
    void operator()(ptr_node* const delete_this) {
      if (!dispose_if_hypercombined(delete_this)) {
        delete delete_this;
      }
    }
  };
  /* 默认的析构函数 */
  ~ptr_node() = default;

  /*
  * 静态函数,ptr_node的接口函数,使用raw初始化,调用create_hypercombined函数
  */
  static std::unique_ptr<ptr_node, disposer> create(ceph::unique_leakable_ptr<raw> r) {
    return create_hypercombined(std::move(r));
  }
  /*
  * 重载函数,创建长度为l的数据块,buffer::create创建unqiue_ptr 的raw块,调用create_hypercombined
  */
  static std::unique_ptr<ptr_node, disposer> create(const unsigned l) {
    return create_hypercombined(buffer::create(l));
  }

  /*
  * 可变参数函数接口,调用ptr_node构造函数
  */
  template <class... Args>
  static std::unique_ptr<ptr_node, disposer> create(Args&&... args) {
    return std::unique_ptr<ptr_node, disposer>(new ptr_node(std::forward<Args>(args)...));
  }
  /* ptr_node构造接口 */
  static ptr_node* copy_hypercombined(const ptr_node& copy_this);

private:
  /*
  * 私有构造函数
  * 可变参数的构造函数的入口
  */
  template <class... Args>
  ptr_node(Args&&... args) : ptr(std::forward<Args>(args)...) {}
  ptr_node(const ptr_node&) = default;

  /*
  * 禁止ptr的拷贝以及移动拷贝构造函数
  * 禁止ptr_node的赋值及移动赋值构造函数
  * 禁止swap功能
  */
  ptr& operator= (const ptr& p) = delete;
  ptr& operator= (ptr&& p) noexcept = delete;
  ptr_node& operator= (const ptr_node& p) = delete;
  ptr_node& operator= (ptr_node&& p) noexcept = delete;
  void swap(ptr& other) noexcept = delete;
  void swap(ptr_node& other) noexcept = delete;

  /*
  * 判断是否使用hypercombined
  */
  static bool dispose_if_hypercombined(ptr_node* delete_this);
  static std::unique_ptr<ptr_node, disposer> create_hypercombined(ceph::unique_leakable_ptr<raw> r);
};

/*
* 判断是否使用hypercombined方式创建的raw
*/
bool buffer::ptr_node::dispose_if_hypercombined(buffer::ptr_node* const delete_this)
{
  const bool is_hypercombined = static_cast<void*>(delete_this) == \
    static_cast<void*>(&delete_this->_raw->bptr_storage);
  if (is_hypercombined) {
    delete_this->~ptr_node();
  }
  return is_hypercombined;
}

/*
* 基于raw创建ptr_node
*/
std::unique_ptr<buffer::ptr_node, buffer::ptr_node::disposer> buffer::ptr_node::create_hypercombined(ceph::unique_leakable_ptr<buffer::raw> r)
{
  return std::unique_ptr<buffer::ptr_node, buffer::ptr_node::disposer>(new ptr_node(std::move(r)));
}

/*
* clone ptr_node
*/
buffer::ptr_node* buffer::ptr_node::cloner::operator()(
  const buffer::ptr_node& clone_this)
{
  return new ptr_node(clone_this);
}
上一篇下一篇

猜你喜欢

热点阅读