blob: c09b25f3ccf3f1c1b71946c56c00d1c904213298 [file] [log] [blame]
Manish R Jainffd14f02017-09-28 08:54:331package badger
2
3import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 "hash/crc32"
8
9 "github.com/dgraph-io/badger/y"
10)
11
12type valuePointer struct {
13 Fid uint32
14 Len uint32
15 Offset uint32
16}
17
18func (p valuePointer) Less(o valuePointer) bool {
19 if p.Fid != o.Fid {
20 return p.Fid < o.Fid
21 }
22 if p.Offset != o.Offset {
23 return p.Offset < o.Offset
24 }
25 return p.Len < o.Len
26}
27
28func (p valuePointer) IsZero() bool {
29 return p.Fid == 0 && p.Offset == 0 && p.Len == 0
30}
31
32const vptrSize = 12
33
34// Encode encodes Pointer into byte buffer.
35func (p valuePointer) Encode(b []byte) []byte {
36 binary.BigEndian.PutUint32(b[:4], p.Fid)
37 binary.BigEndian.PutUint32(b[4:8], p.Len)
38 binary.BigEndian.PutUint32(b[8:12], p.Offset)
39 return b[:vptrSize]
40}
41
42func (p *valuePointer) Decode(b []byte) {
43 p.Fid = binary.BigEndian.Uint32(b[:4])
44 p.Len = binary.BigEndian.Uint32(b[4:8])
45 p.Offset = binary.BigEndian.Uint32(b[8:12])
46}
47
48// header is used in value log as a header before Entry.
49type header struct {
50 klen uint32
51 vlen uint32
52 meta byte
53 userMeta byte
54}
55
56const (
57 headerBufSize = 10
58)
59
60func (h header) Encode(out []byte) {
61 y.AssertTrue(len(out) >= headerBufSize)
62 binary.BigEndian.PutUint32(out[0:4], h.klen)
63 binary.BigEndian.PutUint32(out[4:8], h.vlen)
64 out[8] = h.meta
65 out[9] = h.userMeta
66}
67
68// Decodes h from buf.
69func (h *header) Decode(buf []byte) {
70 h.klen = binary.BigEndian.Uint32(buf[0:4])
71 h.vlen = binary.BigEndian.Uint32(buf[4:8])
72 h.meta = buf[8]
73 h.userMeta = buf[9]
74}
75
76// Entry provides Key, Value and if required, CASCounterCheck to kv.BatchSet() API.
77// If CASCounterCheck is provided, it would be compared against the current casCounter
78// assigned to this key-value. Set be done on this key only if the counters match.
79type Entry struct {
80 Key []byte
81 Value []byte
82 Meta byte
83 UserMeta byte
84
85 // Fields maintained internally.
86 offset uint32
87}
88
89func (e *Entry) estimateSize(threshold int) int {
90 if len(e.Value) < threshold {
91 return len(e.Key) + len(e.Value) + 2 // Meta, UserMeta
92 }
93 return len(e.Key) + 12 + 2 // 12 for ValuePointer, 2 for metas.
94}
95
96// Encodes e to buf. Returns number of bytes written.
97func encodeEntry(e *Entry, buf *bytes.Buffer) (int, error) {
98 var h header
99 h.klen = uint32(len(e.Key))
100 h.vlen = uint32(len(e.Value))
101 h.meta = e.Meta
102 h.userMeta = e.UserMeta
103
104 var headerEnc [headerBufSize]byte
105 h.Encode(headerEnc[:])
106
107 hash := crc32.New(y.CastagnoliCrcTable)
108
109 buf.Write(headerEnc[:])
110 hash.Write(headerEnc[:])
111
112 buf.Write(e.Key)
113 hash.Write(e.Key)
114
115 buf.Write(e.Value)
116 hash.Write(e.Value)
117
118 var crcBuf [4]byte
119 binary.BigEndian.PutUint32(crcBuf[:], hash.Sum32())
120 buf.Write(crcBuf[:])
121
122 return len(headerEnc) + len(e.Key) + len(e.Value) + len(crcBuf), nil
123}
124
125func (e Entry) print(prefix string) {
126 fmt.Printf("%s Key: %s Meta: %d UserMeta: %d Offset: %d len(val)=%d",
127 prefix, e.Key, e.Meta, e.UserMeta, e.offset, len(e.Value))
128}