github.com/flower-corp/rosedb@v1.1.2-0.20230117132829-21dc4f7b319a/logfile/log_entry.go (about) 1 package logfile 2 3 import ( 4 "encoding/binary" 5 "hash/crc32" 6 ) 7 8 // MaxHeaderSize max entry header size. 9 // crc32 typ kSize vSize expiredAt 10 // 4 + 1 + 5 + 5 + 10 = 25 (refer to binary.MaxVarintLen32 and binary.MaxVarintLen64) 11 const MaxHeaderSize = 25 12 13 // EntryType type of Entry. 14 type EntryType byte 15 16 const ( 17 // TypeDelete represents entry type is delete. 18 TypeDelete EntryType = iota + 1 19 // TypeListMeta represents entry is list meta. 20 TypeListMeta 21 ) 22 23 // LogEntry is the data will be appended in log file. 24 type LogEntry struct { 25 Key []byte 26 Value []byte 27 ExpiredAt int64 // time.Unix 28 Type EntryType 29 } 30 31 type entryHeader struct { 32 crc32 uint32 // check sum 33 typ EntryType 34 kSize uint32 35 vSize uint32 36 expiredAt int64 // time.Unix 37 } 38 39 // EncodeEntry will encode entry into a byte slice. 40 // The encoded Entry looks like: 41 // +-------+--------+----------+------------+-----------+-------+---------+ 42 // | crc | type | key size | value size | expiresAt | key | value | 43 // +-------+--------+----------+------------+-----------+-------+---------+ 44 // |------------------------HEADER----------------------| 45 // |--------------------------crc check---------------------------| 46 func EncodeEntry(e *LogEntry) ([]byte, int) { 47 if e == nil { 48 return nil, 0 49 } 50 header := make([]byte, MaxHeaderSize) 51 // encode header. 52 header[4] = byte(e.Type) 53 var index = 5 54 index += binary.PutVarint(header[index:], int64(len(e.Key))) 55 index += binary.PutVarint(header[index:], int64(len(e.Value))) 56 index += binary.PutVarint(header[index:], e.ExpiredAt) 57 58 var size = index + len(e.Key) + len(e.Value) 59 buf := make([]byte, size) 60 copy(buf[:index], header[:]) 61 // key and value. 62 copy(buf[index:], e.Key) 63 copy(buf[index+len(e.Key):], e.Value) 64 65 // crc32. 66 crc := crc32.ChecksumIEEE(buf[4:]) 67 binary.LittleEndian.PutUint32(buf[:4], crc) 68 return buf, size 69 } 70 71 func decodeHeader(buf []byte) (*entryHeader, int64) { 72 if len(buf) <= 4 { 73 return nil, 0 74 } 75 h := &entryHeader{ 76 crc32: binary.LittleEndian.Uint32(buf[:4]), 77 typ: EntryType(buf[4]), 78 } 79 var index = 5 80 ksize, n := binary.Varint(buf[index:]) 81 h.kSize = uint32(ksize) 82 index += n 83 84 vsize, n := binary.Varint(buf[index:]) 85 h.vSize = uint32(vsize) 86 index += n 87 88 expiredAt, n := binary.Varint(buf[index:]) 89 h.expiredAt = expiredAt 90 return h, int64(index + n) 91 } 92 93 func getEntryCrc(e *LogEntry, h []byte) uint32 { 94 if e == nil { 95 return 0 96 } 97 crc := crc32.ChecksumIEEE(h[:]) 98 crc = crc32.Update(crc, crc32.IEEETable, e.Key) 99 crc = crc32.Update(crc, crc32.IEEETable, e.Value) 100 return crc 101 }