寻求帮助
由于自己第一次读开源代码,所以完全没有方法,所以第一步是疯狂Google
brpc学习最佳实践
如何阅读源代码
最终找到一篇比较好的文章
如何阅读一份源代码?
制定计划
目前自己的大计划是一年能够改写brpc
所以小计划是当前一个月先搞清楚brpc的基本框架,了解基本结构
制定以上计划的原因如下:
- 自己第一次读大型开源项目
- 这个brpc涉及的知识点较多,工程庞大,而且十分经典实用,所以应该深入学习
第一周实践
阅读技巧
https://www.codedump.info/post/20200605-how-to-read-code-v2020/
然后跟着brpc学习 慢慢来的,
2020年09月28日16:33:07 发现其中AutoReset<>类是第一个简单易懂的类___继续加油
IOBuf
声明在iobuf.h
,然后实现在iobuf_inl.h
和 iobuf.cpp
中
cntn问题__TODO
size_t IOBuf::cutn(std::string* out, size_t n) {
if (n == 0) {
return 0;
}
const size_t len = length();
if (n > len) {
n = len;
}
const size_t old_size = out->size();
out->resize(out->size() + n);
return cutn(&(*out)[old_size], n);
}
这个cntn在if (n > len)
处的操作有点迷惑,因为凭空就把n缩小了
cut_until理解
brpc之iobuf中说道:
cut_until,从前到后开始cut,直到遇到字符匹配到delim,如果没有匹配到返回-1; 需要注意的地方时,这个地方delim字符串的长度不能超过unsiged long的长度,因为brpc中将字符串hash到一个unsigned long型的整数,然后遍历匹配的时候,也将IOBuf中的字符串hash到一个unsigned long类型的整数,与delim进行比较;这个地方比较精巧的是,hash的时候使用位移操作,向左移,后面的字符串会把前面的字符串冲掉,因此复杂度从 O(N*M) 降到O(N),其中N为block中字符串的长度,M为delim的长度;
我一开始不懂,后面想到其实可能是因为这个hash只能对字符一直加和,但是不能取模,因为取模就会导致类似hash碰撞的事情,所以就不一定是真的字符匹配了(我猜的)
append_from_file_descriptor 读fd___ 有点精妙
看一下实现代码,主要做了三件事:
循环block,准备好readv函数的参数地址(将block的可写首地址和可写长度依次获取,放入到iovec的数组中)
调用pread函数将读取到的内容写入到上面准备的地址,获取读取的总长度nr;
整理现有的block,因为现有的Block可能很多写满了。
ssize_t IOPortal::pappend_from_file_descriptor(
int fd, off_t offset, size_t max_count) {
iovec vec[MAX_APPEND_IOVEC];
int nvec = 0;
size_t space = 0;
Block* prev_p = NULL;
Block* p = _block;
// Prepare at most MAX_APPEND_IOVEC blocks or space of blocks >= max_count
do {
if (p == NULL) {
p = iobuf::acquire_tls_block();
if (BAIDU_UNLIKELY(!p)) {
errno = ENOMEM;
return -1;
}
if (prev_p != NULL) {
prev_p->portal_next = p;
} else {
_block = p;
}
}
vec[nvec].iov_base = p->data + p->size;
vec[nvec].iov_len = std::min(p->left_space(), max_count - space);
space += vec[nvec].iov_len;
++nvec;
if (space >= max_count || nvec >= MAX_APPEND_IOVEC) {
break;
}
prev_p = p;
p = p->portal_next;
} while (1);
ssize_t nr = 0;
if (offset < 0) {
nr = readv(fd, vec, nvec);
} else {
static iobuf::iov_function preadv_func = iobuf::get_preadv_func();
nr = preadv_func(fd, vec, nvec, offset);
}
if (nr <= 0) { // -1 or 0
if (empty()) {
return_cached_blocks();
}
return nr;
}
size_t total_len = nr;
do {
const size_t len = std::min(total_len, _block->left_space());
total_len -= len;
const IOBuf::BlockRef r = { _block->size, (uint32_t)len, _block };
_push_back_ref(r);
_block->size += len;
if (_block->full()) {
Block* const saved_next = _block->portal_next;
_block->dec_ref(); // _block may be deleted
_block = saved_next;
}
} while (total_len);
return nr;
}
inline ssize_t IOPortal::append_from_file_descriptor(int fd, size_t max_count) {
return pappend_from_file_descriptor(fd, -1, max_count);
}
Containers
flatmap
有趣的[]
源码
template <typename _K, typename _T, typename _H, typename _E, bool _S>
_T& FlatMap<_K, _T, _H, _E, _S>::operator[](const key_type& key) {
const size_t index = flatmap_mod(_hashfn(key), _nbucket);
Bucket& first_node = _buckets[index];
if (!first_node.is_valid()) {
++_size;
if (_S) {
bit_array_set(_thumbnail, index);
}
new (&first_node) Bucket(key);
return first_node.element().second_ref();
}
if (_eql(first_node.element().first_ref(), key)) {
return first_node.element().second_ref();
}
Bucket *p = first_node.next;
if (NULL == p) {
if (is_too_crowded(_size)) {
if (resize(_nbucket + 1)) {
return operator[](key);
}
// fail to resize is OK
}
++_size;
Bucket* newp = new (_pool.get()) Bucket(key);
first_node.next = newp;
return newp->element().second_ref();
}
while (1) {
if (_eql(p->element().first_ref(), key)) {
return p->element().second_ref();
}
if (NULL == p->next) {
if (is_too_crowded(_size)) {
if (resize(_nbucket + 1)) {
return operator[](key);
}
// fail to resize is OK
}
++_size;
Bucket* newp = new (_pool.get()) Bucket(key);
p->next = newp;
return newp->element().second_ref();
}
p = p->next;
}
}
TODO_code_双缓冲数据 DoublyBufferedData
2020年10月01日19:22:10 今天花了一段时间看完了官方参考资料:https://github.com/apache/incubator-brpc/blob/master/docs/cn/lalb.md
感觉很有计算含量,所以明天继续看一下代码___2020年10月02日19:01:46 决定暂时宏观层面先学习,所以这个细致代码暂缓
protobuf
client
https://github.com/apache/incubator-brpc/blob/master/docs/cn/client.md
TODO未懂含义_c_murmurhash or c_md5
TODO
- 默认是IOBuf是small view,只有在两个refs种都存储了不同的的Block之后,才自动转为BigView,可以参考iobuf.cpp:601行____这里没有看懂,2020年09月29日20:54:48