Ceph Bufferlist: buffer::ptr的设计与
2020-05-27 本文已影响0人
圣地亚哥_SVIP
上一篇文章介绍了raw。
class ptr数据结构:
- raw *_raw: 指向实际的数据块
- _off,_len: 数据在raw中的偏移地址,及数据长度
- iterator_impl: 简易迭代器
迭代器的结构,定义在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);
}