github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/disttae/logtailreplay/rows_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  	"github.com/matrixorigin/matrixone/pkg/container/types"
    20  	"github.com/tidwall/btree"
    21  )
    22  
    23  type RowsIter interface {
    24  	Next() bool
    25  	Close() error
    26  	Entry() RowEntry
    27  }
    28  
    29  type rowsIter struct {
    30  	ts           types.TS
    31  	iter         btree.IterG[RowEntry]
    32  	firstCalled  bool
    33  	lastRowID    types.Rowid
    34  	checkBlockID bool
    35  	blockID      types.Blockid
    36  	iterDeleted  bool
    37  }
    38  
    39  func (p *PartitionState) NewRowsIter(ts types.TS, blockID *types.Blockid, iterDeleted bool) *rowsIter {
    40  	iter := p.rows.Copy().Iter()
    41  	ret := &rowsIter{
    42  		ts:          ts,
    43  		iter:        iter,
    44  		iterDeleted: iterDeleted,
    45  	}
    46  	if blockID != nil {
    47  		ret.checkBlockID = true
    48  		ret.blockID = *blockID
    49  	}
    50  	return ret
    51  }
    52  
    53  var _ RowsIter = new(rowsIter)
    54  
    55  func (p *rowsIter) Next() bool {
    56  	for {
    57  
    58  		if !p.firstCalled {
    59  			if p.checkBlockID {
    60  				if !p.iter.Seek(RowEntry{
    61  					BlockID: p.blockID,
    62  				}) {
    63  					return false
    64  				}
    65  			} else {
    66  				if !p.iter.First() {
    67  					return false
    68  				}
    69  			}
    70  			p.firstCalled = true
    71  		} else {
    72  			if !p.iter.Next() {
    73  				return false
    74  			}
    75  		}
    76  
    77  		entry := p.iter.Item()
    78  
    79  		if p.checkBlockID && entry.BlockID != p.blockID {
    80  			// no more
    81  			return false
    82  		}
    83  		if entry.Time.Greater(&p.ts) {
    84  			// not visible
    85  			continue
    86  		}
    87  		if entry.RowID.Equal(p.lastRowID) {
    88  			// already met
    89  			continue
    90  		}
    91  		if entry.Deleted != p.iterDeleted {
    92  			// not wanted, skip to next row id
    93  			p.lastRowID = entry.RowID
    94  			continue
    95  		}
    96  
    97  		p.lastRowID = entry.RowID
    98  		return true
    99  	}
   100  }
   101  
   102  func (p *rowsIter) Entry() RowEntry {
   103  	return p.iter.Item()
   104  }
   105  
   106  func (p *rowsIter) Close() error {
   107  	p.iter.Release()
   108  	return nil
   109  }
   110  
   111  type primaryKeyIter struct {
   112  	ts           types.TS
   113  	spec         PrimaryKeyMatchSpec
   114  	iter         btree.IterG[*PrimaryIndexEntry]
   115  	rows         *btree.BTreeG[RowEntry]
   116  	primaryIndex *btree.BTreeG[*PrimaryIndexEntry]
   117  	curRow       RowEntry
   118  }
   119  
   120  type PrimaryKeyMatchSpec struct {
   121  	// Move moves to the target
   122  	Move func(p *primaryKeyIter) bool
   123  	Name string
   124  }
   125  
   126  func Exact(key []byte) PrimaryKeyMatchSpec {
   127  	first := true
   128  	return PrimaryKeyMatchSpec{
   129  		Name: "Exact",
   130  		Move: func(p *primaryKeyIter) bool {
   131  			var ok bool
   132  			if first {
   133  				first = false
   134  				ok = p.iter.Seek(&PrimaryIndexEntry{
   135  					Bytes: key,
   136  				})
   137  			} else {
   138  				ok = p.iter.Next()
   139  			}
   140  
   141  			if !ok {
   142  				return false
   143  			}
   144  
   145  			item := p.iter.Item()
   146  			return bytes.Equal(item.Bytes, key)
   147  		},
   148  	}
   149  }
   150  
   151  func Prefix(prefix []byte) PrimaryKeyMatchSpec {
   152  	first := true
   153  	return PrimaryKeyMatchSpec{
   154  		Name: "Prefix",
   155  		Move: func(p *primaryKeyIter) bool {
   156  			var ok bool
   157  			if first {
   158  				first = false
   159  				ok = p.iter.Seek(&PrimaryIndexEntry{
   160  					Bytes: prefix,
   161  				})
   162  			} else {
   163  				ok = p.iter.Next()
   164  			}
   165  
   166  			if !ok {
   167  				return false
   168  			}
   169  
   170  			item := p.iter.Item()
   171  			return bytes.HasPrefix(item.Bytes, prefix)
   172  		},
   173  	}
   174  }
   175  
   176  func MinMax(min []byte, max []byte) PrimaryKeyMatchSpec {
   177  	return PrimaryKeyMatchSpec{}
   178  }
   179  
   180  type phase int
   181  
   182  const (
   183  	scan  phase = 0
   184  	seek  phase = 1
   185  	judge phase = 2
   186  )
   187  
   188  func ExactIn(encodes [][]byte) PrimaryKeyMatchSpec {
   189  	var encoded []byte
   190  
   191  	first := true
   192  	iterateAll := false
   193  
   194  	idx := 0
   195  	vecLen := len(encodes)
   196  	currentPhase := seek
   197  
   198  	updateEncoded := func() bool {
   199  		if idx >= vecLen {
   200  			return false
   201  		}
   202  		encoded = encodes[idx]
   203  		idx++
   204  		return true
   205  	}
   206  
   207  	match := func(key []byte) bool {
   208  		return bytes.Equal(key, encoded)
   209  	}
   210  
   211  	return PrimaryKeyMatchSpec{
   212  		Name: "ExactIn",
   213  		Move: func(p *primaryKeyIter) bool {
   214  			if first {
   215  				first = false
   216  				// each seek may visit height items
   217  				// we choose to scan all if the seek is more expensive
   218  				if len(encodes)*p.primaryIndex.Height() > p.primaryIndex.Len() {
   219  					iterateAll = true
   220  				}
   221  			}
   222  
   223  			for {
   224  				switch currentPhase {
   225  				case judge:
   226  					if iterateAll {
   227  						if !updateEncoded() {
   228  							return false
   229  						}
   230  						currentPhase = scan
   231  					} else {
   232  						currentPhase = seek
   233  					}
   234  
   235  				case seek:
   236  					if !updateEncoded() {
   237  						// out of vec
   238  						return false
   239  					}
   240  					if !p.iter.Seek(&PrimaryIndexEntry{Bytes: encoded}) {
   241  						return false
   242  					}
   243  					if match(p.iter.Item().Bytes) {
   244  						currentPhase = scan
   245  						return true
   246  					}
   247  
   248  				case scan:
   249  					if !p.iter.Next() {
   250  						return false
   251  					}
   252  					if match(p.iter.Item().Bytes) {
   253  						return true
   254  					}
   255  					p.iter.Prev()
   256  					currentPhase = judge
   257  				}
   258  			}
   259  		},
   260  	}
   261  }
   262  
   263  func (p *PartitionState) NewPrimaryKeyIter(
   264  	ts types.TS,
   265  	spec PrimaryKeyMatchSpec,
   266  ) *primaryKeyIter {
   267  	index := p.primaryIndex.Copy()
   268  	return &primaryKeyIter{
   269  		ts:           ts,
   270  		spec:         spec,
   271  		iter:         index.Iter(),
   272  		primaryIndex: index,
   273  		rows:         p.rows.Copy(),
   274  	}
   275  }
   276  
   277  var _ RowsIter = new(primaryKeyIter)
   278  
   279  func (p *primaryKeyIter) Next() bool {
   280  	for {
   281  		if !p.spec.Move(p) {
   282  			return false
   283  		}
   284  
   285  		entry := p.iter.Item()
   286  
   287  		// validate
   288  		valid := false
   289  		rowsIter := p.rows.Iter()
   290  		for ok := rowsIter.Seek(RowEntry{
   291  			BlockID: entry.BlockID,
   292  			RowID:   entry.RowID,
   293  			Time:    p.ts,
   294  		}); ok; ok = rowsIter.Next() {
   295  			row := rowsIter.Item()
   296  			if row.BlockID != entry.BlockID {
   297  				// no more
   298  				break
   299  			}
   300  			if row.RowID != entry.RowID {
   301  				// no more
   302  				break
   303  			}
   304  			if row.Time.Greater(&p.ts) {
   305  				// not visible
   306  				continue
   307  			}
   308  			if row.Deleted {
   309  				// visible and deleted, no longer valid
   310  				break
   311  			}
   312  			valid = row.ID == entry.RowEntryID
   313  			if valid {
   314  				p.curRow = row
   315  			}
   316  			break
   317  		}
   318  		rowsIter.Release()
   319  
   320  		if !valid {
   321  			continue
   322  		}
   323  
   324  		return true
   325  	}
   326  }
   327  
   328  func (p *primaryKeyIter) Entry() RowEntry {
   329  	return p.curRow
   330  }
   331  
   332  func (p *primaryKeyIter) Close() error {
   333  	p.iter.Release()
   334  	return nil
   335  }
   336  
   337  type primaryKeyDelIter struct {
   338  	primaryKeyIter
   339  	bid types.Blockid
   340  }
   341  
   342  func (p *PartitionState) NewPrimaryKeyDelIter(
   343  	ts types.TS,
   344  	spec PrimaryKeyMatchSpec,
   345  	bid types.Blockid,
   346  ) *primaryKeyDelIter {
   347  	iter := p.primaryIndex.Copy().Iter()
   348  	return &primaryKeyDelIter{
   349  		primaryKeyIter: primaryKeyIter{
   350  			ts:   ts,
   351  			spec: spec,
   352  			iter: iter,
   353  			rows: p.rows.Copy(),
   354  		},
   355  		bid: bid,
   356  	}
   357  }
   358  
   359  var _ RowsIter = new(primaryKeyDelIter)
   360  
   361  func (p *primaryKeyDelIter) Next() bool {
   362  	for {
   363  		if !p.spec.Move(&p.primaryKeyIter) {
   364  			return false
   365  		}
   366  
   367  		entry := p.iter.Item()
   368  
   369  		if entry.BlockID.Compare(p.bid) != 0 {
   370  			continue
   371  		}
   372  
   373  		// validate
   374  		valid := false
   375  		rowsIter := p.rows.Iter()
   376  		for ok := rowsIter.Seek(RowEntry{
   377  			BlockID: entry.BlockID,
   378  			RowID:   entry.RowID,
   379  			Time:    p.ts,
   380  		}); ok; ok = rowsIter.Next() {
   381  			row := rowsIter.Item()
   382  			if row.BlockID != entry.BlockID {
   383  				// no more
   384  				break
   385  			}
   386  			if row.RowID != entry.RowID {
   387  				// no more
   388  				break
   389  			}
   390  			if row.Time.Greater(&p.ts) {
   391  				// not visible
   392  				continue
   393  			}
   394  			if !row.Deleted {
   395  				// skip not deleted
   396  				continue
   397  			}
   398  			valid = row.ID == entry.RowEntryID
   399  			if valid {
   400  				p.curRow = row
   401  			}
   402  			break
   403  		}
   404  		rowsIter.Release()
   405  
   406  		if !valid {
   407  			continue
   408  		}
   409  
   410  		return true
   411  	}
   412  }