/** * WriteBatch逻辑协议=协议头+协议体 * wal日志读出来Block->分割成fragment物理协议->刨去物理协议头拿到fragment协议体->拼成record->就是WriteBatch逻辑协议 * 这个里面存放的就是WriteBatch逻辑协议的二进制 */ std::string rep_; // See comment in write_batch.cc for the format of rep_
/** * 键值对编码到WriteBatch协议 * 1 协议头里面的count字段 * 2 TLV协议 tag+cf id+key长度+key+value长度+value */ Status WriteBatchInternal::Put(WriteBatch* b, uint32_t column_family_id, const Slice& key, const Slice& value){ if (key.size() > size_t{std::numeric_limits<uint32_t>::max()}) { return Status::InvalidArgument("key is too large"); } if (value.size() > size_t{std::numeric_limits<uint32_t>::max()}) { return Status::InvalidArgument("value is too large"); }
LocalSavePoint save(b); // 协议头里面count+1编码进去 WriteBatchInternal::SetCount(b, WriteBatchInternal::Count(b) + 1); if (column_family_id == 0) { // tag标识 // 默认cf约定在编码里面不需要cf id b->rep_.push_back(static_cast<char>(kTypeValue)); } else { b->rep_.push_back(static_cast<char>(kTypeColumnFamilyValue)); // cf id PutVarint32(&b->rep_, column_family_id); } // key的长度+key PutLengthPrefixedSlice(&b->rep_, key); // value的长度+value PutLengthPrefixedSlice(&b->rep_, value); b->content_flags_.store( b->content_flags_.load(std::memory_order_relaxed) | ContentFlags::HAS_PUT, std::memory_order_relaxed); if (b->prot_info_ != nullptr) { // Technically the optype could've been `kTypeColumnFamilyValue` with the // CF ID encoded in the `WriteBatch`. That distinction is unimportant // however since we verify CF ID is correct, as well as all other fields // (a missing/extra encoded CF ID would corrupt another field). It is // convenient to consolidate on `kTypeValue` here as that is what will be // inserted into memtable. b->prot_info_->entries_.emplace_back(ProtectionInfo64() .ProtectKVO(key, value, kTypeValue) .ProtectC(column_family_id)); } return save.commit(); }