123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- package badger
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "hash/crc32"
- "github.com/dgraph-io/badger/y"
- )
- type valuePointer struct {
- Fid uint32
- Len uint32
- Offset uint32
- }
- func (p valuePointer) Less(o valuePointer) bool {
- if p.Fid != o.Fid {
- return p.Fid < o.Fid
- }
- if p.Offset != o.Offset {
- return p.Offset < o.Offset
- }
- return p.Len < o.Len
- }
- func (p valuePointer) IsZero() bool {
- return p.Fid == 0 && p.Offset == 0 && p.Len == 0
- }
- const vptrSize = 12
- // Encode encodes Pointer into byte buffer.
- func (p valuePointer) Encode(b []byte) []byte {
- binary.BigEndian.PutUint32(b[:4], p.Fid)
- binary.BigEndian.PutUint32(b[4:8], p.Len)
- binary.BigEndian.PutUint32(b[8:12], p.Offset)
- return b[:vptrSize]
- }
- func (p *valuePointer) Decode(b []byte) {
- p.Fid = binary.BigEndian.Uint32(b[:4])
- p.Len = binary.BigEndian.Uint32(b[4:8])
- p.Offset = binary.BigEndian.Uint32(b[8:12])
- }
- // header is used in value log as a header before Entry.
- type header struct {
- klen uint32
- vlen uint32
- expiresAt uint64
- meta byte
- userMeta byte
- }
- const (
- headerBufSize = 18
- )
- func (h header) Encode(out []byte) {
- y.AssertTrue(len(out) >= headerBufSize)
- binary.BigEndian.PutUint32(out[0:4], h.klen)
- binary.BigEndian.PutUint32(out[4:8], h.vlen)
- binary.BigEndian.PutUint64(out[8:16], h.expiresAt)
- out[16] = h.meta
- out[17] = h.userMeta
- }
- // Decodes h from buf.
- func (h *header) Decode(buf []byte) {
- h.klen = binary.BigEndian.Uint32(buf[0:4])
- h.vlen = binary.BigEndian.Uint32(buf[4:8])
- h.expiresAt = binary.BigEndian.Uint64(buf[8:16])
- h.meta = buf[16]
- h.userMeta = buf[17]
- }
- // Entry provides Key, Value, UserMeta and ExpiresAt. This struct can be used by the user to set data.
- type Entry struct {
- Key []byte
- Value []byte
- UserMeta byte
- ExpiresAt uint64 // time.Unix
- meta byte
- // Fields maintained internally.
- offset uint32
- }
- func (e *Entry) estimateSize(threshold int) int {
- if len(e.Value) < threshold {
- return len(e.Key) + len(e.Value) + 2 // Meta, UserMeta
- }
- return len(e.Key) + 12 + 2 // 12 for ValuePointer, 2 for metas.
- }
- // Encodes e to buf. Returns number of bytes written.
- func encodeEntry(e *Entry, buf *bytes.Buffer) (int, error) {
- h := header{
- klen: uint32(len(e.Key)),
- vlen: uint32(len(e.Value)),
- expiresAt: e.ExpiresAt,
- meta: e.meta,
- userMeta: e.UserMeta,
- }
- var headerEnc [headerBufSize]byte
- h.Encode(headerEnc[:])
- hash := crc32.New(y.CastagnoliCrcTable)
- buf.Write(headerEnc[:])
- hash.Write(headerEnc[:])
- buf.Write(e.Key)
- hash.Write(e.Key)
- buf.Write(e.Value)
- hash.Write(e.Value)
- var crcBuf [4]byte
- binary.BigEndian.PutUint32(crcBuf[:], hash.Sum32())
- buf.Write(crcBuf[:])
- return len(headerEnc) + len(e.Key) + len(e.Value) + len(crcBuf), nil
- }
- func (e Entry) print(prefix string) {
- fmt.Printf("%s Key: %s Meta: %d UserMeta: %d Offset: %d len(val)=%d",
- prefix, e.Key, e.meta, e.UserMeta, e.offset, len(e.Value))
- }
|