encodeEntry will encode entry to the buf layout of entry +--------+-----+-------+-------+ | header | key | value | crc32 | +--------+-----+-------+-------+
(e *Entry, buf *bytes.Buffer, offset uint32)
| 97 | // | header | key | value | crc32 | |
| 98 | // +--------+-----+-------+-------+ |
| 99 | func (lf *logFile) encodeEntry(e *Entry, buf *bytes.Buffer, offset uint32) (int, error) { |
| 100 | h := header{ |
| 101 | klen: uint32(len(e.Key)), |
| 102 | vlen: uint32(len(e.Value)), |
| 103 | expiresAt: e.ExpiresAt, |
| 104 | meta: e.meta, |
| 105 | userMeta: e.UserMeta, |
| 106 | } |
| 107 | |
| 108 | // encode header. |
| 109 | var headerEnc [maxHeaderSize]byte |
| 110 | sz := h.Encode(headerEnc[:]) |
| 111 | y.Check2(buf.Write(headerEnc[:sz])) |
| 112 | // write hash. |
| 113 | hash := crc32.New(y.CastagnoliCrcTable) |
| 114 | y.Check2(hash.Write(headerEnc[:sz])) |
| 115 | // we'll encrypt only key and value. |
| 116 | if lf.encryptionEnabled() { |
| 117 | // TODO: no need to allocate the bytes. we can calculate the encrypted buf one by one |
| 118 | // since we're using ctr mode of AES encryption. Ordering won't changed. Need some |
| 119 | // refactoring in XORBlock which will work like stream cipher. |
| 120 | eBuf := make([]byte, 0, len(e.Key)+len(e.Value)) |
| 121 | eBuf = append(eBuf, e.Key...) |
| 122 | eBuf = append(eBuf, e.Value...) |
| 123 | var err error |
| 124 | eBuf, err = y.XORBlock(eBuf, lf.dataKey.Data, lf.generateIV(offset)) |
| 125 | if err != nil { |
| 126 | return 0, y.Wrapf(err, "Error while encoding entry for vlog.") |
| 127 | } |
| 128 | // write encrypted buf. |
| 129 | y.Check2(buf.Write(eBuf)) |
| 130 | // write the hash. |
| 131 | y.Check2(hash.Write(eBuf)) |
| 132 | } else { |
| 133 | // Encryption is disabled so writing directly to the buffer. |
| 134 | // write key. |
| 135 | y.Check2(buf.Write(e.Key)) |
| 136 | // write key hash. |
| 137 | y.Check2(hash.Write(e.Key)) |
| 138 | // write value. |
| 139 | y.Check2(buf.Write(e.Value)) |
| 140 | // write value hash. |
| 141 | y.Check2(hash.Write(e.Value)) |
| 142 | } |
| 143 | // write crc32 hash. |
| 144 | var crcBuf [crc32.Size]byte |
| 145 | binary.BigEndian.PutUint32(crcBuf[:], hash.Sum32()) |
| 146 | y.Check2(buf.Write(crcBuf[:])) |
| 147 | // return encoded length. |
| 148 | return len(headerEnc[:sz]) + len(e.Key) + len(e.Value) + len(crcBuf), nil |
| 149 | } |
| 150 | |
| 151 | func (lf *logFile) decodeEntry(buf []byte, offset uint32) (*Entry, error) { |
| 152 | var h header |