github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/logtail/operator.go (about)

     1  // Copyright 2021 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 logtail
    16  
    17  import (
    18  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    19  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    20  )
    21  
    22  // BoundTableOperator holds a read only reader, knows how to iterate catalog entries.
    23  type BoundTableOperator struct {
    24  	catalog *catalog.Catalog
    25  	reader  *Reader
    26  	visitor catalog.Processor
    27  	dbID    uint64
    28  	tableID uint64
    29  	scope   Scope
    30  }
    31  
    32  func NewBoundTableOperator(catalog *catalog.Catalog,
    33  	reader *Reader,
    34  	scope Scope,
    35  	dbID, tableID uint64,
    36  	visitor catalog.Processor) *BoundTableOperator {
    37  	return &BoundTableOperator{
    38  		catalog: catalog,
    39  		reader:  reader,
    40  		visitor: visitor,
    41  		tableID: tableID,
    42  		dbID:    dbID,
    43  		scope:   scope,
    44  	}
    45  }
    46  
    47  // Run takes a RespBuilder to visit every table/Object/block touched by all txn
    48  // in the Reader. During the visiting, RespBuiler will fetch information to return logtail entry
    49  func (c *BoundTableOperator) Run() error {
    50  	switch c.scope {
    51  	case ScopeDatabases:
    52  		return c.processDatabases()
    53  	case ScopeTables, ScopeColumns:
    54  		return c.processTables()
    55  	case ScopeUserTables:
    56  		return c.processTableData()
    57  	default:
    58  		panic("unknown logtail collect scope")
    59  	}
    60  }
    61  
    62  // For normal user table, pick out all dirty blocks and call OnBlock
    63  func (c *BoundTableOperator) processTableData() error {
    64  	db, err := c.catalog.GetDatabaseByID(c.dbID)
    65  	if err != nil {
    66  		return err
    67  	}
    68  	tbl, err := db.GetTableEntryByID(c.tableID)
    69  	if err != nil {
    70  		return err
    71  	}
    72  	dirty := c.reader.GetDirtyByTable(c.dbID, c.tableID)
    73  	for _, dirtyObj := range dirty.Objs {
    74  		obj, err := tbl.GetObjectByID(dirtyObj.ID)
    75  		if err != nil {
    76  			if moerr.IsMoErrCode(err, moerr.OkExpectedEOB) {
    77  				continue
    78  			}
    79  			return err
    80  		}
    81  		if err = c.visitor.OnObject(obj); err != nil {
    82  			return err
    83  		}
    84  
    85  	}
    86  	tombstones := tbl.GetDeleteList().Copy().Items()
    87  	for _, deletes := range tombstones {
    88  		err = c.visitor.OnTombstone(deletes)
    89  		if err != nil {
    90  			return err
    91  		}
    92  	}
    93  	return nil
    94  }
    95  
    96  // For mo_database, iterate over all database and call OnBlock.
    97  // TODO: avoid iterating all. For now it is acceptable because all catalog is in
    98  // memory and ddl is much smaller than dml
    99  func (c *BoundTableOperator) processDatabases() error {
   100  	if !c.reader.HasCatalogChanges() {
   101  		return nil
   102  	}
   103  	dbIt := c.catalog.MakeDBIt(true)
   104  	for ; dbIt.Valid(); dbIt.Next() {
   105  		dbentry := dbIt.Get().GetPayload()
   106  		if err := c.visitor.OnDatabase(dbentry); err != nil {
   107  			return err
   108  		}
   109  	}
   110  	return nil
   111  }
   112  
   113  // For mo_table and mo_columns, iterate over all tables and call OnTable
   114  // TODO: avoid iterating all. For now it is acceptable because all catalog is in
   115  // memory and ddl is much smaller than dml
   116  func (c *BoundTableOperator) processTables() error {
   117  	if !c.reader.HasCatalogChanges() {
   118  		return nil
   119  	}
   120  	dbIt := c.catalog.MakeDBIt(true)
   121  	for ; dbIt.Valid(); dbIt.Next() {
   122  		db := dbIt.Get().GetPayload()
   123  		tblIt := db.MakeTableIt(true)
   124  		for ; tblIt.Valid(); tblIt.Next() {
   125  			if err := c.visitor.OnTable(tblIt.Get().GetPayload()); err != nil {
   126  				return err
   127  			}
   128  		}
   129  	}
   130  	return nil
   131  }