github.com/KinWaiYuen/client-go/v2@v2.5.4/internal/unionstore/memdb_iterator.go (about) 1 // Copyright 2021 TiKV Authors 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 // NOTE: The code in this file is based on code from the 16 // TiDB project, licensed under the Apache License v 2.0 17 // 18 // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/unionstore/memdb_iterator.go 19 // 20 21 // Copyright 2020 PingCAP, Inc. 22 // 23 // Licensed under the Apache License, Version 2.0 (the "License"); 24 // you may not use this file except in compliance with the License. 25 // You may obtain a copy of the License at 26 // 27 // http://www.apache.org/licenses/LICENSE-2.0 28 // 29 // Unless required by applicable law or agreed to in writing, software 30 // distributed under the License is distributed on an "AS IS" BASIS, 31 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 // See the License for the specific language governing permissions and 33 // limitations under the License. 34 35 package unionstore 36 37 import ( 38 "bytes" 39 40 "github.com/KinWaiYuen/client-go/v2/kv" 41 ) 42 43 // MemdbIterator is an Iterator with KeyFlags related functions. 44 type MemdbIterator struct { 45 db *MemDB 46 curr memdbNodeAddr 47 start []byte 48 end []byte 49 reverse bool 50 includeFlags bool 51 } 52 53 // Iter creates an Iterator positioned on the first entry that k <= entry's key. 54 // If such entry is not found, it returns an invalid Iterator with no error. 55 // It yields only keys that < upperBound. If upperBound is nil, it means the upperBound is unbounded. 56 // The Iterator must be Closed after use. 57 func (db *MemDB) Iter(k []byte, upperBound []byte) (Iterator, error) { 58 i := &MemdbIterator{ 59 db: db, 60 start: k, 61 end: upperBound, 62 } 63 i.init() 64 return i, nil 65 } 66 67 // IterReverse creates a reversed Iterator positioned on the first entry which key is less than k. 68 // The returned iterator will iterate from greater key to smaller key. 69 // If k is nil, the returned iterator will be positioned at the last key. 70 // TODO: Add lower bound limit 71 func (db *MemDB) IterReverse(k []byte) (Iterator, error) { 72 i := &MemdbIterator{ 73 db: db, 74 end: k, 75 reverse: true, 76 } 77 i.init() 78 return i, nil 79 } 80 81 // IterWithFlags returns a MemdbIterator. 82 func (db *MemDB) IterWithFlags(k []byte, upperBound []byte) *MemdbIterator { 83 i := &MemdbIterator{ 84 db: db, 85 start: k, 86 end: upperBound, 87 includeFlags: true, 88 } 89 i.init() 90 return i 91 } 92 93 // IterReverseWithFlags returns a reversed MemdbIterator. 94 func (db *MemDB) IterReverseWithFlags(k []byte) *MemdbIterator { 95 i := &MemdbIterator{ 96 db: db, 97 end: k, 98 reverse: true, 99 includeFlags: true, 100 } 101 i.init() 102 return i 103 } 104 105 func (i *MemdbIterator) init() { 106 if i.reverse { 107 if len(i.end) == 0 { 108 i.seekToLast() 109 } else { 110 i.seek(i.end) 111 } 112 } else { 113 if len(i.start) == 0 { 114 i.seekToFirst() 115 } else { 116 i.seek(i.start) 117 } 118 } 119 120 if i.isFlagsOnly() && !i.includeFlags { 121 err := i.Next() 122 _ = err // memdbIterator will never fail 123 } 124 } 125 126 // Valid returns true if the current iterator is valid. 127 func (i *MemdbIterator) Valid() bool { 128 if !i.reverse { 129 return !i.curr.isNull() && (i.end == nil || bytes.Compare(i.Key(), i.end) < 0) 130 } 131 return !i.curr.isNull() 132 } 133 134 // Flags returns flags belong to current iterator. 135 func (i *MemdbIterator) Flags() kv.KeyFlags { 136 return i.curr.getKeyFlags() 137 } 138 139 // UpdateFlags updates and apply with flagsOp. 140 func (i *MemdbIterator) UpdateFlags(ops ...kv.FlagsOp) { 141 origin := i.curr.getKeyFlags() 142 n := kv.ApplyFlagsOps(origin, ops...) 143 i.curr.setKeyFlags(n) 144 } 145 146 // HasValue returns false if it is flags only. 147 func (i *MemdbIterator) HasValue() bool { 148 return !i.isFlagsOnly() 149 } 150 151 // Key returns current key. 152 func (i *MemdbIterator) Key() []byte { 153 return i.curr.getKey() 154 } 155 156 // Handle returns MemKeyHandle with the current position. 157 func (i *MemdbIterator) Handle() MemKeyHandle { 158 return MemKeyHandle{ 159 idx: uint16(i.curr.addr.idx), 160 off: i.curr.addr.off, 161 } 162 } 163 164 // Value returns the value. 165 func (i *MemdbIterator) Value() []byte { 166 return i.db.vlog.getValue(i.curr.vptr) 167 } 168 169 // Next goes the next position. 170 func (i *MemdbIterator) Next() error { 171 for { 172 if i.reverse { 173 i.curr = i.db.predecessor(i.curr) 174 } else { 175 i.curr = i.db.successor(i.curr) 176 } 177 178 // We need to skip persistent flags only nodes. 179 if i.includeFlags || !i.isFlagsOnly() { 180 break 181 } 182 } 183 return nil 184 } 185 186 // Close closes the current iterator. 187 func (i *MemdbIterator) Close() {} 188 189 func (i *MemdbIterator) seekToFirst() { 190 y := memdbNodeAddr{nil, nullAddr} 191 x := i.db.getNode(i.db.root) 192 193 for !x.isNull() { 194 y = x 195 x = y.getLeft(i.db) 196 } 197 198 i.curr = y 199 } 200 201 func (i *MemdbIterator) seekToLast() { 202 y := memdbNodeAddr{nil, nullAddr} 203 x := i.db.getNode(i.db.root) 204 205 for !x.isNull() { 206 y = x 207 x = y.getRight(i.db) 208 } 209 210 i.curr = y 211 } 212 213 func (i *MemdbIterator) seek(key []byte) { 214 y := memdbNodeAddr{nil, nullAddr} 215 x := i.db.getNode(i.db.root) 216 217 var cmp int 218 for !x.isNull() { 219 y = x 220 cmp = bytes.Compare(key, y.getKey()) 221 222 if cmp < 0 { 223 x = y.getLeft(i.db) 224 } else if cmp > 0 { 225 x = y.getRight(i.db) 226 } else { 227 break 228 } 229 } 230 231 if !i.reverse { 232 if cmp > 0 { 233 // Move to next 234 i.curr = i.db.successor(y) 235 return 236 } 237 i.curr = y 238 return 239 } 240 241 if cmp <= 0 && !y.isNull() { 242 i.curr = i.db.predecessor(y) 243 return 244 } 245 i.curr = y 246 } 247 248 func (i *MemdbIterator) isFlagsOnly() bool { 249 return !i.curr.isNull() && i.curr.vptr.isNull() 250 }