//Write负责组织数据有格式的写入,成员变量dest_负责真正写入数据到文件系统 classWriter { public: // Create a writer that will append data to "*dest". // "*dest" must be initially empty. // "*dest" must remain live while this Writer is in use. explicitWriter(WritableFile* dest);
// Create a writer that will append data to "*dest". // "*dest" must have initial length "dest_length". // "*dest" must remain live while this Writer is in use. Writer(WritableFile* dest, uint64_t dest_length);
private: WritableFile* dest_; //每kBlockSize记为一个block,block_offset_记录当前block已经写入的偏移量 int block_offset_; // Current offset in block
// crc32c values for all supported record types. These are // pre-computed to reduce the overhead of computing the crc of the // record type stored in the header. uint32_t type_crc_[kMaxRecordType + 1];
Status EmitPhysicalRecord(RecordType type, constchar* ptr, size_t length);
// No copying allowed Writer(const Writer&); voidoperator=(const Writer&); };
Status Writer::AddRecord(const Slice& slice){ constchar* ptr = slice.data(); size_t left = slice.size();
// Fragment the record if necessary and emit it. Note that if slice // is empty, we still want to iterate once to emit a single // zero-length record Status s; bool begin = true; do { //leftover记录block当前可用大小 constint leftover = kBlockSize - block_offset_;//当前32kb块的剩余量 assert(leftover >= 0); //如果block可用大小已经无法写入header,那么补充\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); //Slice构造函数第二个参数表示字符串长度,因此效果上是leftover个'\x00' //leftover size最大为6,因此第一个参数指定6个'\x00' dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover)); } block_offset_ = 0;//更换新快 }
// Invariant: we never leave < kHeaderSize bytes in a block. // block还有剩余可用空间让我们写入一部分数据 // 如果 = 0,也就是剩余只能写入header,那也写入(只是此时不会写入slice里任何数据) assert(kBlockSize - block_offset_ - kHeaderSize >= 0);
RecordType type; constbool end = (left == fragment_length);//相等表示本次可以全部写入 if (begin && end) { type = kFullType;//数据能够一次写入 } elseif (begin) { type = kFirstType;//数据无法一次写入时,标记首次写入 } elseif (end) { type = kLastType;//数据无法一次写入时,标记最后一次写入 } else { type = kMiddleType;//数据无法一次写入时,标记中间写入 }
s = EmitPhysicalRecord(type, ptr, fragment_length); ptr += fragment_length;//下一次slice待写入位置 left -= fragment_length;//slice还有多少没有写 begin = false; } while (s.ok() && left > 0); return s; }
//计算crc: Extend(type_crc, ptr) -> Mask -> EncodeFixed32 // 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 EncodeFixed32(buf, crc);
// Write the header and the payload // 首先写入header: |crc |length |type |,大小为kHeaderSize Status s = dest_->Append(Slice(buf, kHeaderSize)); if (s.ok()) { //接着写入数据,大小为n s = dest_->Append(Slice(ptr, n)); if (s.ok()) { s = dest_->Flush(); } } block_offset_ += kHeaderSize + n; return s; }