github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/disttae/logtailreplay/blocks_iter.go (about) 1 // Copyright 2023 Matrix Origin 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 logtailreplay 16 17 import ( 18 "bytes" 19 20 "github.com/matrixorigin/matrixone/pkg/common/moerr" 21 "github.com/matrixorigin/matrixone/pkg/container/types" 22 "github.com/matrixorigin/matrixone/pkg/objectio" 23 "github.com/tidwall/btree" 24 ) 25 26 type ObjectsIter interface { 27 Next() bool 28 Close() error 29 Entry() ObjectEntry 30 } 31 32 type objectsIter struct { 33 ts types.TS 34 iter btree.IterG[ObjectEntry] 35 } 36 37 // not accurate! only used by stats 38 func (p *PartitionState) ApproxObjectsNum() int { 39 return p.dataObjects.Len() 40 } 41 42 func (p *PartitionState) NewObjectsIter(ts types.TS) (ObjectsIter, error) { 43 if ts.Less(&p.minTS) { 44 return nil, moerr.NewTxnStaleNoCtx() 45 } 46 iter := p.dataObjects.Copy().Iter() 47 ret := &objectsIter{ 48 ts: ts, 49 iter: iter, 50 } 51 return ret, nil 52 } 53 54 var _ ObjectsIter = new(objectsIter) 55 56 func (b *objectsIter) Next() bool { 57 for b.iter.Next() { 58 entry := b.iter.Item() 59 if !entry.Visible(b.ts) { 60 // not visible 61 continue 62 } 63 return true 64 } 65 return false 66 } 67 68 func (b *objectsIter) Entry() ObjectEntry { 69 return ObjectEntry{ 70 ObjectInfo: b.iter.Item().ObjectInfo, 71 } 72 } 73 74 func (b *objectsIter) Close() error { 75 b.iter.Release() 76 return nil 77 } 78 79 type BlocksIter interface { 80 Next() bool 81 Close() error 82 Entry() types.Blockid 83 } 84 85 type dirtyBlocksIter struct { 86 iter btree.IterG[types.Blockid] 87 firstCalled bool 88 } 89 90 func (p *PartitionState) NewDirtyBlocksIter() BlocksIter { 91 iter := p.dirtyBlocks.Copy().Iter() 92 ret := &dirtyBlocksIter{ 93 iter: iter, 94 } 95 return ret 96 } 97 98 var _ BlocksIter = new(dirtyBlocksIter) 99 100 func (b *dirtyBlocksIter) Next() bool { 101 if !b.firstCalled { 102 if !b.iter.First() { 103 return false 104 } 105 b.firstCalled = true 106 return true 107 } 108 return b.iter.Next() 109 } 110 111 func (b *dirtyBlocksIter) Entry() types.Blockid { 112 return b.iter.Item() 113 } 114 115 func (b *dirtyBlocksIter) Close() error { 116 b.iter.Release() 117 return nil 118 } 119 120 // GetChangedObjsBetween get changed objects between [begin, end], 121 // notice that if an object is created after begin and deleted before end, it will be ignored. 122 func (p *PartitionState) GetChangedObjsBetween( 123 begin types.TS, 124 end types.TS, 125 ) ( 126 deleted map[objectio.ObjectNameShort]struct{}, 127 inserted map[objectio.ObjectNameShort]struct{}, 128 ) { 129 inserted = make(map[objectio.ObjectNameShort]struct{}) 130 deleted = make(map[objectio.ObjectNameShort]struct{}) 131 132 iter := p.objectIndexByTS.Copy().Iter() 133 defer iter.Release() 134 135 for ok := iter.Seek(ObjectIndexByTSEntry{ 136 Time: begin, 137 }); ok; ok = iter.Next() { 138 entry := iter.Item() 139 140 if entry.Time.Greater(&end) { 141 break 142 } 143 144 if entry.IsDelete { 145 // if the object is inserted and deleted between [begin, end], it will be ignored. 146 if _, ok := inserted[entry.ShortObjName]; !ok { 147 deleted[entry.ShortObjName] = struct{}{} 148 } else { 149 delete(inserted, entry.ShortObjName) 150 } 151 } else { 152 inserted[entry.ShortObjName] = struct{}{} 153 } 154 155 } 156 return 157 } 158 159 func (p *PartitionState) GetBockDeltaLoc(bid types.Blockid) (objectio.ObjectLocation, types.TS, bool) { 160 iter := p.blockDeltas.Copy().Iter() 161 defer iter.Release() 162 163 pivot := BlockDeltaEntry{ 164 BlockID: bid, 165 } 166 if ok := iter.Seek(pivot); ok { 167 e := iter.Item() 168 if e.BlockID.Compare(bid) == 0 { 169 return e.DeltaLoc, e.CommitTs, true 170 } 171 } 172 return objectio.ObjectLocation{}, types.TS{}, false 173 } 174 175 func (p *PartitionState) BlockPersisted(blockID types.Blockid) bool { 176 iter := p.dataObjects.Copy().Iter() 177 defer iter.Release() 178 179 pivot := ObjectEntry{} 180 objectio.SetObjectStatsShortName(&pivot.ObjectStats, objectio.ShortName(&blockID)) 181 if ok := iter.Seek(pivot); ok { 182 e := iter.Item() 183 if bytes.Equal(e.ObjectShortName()[:], objectio.ShortName(&blockID)[:]) { 184 return true 185 } 186 } 187 return false 188 } 189 190 func (p *PartitionState) GetObject(name objectio.ObjectNameShort) (ObjectInfo, bool) { 191 iter := p.dataObjects.Copy().Iter() 192 defer iter.Release() 193 194 pivot := ObjectEntry{} 195 objectio.SetObjectStatsShortName(&pivot.ObjectStats, &name) 196 if ok := iter.Seek(pivot); ok { 197 e := iter.Item() 198 if bytes.Equal(e.ObjectShortName()[:], name[:]) { 199 return iter.Item().ObjectInfo, true 200 } 201 } 202 return ObjectInfo{}, false 203 }