go-common/vendor/github.com/dgraph-io/badger/structs.go

133 lines
2.9 KiB
Go

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))
}