Leveldb源码解析第七篇【log】
来源:互联网 发布:在淘宝上班销售怎么做 编辑:程序博客网 时间:2024/06/05 11:24
版权声明:本文为博主原创文章,未经博主允许不得转载。
这里的 log
非彼 log
,这里的 log
是记录下用户的所有操作,防止设备异常导致 memtable
里面的数据丢失,用户在操作数据的时候首先会将操作写到 log
中,然后才会对数据进行操作
log相关的源码文件有
db/log_format.hdb/log_reader.hdb/log_reader.ccdb/log_writer.hdb/log_writer.cc
log_format
先看看log记录的格式
// log_format.h// log存放时会分为很多个块,块的大小是有限制的,当一行数据存储在一个块的结尾,而结尾剩下的空间不足以存下这条数据,那就会在几个块中存储这条记录,怎么将多个块中的数据合并成完整的数据呢,那就要看下面这个字段了。// 块中按record存储,一条数据可以分为多个record,每个record中会有一个type来记录这个record的类型enum RecordType { kZeroType = 0, kFullType = 1, // 表示这个record是一条完整数据 kFirstType = 2, // 表示这个record是一条数据的开始 kMiddleType = 3, // 表示这个record是一条数据的中间部分,后面还有数据 kLastType = 4 // 表示这个record是一条数据的结尾};static const int kMaxRecordType = kLastType;// 块大小static const int kBlockSize = 32768;// record头部长度static const int kHeaderSize = 4 + 2 + 1;
log_writer.h
理解log的结构就先看看数据是怎么写入到log中的
// log_write.cc// 初始化数据type循环冗余校验static void InitTypeCrc(uint32_t* type_crc) { for (int i = 0; i <= kMaxRecordType; i++) { char t = static_cast<char>(i); type_crc[i] = crc32c::Value(&t, 1); }}Status Writer::AddRecord(const Slice& slice) { const char* ptr = slice.data(); // 表示还剩下多少的数据没有写入log中 size_t left = slice.size(); Status s; bool begin = true; do { // 块中还剩下多少空间 const int leftover = kBlockSize - block_offset_; assert(leftover >= 0); // 如果剩下的空间不足7个字节,说明剩下的空间连record的头部都存储不下,用"\x00\x00\x00\x00\x00\x00"在填充剩下的空间 if (leftover < kHeaderSize) { // Switch to a new block if (leftover > 0) { // Fill the trailer (literal below relies on kHeaderSize being 7) assert(kHeaderSize == 7); dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover)); } block_offset_ = 0; } // Invariant: we never leave < kHeaderSize bytes in a block. assert(kBlockSize - block_offset_ - kHeaderSize >= 0); // block剩余空间减去一条record头部占用的空间,剩下是真正可以存储数据的空间 const size_t avail = kBlockSize - block_offset_ - kHeaderSize; // 可以存储数据的空间大小和数据大小比较,哪个小存储哪个 const size_t fragment_length = (left < avail) ? left : avail; RecordType type; // 如果数据大小 小于 可以存储数据的空间大小,那么end就为true;反之 const bool end = (left == fragment_length); if (begin && end) { // 第一次进来begin是true,如果块可以存储,那么end也为true,那么这条数据在这个块中是完整存储的 type = kFullType; } else if (begin) { // 第一次进来begin是true,如果块不够存储,那么end也为false,那么这条数据在这个块中只存储了这条数据的前面部分 type = kFirstType; } else if (end) { // 不是第一次进来begin是false,如果块够存储,那么end也为true,那么这条数据在这个块中是后面部分 type = kLastType; } else { // 又不是第一次进来,块又存储不够,那么这个块就只存储了这条数据的中间部分 type = kMiddleType; } // 将record写入磁盘 s = EmitPhysicalRecord(type, ptr, fragment_length); ptr += fragment_length; left -= fragment_length; begin = false; } while (s.ok() && left > 0); return s;}// 将record写入磁盘Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) { assert(n <= 0xffff); // Must fit in two bytes assert(block_offset_ + kHeaderSize + n <= kBlockSize); char buf[kHeaderSize]; // 块最大为32768,这个数字两个字节可以存下,record head第5和第6位用来存放record大小 buf[4] = static_cast<char>(n & 0xff); buf[5] = static_cast<char>(n >> 8); // 一条record的head第7位存放RecordType buf[6] = static_cast<char>(t); // Compute the crc of the record type and the payload. uint32_t crc = crc32c::Extend(type_crc_[t], ptr, n); crc = crc32c::Mask(crc); // Adjust for storage // head前4位存储crc EncodeFixed32(buf, crc); // Write the header and the payload // 在文件中写入head数据 Status s = dest_->Append(Slice(buf, kHeaderSize)); if (s.ok()) { // 再将数据写入到文件中 s = dest_->Append(Slice(ptr, n)); if (s.ok()) { // 如果都写入成功,文件刷新 s = dest_->Flush(); } } block_offset_ += kHeaderSize + n; return s;}
log
还是很简单的,主要搞明白 record
的格式就可以了
【作者:antonyxu https://antonyxux.github.io/ 】
阅读全文
0 0
- Leveldb源码解析第七篇【log】
- log::Writer-levelDB源码解析
- log::Reader-levelDB源码解析
- log format-levelDB源码解析
- levelDB源码分析-Log文件
- Leveldb源码解析第二篇【Meta Block】
- Leveldb源码解析第三篇【sstable 收尾】
- Leveldb源码解析第六篇【memtable】
- option-levelDB源码解析
- Slice-levelDB源码解析
- Status-levelDB源码解析
- varint-levelDB源码解析
- VersionSet-levelDB源码解析
- Version-levelDB源码解析
- VersionEdit-levelDB源码解析
- memtable-levelDB源码解析
- WriteBatch-levelDB源码解析
- BlockBuilder-levelDB源码解析
- javascript笔记(六)
- 尚学堂百战程序员1573题 答案 第三章
- STM32 485 调试
- 远场(far-field)语音识别的主流技术有哪些
- 【1】稀疏表示与匹配追踪
- Leveldb源码解析第七篇【log】
- 访问网站出现EOF
- find命令
- Check RedHat/HP-UX OS version
- pxe
- intellij IDE build出错,无法显示图片,找不到tomcat server,java编译版本过低,异常推出后无法启动项目等常见问题解决
- ## javascript笔记(七)
- 实现无头结点单链表的基本操作函数
- 舞步学院PUA就是个坑,大家千万不要信