github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/db/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 db 16 17 import ( 18 "sync" 19 20 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common" 21 "github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tasks" 22 ) 23 24 func ScopeConflictCheck(oldScope, newScope *common.ID) (err error) { 25 if oldScope.TableID != newScope.TableID { 26 return 27 } 28 if oldScope.SegmentID != newScope.SegmentID { 29 if oldScope.SegmentID != 0 && newScope.SegmentID != 0 { 30 return 31 } 32 return tasks.ErrScheduleScopeConflict 33 } 34 if oldScope.BlockID != newScope.BlockID && oldScope.BlockID != 0 && newScope.BlockID != 0 { 35 return 36 } 37 return tasks.ErrScheduleScopeConflict 38 } 39 40 type asyncJobDispatcher struct { 41 sync.RWMutex 42 *tasks.BaseDispatcher 43 actives map[common.ID]bool 44 } 45 46 func newAsyncJobDispatcher() *asyncJobDispatcher { 47 return &asyncJobDispatcher{ 48 actives: make(map[common.ID]bool), 49 BaseDispatcher: tasks.NewBaseDispatcher(), 50 } 51 } 52 53 func (dispatcher *asyncJobDispatcher) checkConflictLocked(scopes []common.ID) (err error) { 54 for active := range dispatcher.actives { 55 for _, scope := range scopes { 56 if err = ScopeConflictCheck(&active, &scope); err != nil { 57 return 58 } 59 } 60 } 61 return 62 } 63 64 func (dispatcher *asyncJobDispatcher) TryDispatch(task tasks.Task) (err error) { 65 mscoped := task.(tasks.MScopedTask) 66 scopes := mscoped.Scopes() 67 if len(scopes) == 0 { 68 dispatcher.Dispatch(task) 69 return 70 } 71 dispatcher.Lock() 72 if err = dispatcher.checkConflictLocked(scopes); err != nil { 73 // str := "" 74 // for scope := range dispatcher.actives { 75 // str = fmt.Sprintf("%s%s,", str, scope.String()) 76 // } 77 // logutil.Warnf("ActiveScopes: %s, Incomming: %s", str, common.IDArraryString(scopes)) 78 dispatcher.Unlock() 79 return 80 } 81 for _, scope := range scopes { 82 dispatcher.actives[scope] = true 83 } 84 task.AddObserver(dispatcher) 85 dispatcher.Unlock() 86 dispatcher.Dispatch(task) 87 return 88 } 89 90 func (dispatcher *asyncJobDispatcher) OnExecDone(v any) { 91 task := v.(tasks.MScopedTask) 92 scopes := task.Scopes() 93 dispatcher.Lock() 94 for _, scope := range scopes { 95 delete(dispatcher.actives, scope) 96 } 97 dispatcher.Unlock() 98 }