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: Status EmitPhysicalRecord(RecordType type, constchar* ptr, size_t length);
WritableFile* dest_; int block_offset_; // Curr
// 预计算的crc // 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 Writer::AddRecord(const Slice& slice){ constchar* ptr = slice.data(); size_t left = slice.size(); // left表示剩余多少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 { constint leftover = kBlockSize - block_offset_; // 当前32kb的块的剩余量 assert(leftover >= 0); if (leftover < kHeaderSize) { // 剩余量 < 一个record的header size // Switch to a new block if (leftover > 0) { // Fill the trailer (literal below relies on kHeaderSize being 7) static_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);
Status Writer::EmitPhysicalRecord(RecordType t, constchar* ptr, size_t length){ assert(length <= 0xffff); // Must fit in two bytes 一个块最多写32kb,即2^15,至少需要15个bit,所以需要2个字节(解释了为什么要用0xffff) assert(block_offset_ + kHeaderSize + length <= kBlockSize);
// Compute the crc of the record type and the payload. uint32_t crc = crc32c::Extend(type_crc_[t], ptr, length); crc = crc32c::Mask(crc); // Adjust for storage // crc校验 EncodeFixed32(buf, crc);
// Write the header and the payload Status s = dest_->Append(Slice(buf, kHeaderSize)); // 加入heder if (s.ok()) { s = dest_->Append(Slice(ptr, length)); // 加如实际数据 if (s.ok()) { s = dest_->Flush(); } } block_offset_ += kHeaderSize + length; return s; }