github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/db/scanner.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 db
    16  
    17  import (
    18  	"github.com/RoaringBitmap/roaring"
    19  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    20  	"github.com/matrixorigin/matrixone/pkg/logutil"
    21  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    22  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/db/dbutils"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tasks/worker/base"
    24  )
    25  
    26  type DBScanner interface {
    27  	base.IHBHandle
    28  	RegisterOp(ScannerOp)
    29  }
    30  
    31  type ErrHandler interface {
    32  	OnObjectErr(entry *catalog.ObjectEntry, err error) error
    33  	OnTableErr(entry *catalog.TableEntry, err error) error
    34  	OnDatabaseErr(entry *catalog.DBEntry, err error) error
    35  }
    36  
    37  type NoopErrHandler struct{}
    38  
    39  func (h *NoopErrHandler) OnObjectErr(entry *catalog.ObjectEntry, err error) error { return nil }
    40  func (h *NoopErrHandler) OnTableErr(entry *catalog.TableEntry, err error) error   { return nil }
    41  func (h *NoopErrHandler) OnDatabaseErr(entry *catalog.DBEntry, err error) error   { return nil }
    42  
    43  type dbScanner struct {
    44  	*catalog.LoopProcessor
    45  	db         *DB
    46  	ops        []ScannerOp
    47  	errHandler ErrHandler
    48  	dbmask     *roaring.Bitmap
    49  	tablemask  *roaring.Bitmap
    50  	objmask    *roaring.Bitmap
    51  }
    52  
    53  func (scanner *dbScanner) OnStopped() {
    54  	logutil.Infof("DBScanner Stopped")
    55  }
    56  
    57  func (scanner *dbScanner) OnExec() {
    58  	scanner.dbmask.Clear()
    59  	scanner.tablemask.Clear()
    60  	scanner.objmask.Clear()
    61  	dbutils.PrintMemStats()
    62  
    63  	// compact logtail table
    64  	scanner.db.LogtailMgr.TryCompactTable()
    65  
    66  	for _, op := range scanner.ops {
    67  		err := op.PreExecute()
    68  		if err != nil {
    69  			panic(err)
    70  		}
    71  	}
    72  	if err := scanner.db.Catalog.RecurLoop(scanner); err != nil {
    73  		logutil.Errorf("DBScanner Execute: %v", err)
    74  	}
    75  	for _, op := range scanner.ops {
    76  		err := op.PostExecute()
    77  		if err != nil {
    78  			panic(err)
    79  		}
    80  	}
    81  }
    82  
    83  func NewDBScanner(db *DB, errHandler ErrHandler) *dbScanner {
    84  	if errHandler == nil {
    85  		errHandler = new(NoopErrHandler)
    86  	}
    87  	scanner := &dbScanner{
    88  		LoopProcessor: new(catalog.LoopProcessor),
    89  		db:            db,
    90  		ops:           make([]ScannerOp, 0),
    91  		errHandler:    errHandler,
    92  		dbmask:        roaring.New(),
    93  		tablemask:     roaring.New(),
    94  		objmask:       roaring.New(),
    95  	}
    96  	scanner.ObjectFn = scanner.onObject
    97  	scanner.PostObjectFn = scanner.onPostObject
    98  	scanner.TableFn = scanner.onTable
    99  	scanner.PostTableFn = scanner.onPostTable
   100  	scanner.DatabaseFn = scanner.onDatabase
   101  	scanner.PostDatabaseFn = scanner.onPostDatabase
   102  	return scanner
   103  }
   104  
   105  func (scanner *dbScanner) RegisterOp(op ScannerOp) {
   106  	scanner.ops = append(scanner.ops, op)
   107  }
   108  
   109  func (scanner *dbScanner) onPostObject(entry *catalog.ObjectEntry) (err error) {
   110  	for _, op := range scanner.ops {
   111  		err = op.OnPostObject(entry)
   112  		if err = scanner.errHandler.OnObjectErr(entry, err); err != nil {
   113  			break
   114  		}
   115  	}
   116  	return
   117  }
   118  
   119  func (scanner *dbScanner) onPostTable(entry *catalog.TableEntry) (err error) {
   120  	for _, op := range scanner.ops {
   121  		err = op.OnPostTable(entry)
   122  		if err = scanner.errHandler.OnTableErr(entry, err); err != nil {
   123  			break
   124  		}
   125  	}
   126  	return
   127  }
   128  
   129  func (scanner *dbScanner) onPostDatabase(entry *catalog.DBEntry) (err error) {
   130  	for _, op := range scanner.ops {
   131  		err = op.OnPostDatabase(entry)
   132  		if err = scanner.errHandler.OnDatabaseErr(entry, err); err != nil {
   133  			break
   134  		}
   135  	}
   136  	return
   137  }
   138  
   139  func (scanner *dbScanner) onObject(entry *catalog.ObjectEntry) (err error) {
   140  	scanner.objmask.Clear()
   141  	for i, op := range scanner.ops {
   142  		if scanner.tablemask.Contains(uint32(i)) {
   143  			scanner.objmask.Add(uint32(i))
   144  			continue
   145  		}
   146  		err = op.OnObject(entry)
   147  		if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) {
   148  			scanner.objmask.Add(uint32(i))
   149  		}
   150  		if err = scanner.errHandler.OnObjectErr(entry, err); err != nil {
   151  			break
   152  		}
   153  	}
   154  	if scanner.objmask.GetCardinality() == uint64(len(scanner.ops)) {
   155  		err = moerr.GetOkStopCurrRecur()
   156  	}
   157  	return
   158  }
   159  
   160  func (scanner *dbScanner) onTable(entry *catalog.TableEntry) (err error) {
   161  	if entry.IsVirtual() {
   162  		err = moerr.GetOkStopCurrRecur()
   163  		return
   164  	}
   165  	scanner.tablemask.Clear()
   166  	for i, op := range scanner.ops {
   167  		// If the specified op was masked OnDatabase. skip it
   168  		if scanner.dbmask.Contains(uint32(i)) {
   169  			scanner.tablemask.Add(uint32(i))
   170  			continue
   171  		}
   172  		err = op.OnTable(entry)
   173  		if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) {
   174  			scanner.tablemask.Add(uint32(i))
   175  		}
   176  		if err = scanner.errHandler.OnTableErr(entry, err); err != nil {
   177  			break
   178  		}
   179  	}
   180  	if scanner.tablemask.GetCardinality() == uint64(len(scanner.ops)) {
   181  		err = moerr.GetOkStopCurrRecur()
   182  	}
   183  	return
   184  }
   185  
   186  func (scanner *dbScanner) onDatabase(entry *catalog.DBEntry) (err error) {
   187  	// if entry.IsSystemDB() {
   188  	// 	err = catalog.ErrStopCurrRecur
   189  	// 	return
   190  	// }
   191  	scanner.dbmask.Clear()
   192  	for i, op := range scanner.ops {
   193  		err = op.OnDatabase(entry)
   194  		if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) {
   195  			scanner.dbmask.Add(uint32(i))
   196  		}
   197  		if err = scanner.errHandler.OnDatabaseErr(entry, err); err != nil {
   198  			break
   199  		}
   200  	}
   201  	if scanner.dbmask.GetCardinality() == uint64(len(scanner.ops)) {
   202  		err = moerr.GetOkStopCurrRecur()
   203  	}
   204  	return
   205  }