github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/allegrosql/memdb_iterator.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package ekv 15 16 import "bytes" 17 18 type memdbIterator struct { 19 EDB *memdb 20 curr memdbNodeAddr 21 start Key 22 end Key 23 reverse bool 24 includeFlags bool 25 } 26 27 func (EDB *memdb) Iter(k Key, upperBound Key) (Iterator, error) { 28 i := &memdbIterator{ 29 EDB: EDB, 30 start: k, 31 end: upperBound, 32 } 33 i.init() 34 return i, nil 35 } 36 37 func (EDB *memdb) IterReverse(k Key) (Iterator, error) { 38 i := &memdbIterator{ 39 EDB: EDB, 40 end: k, 41 reverse: true, 42 } 43 i.init() 44 return i, nil 45 } 46 47 func (EDB *memdb) IterWithFlags(k Key, upperBound Key) MemBufferIterator { 48 i := &memdbIterator{ 49 EDB: EDB, 50 start: k, 51 end: upperBound, 52 includeFlags: true, 53 } 54 i.init() 55 return i 56 } 57 58 func (EDB *memdb) IterReverseWithFlags(k Key) MemBufferIterator { 59 i := &memdbIterator{ 60 EDB: EDB, 61 end: k, 62 reverse: true, 63 includeFlags: true, 64 } 65 i.init() 66 return i 67 } 68 69 func (i *memdbIterator) init() { 70 if i.reverse { 71 if len(i.end) == 0 { 72 i.seekToLast() 73 } else { 74 i.seek(i.end) 75 } 76 } else { 77 if len(i.start) == 0 { 78 i.seekToFirst() 79 } else { 80 i.seek(i.start) 81 } 82 } 83 84 if i.isFlagsOnly() && !i.includeFlags { 85 err := i.Next() 86 _ = err // memdbIterator will never fail 87 } 88 } 89 90 func (i *memdbIterator) Valid() bool { 91 if !i.reverse { 92 return !i.curr.isNull() && (i.end == nil || bytes.Compare(i.Key(), i.end) < 0) 93 } 94 return !i.curr.isNull() 95 } 96 97 func (i *memdbIterator) Flags() KeyFlags { 98 return i.curr.getKeyFlags() 99 } 100 101 func (i *memdbIterator) HasValue() bool { 102 return !i.isFlagsOnly() 103 } 104 105 func (i *memdbIterator) Key() Key { 106 return i.curr.getKey() 107 } 108 109 func (i *memdbIterator) Value() []byte { 110 return i.EDB.vlog.getValue(i.curr.vptr) 111 } 112 113 func (i *memdbIterator) Next() error { 114 for { 115 if i.reverse { 116 i.curr = i.EDB.predecessor(i.curr) 117 } else { 118 i.curr = i.EDB.successor(i.curr) 119 } 120 121 // We need to skip persistent flags only nodes. 122 if i.includeFlags || !i.isFlagsOnly() { 123 break 124 } 125 } 126 return nil 127 } 128 129 func (i *memdbIterator) Close() {} 130 131 func (i *memdbIterator) seekToFirst() { 132 y := memdbNodeAddr{nil, nullAddr} 133 x := i.EDB.getNode(i.EDB.root) 134 135 for !x.isNull() { 136 y = x 137 x = y.getLeft(i.EDB) 138 } 139 140 i.curr = y 141 } 142 143 func (i *memdbIterator) seekToLast() { 144 y := memdbNodeAddr{nil, nullAddr} 145 x := i.EDB.getNode(i.EDB.root) 146 147 for !x.isNull() { 148 y = x 149 x = y.getRight(i.EDB) 150 } 151 152 i.curr = y 153 } 154 155 func (i *memdbIterator) seek(key Key) { 156 y := memdbNodeAddr{nil, nullAddr} 157 x := i.EDB.getNode(i.EDB.root) 158 159 var cmp int 160 for !x.isNull() { 161 y = x 162 cmp = bytes.Compare(key, y.getKey()) 163 164 if cmp < 0 { 165 x = y.getLeft(i.EDB) 166 } else if cmp > 0 { 167 x = y.getRight(i.EDB) 168 } else { 169 break 170 } 171 } 172 173 if !i.reverse { 174 if cmp > 0 { 175 // Move to next 176 i.curr = i.EDB.successor(y) 177 return 178 } 179 i.curr = y 180 return 181 } 182 183 if cmp <= 0 && !y.isNull() { 184 i.curr = i.EDB.predecessor(y) 185 return 186 } 187 i.curr = y 188 } 189 190 func (i *memdbIterator) isFlagsOnly() bool { 191 return !i.curr.isNull() && i.curr.vptr.isNull() 192 }