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  }