github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/db/scheduler.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 "fmt" 19 20 "github.com/matrixorigin/matrixone/pkg/common/moerr" 21 "github.com/matrixorigin/matrixone/pkg/container/types" 22 23 "github.com/matrixorigin/matrixone/pkg/logutil" 24 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 25 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model" 26 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tasks" 27 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/wal" 28 ) 29 30 var ( 31 ErrTaskDuplicated = moerr.NewInternalErrorNoCtx("tae task: duplicated task found") 32 ErrTaskNotFound = moerr.NewInternalErrorNoCtx("tae task: task not found") 33 ) 34 35 type taskScheduler struct { 36 *tasks.BaseScheduler 37 db *DB 38 } 39 40 func newTaskScheduler(db *DB, asyncWorkers int, ioWorkers int) *taskScheduler { 41 if asyncWorkers < 0 || asyncWorkers > 100 { 42 panic(fmt.Sprintf("bad param: %d txn workers", asyncWorkers)) 43 } 44 if ioWorkers < 0 || ioWorkers > 100 { 45 panic(fmt.Sprintf("bad param: %d io workers", ioWorkers)) 46 } 47 s := &taskScheduler{ 48 BaseScheduler: tasks.NewBaseScheduler("taskScheduler"), 49 db: db, 50 } 51 jobDispatcher := newAsyncJobDispatcher() 52 jobHandler := tasks.NewPoolHandler(asyncWorkers) 53 jobHandler.Start() 54 jobDispatcher.RegisterHandler(tasks.DataCompactionTask, jobHandler) 55 // jobDispatcher.RegisterHandler(tasks.GCTask, jobHandler) 56 gcHandler := tasks.NewSingleWorkerHandler("gc") 57 gcHandler.Start() 58 jobDispatcher.RegisterHandler(tasks.GCTask, gcHandler) 59 60 ckpDispatcher := tasks.NewBaseScopedDispatcher(tasks.DefaultScopeSharder) 61 for i := 0; i < 4; i++ { 62 handler := tasks.NewSingleWorkerHandler(fmt.Sprintf("[ckpworker-%d]", i)) 63 ckpDispatcher.AddHandle(handler) 64 handler.Start() 65 } 66 67 ioDispatcher := tasks.NewBaseScopedDispatcher(nil) 68 for i := 0; i < ioWorkers; i++ { 69 handler := tasks.NewSingleWorkerHandler(fmt.Sprintf("[ioworker-%d]", i)) 70 ioDispatcher.AddHandle(handler) 71 handler.Start() 72 } 73 74 s.RegisterDispatcher(tasks.GCTask, jobDispatcher) 75 s.RegisterDispatcher(tasks.DataCompactionTask, jobDispatcher) 76 s.RegisterDispatcher(tasks.IOTask, ioDispatcher) 77 s.RegisterDispatcher(tasks.CheckpointTask, ckpDispatcher) 78 s.Start() 79 return s 80 } 81 82 func (s *taskScheduler) Stop() { 83 s.BaseScheduler.Stop() 84 logutil.Info("TaskScheduler Stopped") 85 } 86 87 func (s *taskScheduler) ScheduleTxnTask( 88 ctx *tasks.Context, 89 taskType tasks.TaskType, 90 factory tasks.TxnTaskFactory) (task tasks.Task, err error) { 91 task = NewScheduledTxnTask(ctx, s.db, taskType, nil, factory) 92 err = s.Schedule(task) 93 return 94 } 95 96 func (s *taskScheduler) ScheduleMultiScopedTxnTask( 97 ctx *tasks.Context, 98 taskType tasks.TaskType, 99 scopes []common.ID, 100 factory tasks.TxnTaskFactory) (task tasks.Task, err error) { 101 task = NewScheduledTxnTask(ctx, s.db, taskType, scopes, factory) 102 err = s.Schedule(task) 103 return 104 } 105 106 func (s *taskScheduler) ScheduleMultiScopedFn( 107 ctx *tasks.Context, 108 taskType tasks.TaskType, 109 scopes []common.ID, 110 fn tasks.FuncT) (task tasks.Task, err error) { 111 task = tasks.NewMultiScopedFnTask(ctx, taskType, scopes, fn) 112 err = s.Schedule(task) 113 return 114 } 115 116 func (s *taskScheduler) Checkpoint(indexes []*wal.Index) (err error) { 117 entry, err := s.db.Wal.Checkpoint(indexes) 118 if err != nil { 119 return err 120 } 121 s.db.BGCheckpointRunner.EnqueueWait(entry) 122 return 123 } 124 125 // TODO: implement later 126 func (s *taskScheduler) GetGCTS() (ts types.TS) { 127 return 128 } 129 130 func (s *taskScheduler) GetCheckpointTS() types.TS { 131 return s.db.TxnMgr.StatMaxCommitTS() 132 } 133 134 func (s *taskScheduler) GetPenddingLSNCnt() uint64 { 135 return s.db.Wal.GetPenddingCnt() 136 } 137 138 func (s *taskScheduler) GetCheckpointedLSN() uint64 { 139 return s.db.Wal.GetCheckpointed() 140 } 141 142 func (s *taskScheduler) AddTransferPage(page *model.TransferHashPage) (err error) { 143 s.db.TransferTable.AddPage(page) 144 return 145 } 146 147 func (s *taskScheduler) DeleteTransferPage(id *common.ID) (err error) { 148 s.db.TransferTable.DeletePage(id) 149 return 150 } 151 152 func (s *taskScheduler) ScheduleFn(ctx *tasks.Context, taskType tasks.TaskType, fn func() error) (task tasks.Task, err error) { 153 task = tasks.NewFnTask(ctx, taskType, fn) 154 err = s.Schedule(task) 155 return 156 } 157 158 func (s *taskScheduler) ScheduleScopedFn(ctx *tasks.Context, taskType tasks.TaskType, scope *common.ID, fn func() error) (task tasks.Task, err error) { 159 task = tasks.NewScopedFnTask(ctx, taskType, scope, fn) 160 err = s.Schedule(task) 161 return 162 } 163 164 func (s *taskScheduler) Schedule(task tasks.Task) (err error) { 165 taskType := task.Type() 166 // if taskType == tasks.DataCompactionTask || taskType == tasks.GCTask { 167 if taskType == tasks.DataCompactionTask { 168 dispatcher := s.Dispatchers[task.Type()].(*asyncJobDispatcher) 169 return dispatcher.TryDispatch(task) 170 } 171 return s.BaseScheduler.Schedule(task) 172 }