ceph::buffer是ceph非常底层的实现,负责管理ceph的内存。ceph::buffer的设计较为复杂,但本身没有任何内容,主要包含buffer::list、buffer::ptr、buffer::hash。这三个类都定义在src/include/buffer.h和src/common/http://buffer.cc中。
buffer::raw:负责维护物理内存的引用计数nref和释放操作。
buffer::ptr:指向buffer::raw的指针。
buffer::list:表示一个ptr的列表(std::list
buffer::hash:一个或多个bufferlist的有效哈希。
bufferlist是基于bufferptr和bufferraw实现的,所以先分析buffer::raw。
class raw {
public:
std::aligned_storage::type bptr_storage;
char *data;
unsigned len;
std::atomic nref { 0 };
int mempool;
std::pair last_crc_offset {std::numeric_limits::max(), std::numeric_limits::max()};
std::pair last_crc_val;
mutable ceph::spinlock crc_spinlock;
...
}
成员变量:
data:指向原始数据raw的指针。
len:原始数据raw的长度。
nref:引用计数。
mempool:其对应的内存池的index,这个和data空间的分配有关。
crc_spinlock:读写锁。
bufferptr是基于bufferraw,bufferptr是bufferraw的指针,指向buffer::raw的一部分数据段。
class CEPH_BUFFER_API ptr {
raw *_raw;
public: // dirty hack for testing; if it works, this will be abstracted
unsigned _off, _len;
...
}
成员变量:
_raw:指向raw的指针
_off:数据偏移量
_len:数据长度
在list类前面定义了链表的结构体struct ptr_hook。
struct ptr_hook {
mutable ptr_hook* next;
ptr_hook() = default;
ptr_hook(ptr_hook* const next)
: next(next) {
}
};
buffer::list是由ptr组成的链表
class buffers_t {
// _root.next can be thought as _head
ptr_hook _root;
ptr_hook* _tail;
std::size_t _size;
...
}
_root:链表头
_tail:链表尾
_size:链表节点数
bufferlist将数据以不连续链表的方式存储。
bufferlist的迭代器
template
class CEPH_BUFFER_API iterator_impl
: public std::iterator
{
protected:
bl_t *bl;
list_t *ls; // meh.. just here to avoid an extra pointer dereference..
unsigned off; // in bl
list_iter_t p;
unsigned p_off; // in *p
......
};
bl:指针,指向bufferlist
ls:指针,指向bufferlist的成员 _buffers
p: 类型是std::list::iterator,用来迭代遍历bufferlist中的bufferptr
p_off:当前位置在对应的bufferptr中的偏移量
off:当前位置在整个bufferlist中的偏移量
void buffer::list::substr_of()
获取子字符串
other:指向原数据的bufferlist指针
off:数据的偏移
len:数据截取长度
void buffer::list::substr_of(const list& other, unsigned off, unsigned len)
{
if (off + len > other.length())
throw end_of_buffer();
clear();
// skip off
//curbuf获得other的链表头
auto curbuf = std::cbegin(other._buffers);
//找到和off对应的链表节点
while (off > 0 && off >= curbuf->length()) {
// skip this buffer
//cout << "skipping over " << *curbuf << std::endl;
off -= (*curbuf).length();
++curbuf;
}
ceph_assert(len == 0 || curbuf != std::cend(other._buffers));
//截取所需要的长度,创建新的节点加入到链表尾
while (len > 0) {
// partial?
if (off + len < curbuf->length()) {
//cout << "copying partial of " << *curbuf << std::endl;
_buffers.push_back(*ptr_node::create( *curbuf, off, len ).release());
_len += len;
break;
}
// through end
//cout << "copying end (all?) of " << *curbuf << std::endl;
unsigned howmuch = curbuf->length() - off;
_buffers.push_back(*ptr_node::create( *curbuf, off, howmuch ).release());
_len += howmuch;
len -= howmuch;
off = 0;
++curbuf;
}
}
buffer::create_aligned()
预对齐内存的分配
len:分配内存的大小
align:内存对齐的倍数
ceph::unique_leakable_ptr buffer::create_aligned(
unsigned len, unsigned align) {
return create_aligned_in_mempool(len, align,
mempool::mempool_buffer_anon);
}
void buffer::list::claim_append(list& bl, unsigned int flags)
将bl的数据复制_buffers的尾部/头部,然后接bl的数据清空。
void buffer::list::rebuild(
std::unique_ptr
将bufferlist中_buffers链表中所有的ptr中的数据存到一个ptr中,并将_buffers原有数据clear,然后将新的单个ptr push到_buffers中。