github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitpage/array_table_iterator.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 bitpage 16 17 import ( 18 "bytes" 19 "sync" 20 21 "github.com/zuoyebang/bitalosdb/internal/base" 22 "github.com/zuoyebang/bitalosdb/internal/bytepools" 23 ) 24 25 var _ base.InternalIterator = (*arrayTableIterator)(nil) 26 27 type sharedInfo struct { 28 idx int 29 key []byte 30 } 31 32 type arrayTableIterator struct { 33 at *arrayTable 34 intIndexPos int 35 blockIter *pageBlockIterator 36 blockCloser func() 37 iterKey internalKey 38 iterValue []byte 39 keyBuf []byte 40 sharedCache *sharedInfo 41 disableCache bool 42 } 43 44 var atIterPool = sync.Pool{ 45 New: func() interface{} { 46 return &arrayTableIterator{} 47 }, 48 } 49 50 func (ai *arrayTableIterator) findItem() (*internalKey, []byte) { 51 sharedKey1, sharedKey2, value := ai.at.getSharedKV(ai.intIndexPos, ai.sharedCache) 52 if sharedKey1 == nil { 53 return nil, nil 54 } 55 56 var key []byte 57 if sharedKey2 == nil { 58 key = sharedKey1 59 } else { 60 ai.keyBuf = append(ai.keyBuf[:0], sharedKey1...) 61 key = append(ai.keyBuf, sharedKey2...) 62 } 63 64 ai.iterKey = base.MakeInternalSetKey(key) 65 ai.iterValue = value 66 return &ai.iterKey, ai.iterValue 67 } 68 69 func (ai *arrayTableIterator) firstInternal() (*internalKey, []byte) { 70 ai.intIndexPos = 0 71 if ai.at.isNonBlock() { 72 return ai.findItem() 73 } 74 75 if ai.setBlockIter() { 76 return ai.blockIter.First() 77 } 78 79 return nil, nil 80 } 81 82 func (ai *arrayTableIterator) First() (*internalKey, []byte) { 83 return ai.firstInternal() 84 } 85 86 func (ai *arrayTableIterator) nextInternal() (*internalKey, []byte) { 87 if ai.at.isNonBlock() { 88 ai.intIndexPos++ 89 return ai.findItem() 90 } 91 92 if ai.blockIter == nil { 93 return nil, nil 94 } 95 96 ikey, value := ai.blockIter.Next() 97 if ikey != nil { 98 return ikey, value 99 } 100 101 ai.intIndexPos++ 102 if ai.setBlockIter() { 103 return ai.blockIter.First() 104 } 105 106 return nil, nil 107 } 108 109 func (ai *arrayTableIterator) Next() (*internalKey, []byte) { 110 return ai.nextInternal() 111 } 112 113 func (ai *arrayTableIterator) Prev() (*internalKey, []byte) { 114 if ai.at.isNonBlock() { 115 ai.intIndexPos-- 116 return ai.findItem() 117 } 118 119 if ai.blockIter == nil { 120 return nil, nil 121 } 122 123 ikey, value := ai.blockIter.Prev() 124 if ikey != nil { 125 return ikey, value 126 } 127 128 ai.intIndexPos-- 129 if ai.setBlockIter() { 130 return ai.blockIter.Last() 131 } 132 133 return nil, nil 134 } 135 136 func (ai *arrayTableIterator) Last() (*internalKey, []byte) { 137 ai.intIndexPos = ai.at.num - 1 138 if ai.at.isNonBlock() { 139 return ai.findItem() 140 } 141 142 if ai.setBlockIter() { 143 return ai.blockIter.Last() 144 } 145 146 return nil, nil 147 } 148 149 func (ai *arrayTableIterator) SeekGE(key []byte) (*internalKey, []byte) { 150 ai.intIndexPos = ai.at.findKeyByIntIndex(key) 151 if ai.at.isNonBlock() { 152 return ai.findItem() 153 } 154 155 if ai.setBlockIter() { 156 return ai.blockIter.SeekGE(key) 157 } 158 159 return nil, nil 160 } 161 162 func (ai *arrayTableIterator) SeekLT(key []byte) (*internalKey, []byte) { 163 ai.intIndexPos = ai.at.findKeyByIntIndex(key) 164 if ai.at.isNonBlock() { 165 poskey, _ := ai.findItem() 166 if poskey != nil { 167 return ai.Prev() 168 } 169 170 lastKey, lastValue := ai.Last() 171 if lastKey != nil && bytes.Compare(lastKey.UserKey, key) < 0 { 172 return lastKey, lastValue 173 } 174 return nil, nil 175 } 176 177 if ai.intIndexPos >= ai.at.num { 178 ai.intIndexPos = ai.at.num - 1 179 } 180 181 for i := 0; ai.setBlockIter() && i < 2; i++ { 182 ikey, value := ai.blockIter.SeekLT(key) 183 if ikey != nil { 184 return ikey, value 185 } 186 187 ai.intIndexPos-- 188 } 189 190 return nil, nil 191 } 192 193 func (ai *arrayTableIterator) SeekPrefixGE( 194 prefix, key []byte, trySeekUsingNext bool, 195 ) (ikey *internalKey, value []byte) { 196 return ai.SeekGE(key) 197 } 198 199 func (ai *arrayTableIterator) SetBounds(lower, upper []byte) { 200 } 201 202 func (ai *arrayTableIterator) Error() error { 203 return nil 204 } 205 206 func (ai *arrayTableIterator) setBlockIter() bool { 207 if !ai.at.checkPositon(ai.intIndexPos) { 208 ai.closeBlockIter() 209 return false 210 } 211 212 blockBuf, closer, blockExist := ai.at.blockCache.GetBlock(ai.at.cacheID, uint64(ai.intIndexPos)) 213 if !blockExist { 214 _, blockBuf = ai.at.getKV(ai.intIndexPos) 215 if len(blockBuf) > 0 { 216 var compressedBuf []byte 217 compressedBuf, closer = bytepools.ReaderBytePools.GetMaxBytePool() 218 blockBuf, _ = compressDecode(compressedBuf, blockBuf) 219 if !ai.disableCache { 220 ai.at.blockCache.SetBlock(ai.at.cacheID, uint64(ai.intIndexPos), blockBuf) 221 } 222 } else { 223 ai.closeBlockIter() 224 return false 225 } 226 } 227 228 ai.closeBlockIter() 229 230 if closer != nil { 231 ai.blockCloser = closer 232 } 233 234 pb := pageBlock{} 235 openPageBlock(&pb, blockBuf) 236 237 ai.blockIter = pb.newIter(nil) 238 239 return true 240 } 241 242 func (ai *arrayTableIterator) closeBlockIter() { 243 if ai.blockIter != nil { 244 if ai.blockCloser != nil { 245 ai.blockCloser() 246 } 247 248 ai.blockIter.Close() 249 } 250 ai.blockIter = nil 251 ai.blockCloser = nil 252 } 253 254 func (ai *arrayTableIterator) Close() error { 255 ai.closeBlockIter() 256 ai.at = nil 257 ai.intIndexPos = 0 258 ai.iterValue = nil 259 ai.disableCache = false 260 if ai.keyBuf != nil { 261 ai.keyBuf = ai.keyBuf[:0] 262 } 263 if ai.sharedCache != nil { 264 ai.sharedCache.idx = -1 265 ai.sharedCache.key = nil 266 } 267 atIterPool.Put(ai) 268 269 return nil 270 } 271 272 func (ai *arrayTableIterator) String() string { 273 return "arrayTableIterator" 274 }