structs.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package badger
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "hash/crc32"
  7. "github.com/dgraph-io/badger/y"
  8. )
  9. type valuePointer struct {
  10. Fid uint32
  11. Len uint32
  12. Offset uint32
  13. }
  14. func (p valuePointer) Less(o valuePointer) bool {
  15. if p.Fid != o.Fid {
  16. return p.Fid < o.Fid
  17. }
  18. if p.Offset != o.Offset {
  19. return p.Offset < o.Offset
  20. }
  21. return p.Len < o.Len
  22. }
  23. func (p valuePointer) IsZero() bool {
  24. return p.Fid == 0 && p.Offset == 0 && p.Len == 0
  25. }
  26. const vptrSize = 12
  27. // Encode encodes Pointer into byte buffer.
  28. func (p valuePointer) Encode(b []byte) []byte {
  29. binary.BigEndian.PutUint32(b[:4], p.Fid)
  30. binary.BigEndian.PutUint32(b[4:8], p.Len)
  31. binary.BigEndian.PutUint32(b[8:12], p.Offset)
  32. return b[:vptrSize]
  33. }
  34. func (p *valuePointer) Decode(b []byte) {
  35. p.Fid = binary.BigEndian.Uint32(b[:4])
  36. p.Len = binary.BigEndian.Uint32(b[4:8])
  37. p.Offset = binary.BigEndian.Uint32(b[8:12])
  38. }
  39. // header is used in value log as a header before Entry.
  40. type header struct {
  41. klen uint32
  42. vlen uint32
  43. expiresAt uint64
  44. meta byte
  45. userMeta byte
  46. }
  47. const (
  48. headerBufSize = 18
  49. )
  50. func (h header) Encode(out []byte) {
  51. y.AssertTrue(len(out) >= headerBufSize)
  52. binary.BigEndian.PutUint32(out[0:4], h.klen)
  53. binary.BigEndian.PutUint32(out[4:8], h.vlen)
  54. binary.BigEndian.PutUint64(out[8:16], h.expiresAt)
  55. out[16] = h.meta
  56. out[17] = h.userMeta
  57. }
  58. // Decodes h from buf.
  59. func (h *header) Decode(buf []byte) {
  60. h.klen = binary.BigEndian.Uint32(buf[0:4])
  61. h.vlen = binary.BigEndian.Uint32(buf[4:8])
  62. h.expiresAt = binary.BigEndian.Uint64(buf[8:16])
  63. h.meta = buf[16]
  64. h.userMeta = buf[17]
  65. }
  66. // Entry provides Key, Value, UserMeta and ExpiresAt. This struct can be used by the user to set data.
  67. type Entry struct {
  68. Key []byte
  69. Value []byte
  70. UserMeta byte
  71. ExpiresAt uint64 // time.Unix
  72. meta byte
  73. // Fields maintained internally.
  74. offset uint32
  75. }
  76. func (e *Entry) estimateSize(threshold int) int {
  77. if len(e.Value) < threshold {
  78. return len(e.Key) + len(e.Value) + 2 // Meta, UserMeta
  79. }
  80. return len(e.Key) + 12 + 2 // 12 for ValuePointer, 2 for metas.
  81. }
  82. // Encodes e to buf. Returns number of bytes written.
  83. func encodeEntry(e *Entry, buf *bytes.Buffer) (int, error) {
  84. h := header{
  85. klen: uint32(len(e.Key)),
  86. vlen: uint32(len(e.Value)),
  87. expiresAt: e.ExpiresAt,
  88. meta: e.meta,
  89. userMeta: e.UserMeta,
  90. }
  91. var headerEnc [headerBufSize]byte
  92. h.Encode(headerEnc[:])
  93. hash := crc32.New(y.CastagnoliCrcTable)
  94. buf.Write(headerEnc[:])
  95. hash.Write(headerEnc[:])
  96. buf.Write(e.Key)
  97. hash.Write(e.Key)
  98. buf.Write(e.Value)
  99. hash.Write(e.Value)
  100. var crcBuf [4]byte
  101. binary.BigEndian.PutUint32(crcBuf[:], hash.Sum32())
  102. buf.Write(crcBuf[:])
  103. return len(headerEnc) + len(e.Key) + len(e.Value) + len(crcBuf), nil
  104. }
  105. func (e Entry) print(prefix string) {
  106. fmt.Printf("%s Key: %s Meta: %d UserMeta: %d Offset: %d len(val)=%d",
  107. prefix, e.Key, e.meta, e.UserMeta, e.offset, len(e.Value))
  108. }