github.com/matrixorigin/matrixone@v1.2.0/pkg/common/runtime/runtime.go (about) 1 // Copyright 2022 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 runtime 16 17 import ( 18 "context" 19 "sync" 20 "sync/atomic" 21 "time" 22 23 "github.com/matrixorigin/matrixone/pkg/common/log" 24 "github.com/matrixorigin/matrixone/pkg/common/moerr" 25 "github.com/matrixorigin/matrixone/pkg/defines" 26 "github.com/matrixorigin/matrixone/pkg/logutil" 27 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 28 "github.com/matrixorigin/matrixone/pkg/txn/clock" 29 "go.uber.org/zap" 30 "go.uber.org/zap/zapcore" 31 ) 32 33 var ( 34 processLevel atomic.Value 35 ) 36 37 type LoggerName int 38 39 const ( 40 Default LoggerName = iota 41 SystemInit 42 ) 43 44 // ProcessLevelRuntime returns a process-lelve runtime 45 func ProcessLevelRuntime() Runtime { 46 v := processLevel.Load() 47 if v == nil { 48 return nil 49 } 50 return v.(Runtime) 51 } 52 53 // SetupProcessLevelRuntime set a process-level runtime. If the service does not 54 // support a service-level runtime when running in launch mode, it will use the 55 // process-level runtime. The process-level runtime must setup in main. 56 func SetupProcessLevelRuntime(r Runtime) { 57 processLevel.Store(r) 58 if _, ok := ProcessLevelRuntime().GetGlobalVariables(MOProtocolVersion); !ok { 59 ProcessLevelRuntime().SetGlobalVariables(MOProtocolVersion, defines.MORPCLatestVersion) 60 } 61 } 62 63 // WithClock setup clock for a runtime, CN and TN must contain an instance of the 64 // Clock that is used to provide the timestamp service to the transaction. 65 func WithClock(clock clock.Clock) Option { 66 return func(r *runtime) { 67 r.global.clock = clock 68 } 69 } 70 71 // NewRuntime create a mo runtime environment. 72 func NewRuntime(service metadata.ServiceType, uuid string, logger *zap.Logger, opts ...Option) Runtime { 73 rt := &runtime{ 74 serviceType: service, 75 serviceUUID: uuid, 76 } 77 for _, opt := range opts { 78 opt(rt) 79 } 80 rt.global.logger = log.GetServiceLogger(logutil.Adjust(logger), service, uuid) 81 rt.initSystemInitLogger() 82 return rt 83 } 84 85 type runtime struct { 86 serviceType metadata.ServiceType 87 serviceUUID string 88 89 global struct { 90 clock clock.Clock 91 logger *log.MOLogger 92 variables sync.Map 93 94 systemInitLogger *log.MOLogger 95 } 96 } 97 98 func (r *runtime) Logger() *log.MOLogger { 99 return r.global.logger 100 } 101 102 func (r *runtime) SubLogger(name LoggerName) *log.MOLogger { 103 switch name { 104 case SystemInit: 105 return r.global.systemInitLogger 106 default: 107 return r.Logger() 108 } 109 } 110 111 func (r *runtime) Clock() clock.Clock { 112 return r.global.clock 113 } 114 115 func (r *runtime) ServiceType() metadata.ServiceType { 116 return r.serviceType 117 } 118 119 func (r *runtime) ServiceUUID() string { 120 return r.serviceUUID 121 } 122 123 func (r *runtime) SetGlobalVariables(name string, value any) { 124 r.global.variables.Store(name, value) 125 } 126 127 func (r *runtime) GetGlobalVariables(name string) (any, bool) { 128 return r.global.variables.Load(name) 129 } 130 131 // DefaultRuntime used to test 132 func DefaultRuntime() Runtime { 133 return DefaultRuntimeWithLevel(zap.DebugLevel) 134 } 135 136 // DefaultRuntime used to test 137 func DefaultRuntimeWithLevel(level zapcore.Level) Runtime { 138 return NewRuntime( 139 metadata.ServiceType_CN, 140 "", 141 logutil.GetPanicLoggerWithLevel(level), 142 WithClock(clock.NewHLCClock(func() int64 { 143 return time.Now().UTC().UnixNano() 144 }, 0))) 145 } 146 147 func (r *runtime) initSystemInitLogger() { 148 if r.global.logger == nil { 149 r.global.logger = log.GetServiceLogger(logutil.Adjust(nil), r.serviceType, r.serviceUUID) 150 } 151 r.global.systemInitLogger = r.Logger().WithProcess(log.SystemInit) 152 } 153 154 type methodType interface { 155 ~int32 156 String() string 157 } 158 159 func CheckMethodVersion[Req interface{ GetMethod() T }, T methodType](ctx context.Context, versionMap map[T]int64, req Req) error { 160 if version, ok := versionMap[req.GetMethod()]; !ok { 161 return moerr.NewNotSupported(ctx, "%s not support in current version", req.GetMethod().String()) 162 } else { 163 v, ok := ProcessLevelRuntime().GetGlobalVariables(MOProtocolVersion) 164 if !ok { 165 return moerr.NewInternalError(ctx, "failed to get protocol version") 166 } 167 if v.(int64) < version { 168 return moerr.NewInternalError(ctx, "unsupported protocol version %d", version) 169 } 170 } 171 return nil 172 }