github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/ekv/union_iter.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 ( 17 "github.com/whtcorpsinc/milevadb/soliton/logutil" 18 "go.uber.org/zap" 19 ) 20 21 // UnionIter is the iterator on an UnionStore. 22 type UnionIter struct { 23 dirtyIt Iterator 24 snapshotIt Iterator 25 26 dirtyValid bool 27 snapshotValid bool 28 29 curIsDirty bool 30 isValid bool 31 reverse bool 32 } 33 34 // NewUnionIter returns a union iterator for BufferStore. 35 func NewUnionIter(dirtyIt Iterator, snapshotIt Iterator, reverse bool) (*UnionIter, error) { 36 it := &UnionIter{ 37 dirtyIt: dirtyIt, 38 snapshotIt: snapshotIt, 39 dirtyValid: dirtyIt.Valid(), 40 snapshotValid: snapshotIt.Valid(), 41 reverse: reverse, 42 } 43 err := it.uFIDelateCur() 44 if err != nil { 45 return nil, err 46 } 47 return it, nil 48 } 49 50 // dirtyNext makes iter.dirtyIt go and uFIDelate valid status. 51 func (iter *UnionIter) dirtyNext() error { 52 err := iter.dirtyIt.Next() 53 iter.dirtyValid = iter.dirtyIt.Valid() 54 return err 55 } 56 57 // snapshotNext makes iter.snapshotIt go and uFIDelate valid status. 58 func (iter *UnionIter) snapshotNext() error { 59 err := iter.snapshotIt.Next() 60 iter.snapshotValid = iter.snapshotIt.Valid() 61 return err 62 } 63 64 func (iter *UnionIter) uFIDelateCur() error { 65 iter.isValid = true 66 for { 67 if !iter.dirtyValid && !iter.snapshotValid { 68 iter.isValid = false 69 break 70 } 71 72 if !iter.dirtyValid { 73 iter.curIsDirty = false 74 break 75 } 76 77 if !iter.snapshotValid { 78 iter.curIsDirty = true 79 // if delete it 80 if len(iter.dirtyIt.Value()) == 0 { 81 if err := iter.dirtyNext(); err != nil { 82 return err 83 } 84 continue 85 } 86 break 87 } 88 89 // both valid 90 if iter.snapshotValid && iter.dirtyValid { 91 snapshotKey := iter.snapshotIt.Key() 92 dirtyKey := iter.dirtyIt.Key() 93 cmp := dirtyKey.Cmp(snapshotKey) 94 if iter.reverse { 95 cmp = -cmp 96 } 97 // if equal, means both have value 98 if cmp == 0 { 99 if len(iter.dirtyIt.Value()) == 0 { 100 // snapshot has a record, but txn says we have deleted it 101 // just go next 102 if err := iter.dirtyNext(); err != nil { 103 return err 104 } 105 if err := iter.snapshotNext(); err != nil { 106 return err 107 } 108 continue 109 } 110 // both go next 111 if err := iter.snapshotNext(); err != nil { 112 return err 113 } 114 iter.curIsDirty = true 115 break 116 } else if cmp > 0 { 117 // record from snapshot comes first 118 iter.curIsDirty = false 119 break 120 } else { 121 // record from dirty comes first 122 if len(iter.dirtyIt.Value()) == 0 { 123 logutil.BgLogger().Warn("delete a record not exists?", 124 zap.Stringer("key", iter.dirtyIt.Key())) 125 // jump over this deletion 126 if err := iter.dirtyNext(); err != nil { 127 return err 128 } 129 continue 130 } 131 iter.curIsDirty = true 132 break 133 } 134 } 135 } 136 return nil 137 } 138 139 // Next implements the Iterator Next interface. 140 func (iter *UnionIter) Next() error { 141 var err error 142 if !iter.curIsDirty { 143 err = iter.snapshotNext() 144 } else { 145 err = iter.dirtyNext() 146 } 147 if err != nil { 148 return err 149 } 150 err = iter.uFIDelateCur() 151 return err 152 } 153 154 // Value implements the Iterator Value interface. 155 // Multi columns 156 func (iter *UnionIter) Value() []byte { 157 if !iter.curIsDirty { 158 return iter.snapshotIt.Value() 159 } 160 return iter.dirtyIt.Value() 161 } 162 163 // Key implements the Iterator Key interface. 164 func (iter *UnionIter) Key() Key { 165 if !iter.curIsDirty { 166 return iter.snapshotIt.Key() 167 } 168 return iter.dirtyIt.Key() 169 } 170 171 // Valid implements the Iterator Valid interface. 172 func (iter *UnionIter) Valid() bool { 173 return iter.isValid 174 } 175 176 // Close implements the Iterator Close interface. 177 func (iter *UnionIter) Close() { 178 if iter.snapshotIt != nil { 179 iter.snapshotIt.Close() 180 iter.snapshotIt = nil 181 } 182 if iter.dirtyIt != nil { 183 iter.dirtyIt.Close() 184 iter.dirtyIt = nil 185 } 186 }