github.com/matrixorigin/matrixone@v0.7.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/tasks/worker/base"
    23  )
    24  
    25  type DBScanner interface {
    26  	base.IHBHandle
    27  	RegisterOp(ScannerOp)
    28  }
    29  
    30  type ErrHandler interface {
    31  	OnBlockErr(entry *catalog.BlockEntry, err error) error
    32  	OnSegmentErr(entry *catalog.SegmentEntry, 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) OnBlockErr(entry *catalog.BlockEntry, err error) error     { return nil }
    40  func (h *NoopErrHandler) OnSegmentErr(entry *catalog.SegmentEntry, err error) error { return nil }
    41  func (h *NoopErrHandler) OnTableErr(entry *catalog.TableEntry, err error) error     { return nil }
    42  func (h *NoopErrHandler) OnDatabaseErr(entry *catalog.DBEntry, err error) error     { return nil }
    43  
    44  type dbScanner struct {
    45  	*catalog.LoopProcessor
    46  	db         *DB
    47  	ops        []ScannerOp
    48  	errHandler ErrHandler
    49  	dbmask     *roaring.Bitmap
    50  	tablemask  *roaring.Bitmap
    51  	segmask    *roaring.Bitmap
    52  }
    53  
    54  func (scanner *dbScanner) OnStopped() {
    55  	logutil.Infof("DBScanner Stopped")
    56  }
    57  
    58  func (scanner *dbScanner) OnExec() {
    59  	scanner.dbmask.Clear()
    60  	scanner.tablemask.Clear()
    61  	scanner.segmask.Clear()
    62  	for _, op := range scanner.ops {
    63  		err := op.PreExecute()
    64  		if err != nil {
    65  			panic(err)
    66  		}
    67  	}
    68  	if err := scanner.db.Catalog.RecurLoop(scanner); err != nil {
    69  		logutil.Errorf("DBScanner Execute: %v", err)
    70  	}
    71  	for _, op := range scanner.ops {
    72  		err := op.PostExecute()
    73  		if err != nil {
    74  			panic(err)
    75  		}
    76  	}
    77  }
    78  
    79  func NewDBScanner(db *DB, errHandler ErrHandler) *dbScanner {
    80  	if errHandler == nil {
    81  		errHandler = new(NoopErrHandler)
    82  	}
    83  	scanner := &dbScanner{
    84  		LoopProcessor: new(catalog.LoopProcessor),
    85  		db:            db,
    86  		ops:           make([]ScannerOp, 0),
    87  		errHandler:    errHandler,
    88  		dbmask:        roaring.New(),
    89  		tablemask:     roaring.New(),
    90  		segmask:       roaring.New(),
    91  	}
    92  	scanner.BlockFn = scanner.onBlock
    93  	scanner.SegmentFn = scanner.onSegment
    94  	scanner.PostSegmentFn = scanner.onPostSegment
    95  	scanner.TableFn = scanner.onTable
    96  	scanner.DatabaseFn = scanner.onDatabase
    97  	return scanner
    98  }
    99  
   100  func (scanner *dbScanner) RegisterOp(op ScannerOp) {
   101  	scanner.ops = append(scanner.ops, op)
   102  }
   103  
   104  func (scanner *dbScanner) onBlock(entry *catalog.BlockEntry) (err error) {
   105  	for _, op := range scanner.ops {
   106  		err = op.OnBlock(entry)
   107  		if err = scanner.errHandler.OnBlockErr(entry, err); err != nil {
   108  			break
   109  		}
   110  	}
   111  	return
   112  }
   113  
   114  func (scanner *dbScanner) onPostSegment(entry *catalog.SegmentEntry) (err error) {
   115  	for _, op := range scanner.ops {
   116  		err = op.OnPostSegment(entry)
   117  		if err = scanner.errHandler.OnSegmentErr(entry, err); err != nil {
   118  			break
   119  		}
   120  	}
   121  	return
   122  }
   123  
   124  func (scanner *dbScanner) onSegment(entry *catalog.SegmentEntry) (err error) {
   125  	scanner.segmask.Clear()
   126  	for i, op := range scanner.ops {
   127  		if scanner.tablemask.Contains(uint32(i)) {
   128  			scanner.segmask.Add(uint32(i))
   129  			continue
   130  		}
   131  		err = op.OnSegment(entry)
   132  		if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) {
   133  			scanner.segmask.Add(uint32(i))
   134  		}
   135  		if err = scanner.errHandler.OnSegmentErr(entry, err); err != nil {
   136  			break
   137  		}
   138  	}
   139  	if scanner.segmask.GetCardinality() == uint64(len(scanner.ops)) {
   140  		err = moerr.GetOkStopCurrRecur()
   141  	}
   142  	return
   143  }
   144  
   145  func (scanner *dbScanner) onTable(entry *catalog.TableEntry) (err error) {
   146  	if entry.IsVirtual() {
   147  		err = moerr.GetOkStopCurrRecur()
   148  		return
   149  	}
   150  	scanner.tablemask.Clear()
   151  	for i, op := range scanner.ops {
   152  		// If the specified op was masked OnDatabase. skip it
   153  		if scanner.dbmask.Contains(uint32(i)) {
   154  			scanner.tablemask.Add(uint32(i))
   155  			continue
   156  		}
   157  		err = op.OnTable(entry)
   158  		if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) {
   159  			scanner.tablemask.Add(uint32(i))
   160  		}
   161  		if err = scanner.errHandler.OnTableErr(entry, err); err != nil {
   162  			break
   163  		}
   164  	}
   165  	if scanner.tablemask.GetCardinality() == uint64(len(scanner.ops)) {
   166  		err = moerr.GetOkStopCurrRecur()
   167  	}
   168  	return
   169  }
   170  
   171  func (scanner *dbScanner) onDatabase(entry *catalog.DBEntry) (err error) {
   172  	// if entry.IsSystemDB() {
   173  	// 	err = catalog.ErrStopCurrRecur
   174  	// 	return
   175  	// }
   176  	scanner.dbmask.Clear()
   177  	for i, op := range scanner.ops {
   178  		err = op.OnDatabase(entry)
   179  		if moerr.IsMoErrCode(err, moerr.OkStopCurrRecur) {
   180  			scanner.dbmask.Add(uint32(i))
   181  		}
   182  		if err = scanner.errHandler.OnDatabaseErr(entry, err); err != nil {
   183  			break
   184  		}
   185  	}
   186  	if scanner.dbmask.GetCardinality() == uint64(len(scanner.ops)) {
   187  		err = moerr.GetOkStopCurrRecur()
   188  	}
   189  	return
   190  }