github.com/matrixorigin/matrixone@v1.2.0/pkg/vm/engine/tae/tasks/dispatcher.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 tasks 16 17 import ( 18 "io" 19 "sync/atomic" 20 21 "github.com/matrixorigin/matrixone/pkg/common/moerr" 22 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 23 ) 24 25 var ( 26 ErrDispatchWrongTask = moerr.NewInternalErrorNoCtx("tae: wrong task type") 27 ) 28 29 type Dispatcher interface { 30 io.Closer 31 Dispatch(Task) 32 } 33 34 type TaskHandler interface { 35 io.Closer 36 Start() 37 Enqueue(Task) 38 Execute(Task) 39 } 40 41 type BaseDispatcher struct { 42 handlers map[TaskType]TaskHandler 43 } 44 45 func NewBaseDispatcher() *BaseDispatcher { 46 d := &BaseDispatcher{ 47 handlers: make(map[TaskType]TaskHandler), 48 } 49 return d 50 } 51 52 func (d *BaseDispatcher) Dispatch(task Task) { 53 handler, ok := d.handlers[task.Type()] 54 if !ok { 55 panic(ErrDispatchWrongTask) 56 } 57 handler.Enqueue(task) 58 } 59 60 func (d *BaseDispatcher) RegisterHandler(t TaskType, h TaskHandler) { 61 d.handlers[t] = h 62 } 63 64 func (d *BaseDispatcher) Close() error { 65 for _, h := range d.handlers { 66 h.Close() 67 } 68 return nil 69 } 70 71 type ScopedTaskSharder = func(scope *common.ID) int 72 type BaseScopedDispatcher struct { 73 handlers []TaskHandler 74 sharder ScopedTaskSharder 75 curr uint64 76 } 77 78 func NewBaseScopedDispatcher(sharder ScopedTaskSharder) *BaseScopedDispatcher { 79 d := &BaseScopedDispatcher{ 80 handlers: make([]TaskHandler, 0), 81 curr: 0, 82 } 83 if sharder == nil { 84 d.sharder = d.roundRobinSharder 85 } else { 86 d.sharder = sharder 87 } 88 return d 89 } 90 91 func (d *BaseScopedDispatcher) AddHandle(h TaskHandler) { 92 d.handlers = append(d.handlers, h) 93 } 94 95 func (d *BaseScopedDispatcher) roundRobinSharder(scope *common.ID) int { 96 curr := atomic.AddUint64(&d.curr, uint64(1)) 97 return int(curr) 98 } 99 100 func (d *BaseScopedDispatcher) Dispatch(task Task) { 101 scoped := task.(ScopedTask) 102 val := d.sharder(scoped.Scope()) 103 104 shardIdx := val % len(d.handlers) 105 d.handlers[shardIdx].Enqueue(task) 106 } 107 108 func (d *BaseScopedDispatcher) Close() error { 109 for _, h := range d.handlers { 110 h.Close() 111 } 112 return nil 113 }