github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/internal/cache/lfucache/array_table.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package lfucache 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "fmt" 21 "os" 22 "sort" 23 24 "github.com/zuoyebang/bitalosdb/internal/cache/lfucache/internal/arenaskl" 25 "github.com/zuoyebang/bitalosdb/internal/manual" 26 ) 27 28 const ( 29 itemHeaderLen = 2 30 ) 31 32 type arrayTable struct { 33 id int64 34 num int 35 index []uint32 36 arenaBuf []byte 37 arena *arenaskl.Arena 38 } 39 40 func checkArrayTable(obj interface{}) { 41 at := obj.(*arrayTable) 42 if at.arenaBuf != nil { 43 fmt.Fprintf(os.Stderr, "%p: arrayTable(%d) buffer was not freed\n", at.arenaBuf, at.id) 44 os.Exit(1) 45 } 46 } 47 48 func newArrayTable(id int64, size int) *arrayTable { 49 arenaBuf := manual.New(size + 8) 50 at := &arrayTable{ 51 id: id, 52 num: 0, 53 arenaBuf: arenaBuf, 54 arena: arenaskl.NewArena(arenaBuf), 55 } 56 57 return at 58 } 59 60 func arrayTableEntrySize(keyBytes, valueBytes int) int { 61 return keyBytes + valueBytes + itemHeaderLen 62 } 63 64 func (t *arrayTable) add(key []byte, value []byte) error { 65 keySize := len(key) 66 valueSize := len(value) 67 itemSize := arrayTableEntrySize(keySize, valueSize) 68 itemOffset, err := t.arena.AllocNoAlign(uint32(itemSize)) 69 if err != nil { 70 return err 71 } 72 73 binary.BigEndian.PutUint16(t.arena.GetBytes(itemOffset, itemHeaderLen), uint16(keySize)) 74 copy(t.arena.GetBytes(itemOffset+itemHeaderLen, uint32(keySize)), key) 75 copy(t.arena.GetBytes(itemOffset+itemHeaderLen+uint32(keySize), uint32(valueSize)), value) 76 77 t.index = append(t.index, itemOffset) 78 t.num++ 79 80 return nil 81 } 82 83 func (t *arrayTable) validIndexPos(i int) bool { 84 return i >= 0 && i < t.num 85 } 86 87 func (t *arrayTable) get(key []byte) ([]byte, bool, internalKeyKind) { 88 indexPos := sort.Search(t.num, func(i int) bool { 89 return bytes.Compare(t.getKey(i), key) != -1 90 }) 91 92 k, v := t.getKV(indexPos) 93 if k == nil || bytes.Compare(k, key) != 0 { 94 return nil, false, internalKeyKindInvalid 95 } 96 97 return v, true, internalKeyKindSet 98 } 99 100 func (t *arrayTable) getKey(i int) []byte { 101 if !t.validIndexPos(i) { 102 return nil 103 } 104 105 itemOffset := t.index[i] 106 keySize := uint32(binary.BigEndian.Uint16(t.arena.GetBytes(itemOffset, itemHeaderLen))) 107 key := t.arena.GetBytes(itemOffset+itemHeaderLen, keySize) 108 return key 109 } 110 111 func (t *arrayTable) getKV(i int) ([]byte, []byte) { 112 if !t.validIndexPos(i) { 113 return nil, nil 114 } 115 116 var itemSize uint32 117 itemOffset := t.index[i] 118 if i == t.num-1 { 119 itemSize = t.arena.Size() - itemOffset 120 } else { 121 itemSize = t.index[i+1] - itemOffset 122 } 123 124 keySize := uint32(binary.BigEndian.Uint16(t.arena.GetBytes(itemOffset, itemHeaderLen))) 125 key := t.arena.GetBytes(itemOffset+itemHeaderLen, keySize) 126 valueSize := itemSize - keySize - itemHeaderLen 127 value := t.arena.GetBytes(itemOffset+itemHeaderLen+keySize, valueSize) 128 129 return key, value 130 } 131 132 func (t *arrayTable) seek(key []byte) (*internalKey, []byte) { 133 iter := t.newIter(nil) 134 defer iter.Close() 135 136 ik, value := iter.SeekGE(key) 137 if ik == nil || !bytes.Equal(ik.UserKey, key) { 138 return nil, nil 139 } 140 return ik, value 141 } 142 143 func (t *arrayTable) newIter(o *iterOptions) internalIterator { 144 iter := iterPool.Get().(*arrayTableIterator) 145 *iter = arrayTableIterator{ 146 at: t, 147 indexPos: 0, 148 iterKey: new(internalKey), 149 iterValue: nil, 150 } 151 return iter 152 } 153 154 func (t *arrayTable) newFlushIter(o *iterOptions, bytesFlushed *uint64) internalIterator { 155 iter := &arrayTableFlushIterator{ 156 arrayTableIterator: arrayTableIterator{at: t, iterKey: new(internalKey)}, 157 bytesIterated: bytesFlushed, 158 } 159 return iter 160 } 161 162 func (t *arrayTable) inuseBytes() uint64 { 163 return uint64(t.arena.Size()) 164 } 165 166 func (t *arrayTable) totalBytes() uint64 { 167 return uint64(t.arena.Capacity()) 168 } 169 170 func (t *arrayTable) close() error { 171 return nil 172 } 173 174 func (t *arrayTable) readyForFlush() bool { 175 return true 176 } 177 178 func (t *arrayTable) getID() int64 { 179 return t.id 180 } 181 182 func (t *arrayTable) count() int { 183 return t.num 184 }