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 }