github.com/pingcap/badger@v1.5.1-0.20230103063557-828f39b09b6d/structs.go (about)

     1  package badger
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"hash/crc32"
     8  
     9  	"github.com/pingcap/badger/y"
    10  )
    11  
    12  // header is used in value log as a header before Entry.
    13  type header struct {
    14  	klen uint32
    15  	vlen uint32
    16  	ver  uint64
    17  	meta byte
    18  
    19  	// umlen is the length of UserMeta
    20  	umlen byte
    21  }
    22  
    23  const (
    24  	headerBufSize       = 18
    25  	metaNotEntryEncoded = 0
    26  )
    27  
    28  func (h header) Encode(out []byte) {
    29  	y.Assert(len(out) >= headerBufSize)
    30  	// Because meta can never be 0xff, so 0x00 in vlog file indicates there is not an entry.
    31  	out[0] = ^h.meta
    32  	binary.BigEndian.PutUint32(out[1:5], h.klen)
    33  	binary.BigEndian.PutUint32(out[5:9], h.vlen)
    34  	binary.BigEndian.PutUint64(out[9:17], h.ver)
    35  	out[17] = h.umlen
    36  }
    37  
    38  // Decodes h from buf.
    39  func (h *header) Decode(buf []byte) {
    40  	h.meta = ^buf[0]
    41  	h.klen = binary.BigEndian.Uint32(buf[1:5])
    42  	h.vlen = binary.BigEndian.Uint32(buf[5:9])
    43  	h.ver = binary.BigEndian.Uint64(buf[9:17])
    44  	h.umlen = buf[17]
    45  }
    46  
    47  func isEncodedHeader(data []byte) bool {
    48  	if len(data) < 1 {
    49  		return false
    50  	}
    51  	return data[0] != metaNotEntryEncoded
    52  }
    53  
    54  // Entry provides Key, Value, UserMeta. This struct can be used by the user to set data.
    55  type Entry struct {
    56  	Key       y.Key
    57  	Value     []byte
    58  	UserMeta  []byte
    59  	meta      byte
    60  	logOffset logOffset
    61  
    62  	// Fields maintained internally.
    63  	offset uint32
    64  }
    65  
    66  func (e *Entry) SetDelete() {
    67  	e.meta |= bitDelete
    68  }
    69  
    70  func (e *Entry) estimateSize() int {
    71  	return e.Key.Len() + len(e.Value) + len(e.UserMeta) + 2 // Meta, UserMeta
    72  }
    73  
    74  // Encodes e to buf. Returns number of bytes written.
    75  func encodeEntry(e *Entry, buf *bytes.Buffer) (int, error) {
    76  	h := header{
    77  		klen:  uint32(len(e.Key.UserKey)),
    78  		vlen:  uint32(len(e.Value)),
    79  		ver:   e.Key.Version,
    80  		meta:  e.meta,
    81  		umlen: byte(len(e.UserMeta)),
    82  	}
    83  
    84  	var headerEnc [headerBufSize]byte
    85  	h.Encode(headerEnc[:])
    86  
    87  	hash := crc32.New(y.CastagnoliCrcTable)
    88  
    89  	buf.Write(headerEnc[:])
    90  	hash.Write(headerEnc[:])
    91  
    92  	buf.Write(e.UserMeta)
    93  	hash.Write(e.UserMeta)
    94  
    95  	buf.Write(e.Key.UserKey)
    96  	hash.Write(e.Key.UserKey)
    97  
    98  	buf.Write(e.Value)
    99  	hash.Write(e.Value)
   100  
   101  	var crcBuf [4]byte
   102  	binary.BigEndian.PutUint32(crcBuf[:], hash.Sum32())
   103  	buf.Write(crcBuf[:])
   104  
   105  	return len(headerEnc) + len(e.UserMeta) + len(e.Key.UserKey) + len(e.Value) + len(crcBuf), nil
   106  }
   107  
   108  func (e Entry) print(prefix string) {
   109  	fmt.Printf("%s Key: %s Meta: %d UserMeta: %v Offset: %d len(val)=%d",
   110  		prefix, e.Key, e.meta, e.UserMeta, e.offset, len(e.Value))
   111  }