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