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 }