github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/server.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 frontend 16 17 import ( 18 "context" 19 "io" 20 "strings" 21 "sync/atomic" 22 "time" 23 24 "go.uber.org/zap" 25 26 "github.com/fagongzi/goetty/v2" 27 28 "github.com/matrixorigin/matrixone/pkg/config" 29 "github.com/matrixorigin/matrixone/pkg/defines" 30 "github.com/matrixorigin/matrixone/pkg/logutil" 31 "github.com/matrixorigin/matrixone/pkg/queryservice" 32 ) 33 34 // RelationName counter for the new connection 35 var initConnectionID uint32 = 1000 36 37 // ConnIDAllocKey is used get connection ID from HAKeeper. 38 var ConnIDAllocKey = "____server_conn_id" 39 40 // MOServer MatrixOne Server 41 type MOServer struct { 42 addr string 43 uaddr string 44 app goetty.NetApplication 45 rm *RoutineManager 46 readTimeout time.Duration 47 } 48 49 // BaseService is an interface which indicates that the instance is 50 // the base CN service and should implements the following methods. 51 type BaseService interface { 52 // ID returns the ID of the service. 53 ID() string 54 // SQLAddress returns the SQL listen address of the service. 55 SQLAddress() string 56 // SessionMgr returns the session manager instance of the service. 57 SessionMgr() *queryservice.SessionManager 58 // CheckTenantUpgrade used to upgrade tenant metadata if the tenant is old version. 59 CheckTenantUpgrade(ctx context.Context, tenantID int64) error 60 // GetFinalVersion Get mo final version, which is based on the current code 61 GetFinalVersion() string 62 // UpgradeTenant used to upgrade tenant 63 UpgradeTenant(ctx context.Context, tenantName string, retryCount uint32, isALLAccount bool) error 64 } 65 66 func (mo *MOServer) GetRoutineManager() *RoutineManager { 67 return mo.rm 68 } 69 70 func (mo *MOServer) Start() error { 71 logutil.Infof("Server Listening on : %s ", mo.addr) 72 return mo.app.Start() 73 } 74 75 func (mo *MOServer) Stop() error { 76 return mo.app.Stop() 77 } 78 79 func nextConnectionID() uint32 { 80 return atomic.AddUint32(&initConnectionID, 1) 81 } 82 83 var globalRtMgr atomic.Value 84 var globalPu atomic.Value 85 var globalAicm atomic.Value 86 87 func setGlobalRtMgr(rtMgr *RoutineManager) { 88 globalRtMgr.Store(rtMgr) 89 } 90 91 func getGlobalRtMgr() *RoutineManager { 92 return globalRtMgr.Load().(*RoutineManager) 93 } 94 95 func setGlobalPu(pu *config.ParameterUnit) { 96 globalPu.Store(pu) 97 } 98 99 func getGlobalPu() *config.ParameterUnit { 100 return globalPu.Load().(*config.ParameterUnit) 101 } 102 103 func setGlobalAicm(aicm *defines.AutoIncrCacheManager) { 104 globalAicm.Store(aicm) 105 } 106 107 func getGlobalAic() *defines.AutoIncrCacheManager { 108 if globalAicm.Load() != nil { 109 return globalAicm.Load().(*defines.AutoIncrCacheManager) 110 } 111 return nil 112 } 113 114 func NewMOServer( 115 ctx context.Context, 116 addr string, 117 pu *config.ParameterUnit, 118 aicm *defines.AutoIncrCacheManager, 119 baseService BaseService, 120 ) *MOServer { 121 setGlobalPu(pu) 122 setGlobalAicm(aicm) 123 codec := NewSqlCodec() 124 rm, err := NewRoutineManager(ctx) 125 if err != nil { 126 logutil.Panicf("start server failed with %+v", err) 127 } 128 setGlobalRtMgr(rm) 129 rm.setBaseService(baseService) 130 if baseService != nil { 131 rm.setSessionMgr(baseService.SessionMgr()) 132 } 133 // TODO asyncFlushBatch 134 addresses := []string{addr} 135 unixAddr := pu.SV.GetUnixSocketAddress() 136 if unixAddr != "" { 137 addresses = append(addresses, "unix://"+unixAddr) 138 } 139 mo := &MOServer{ 140 addr: addr, 141 uaddr: pu.SV.UnixSocketAddress, 142 rm: rm, 143 readTimeout: pu.SV.SessionTimeout.Duration, 144 } 145 app, err := goetty.NewApplicationWithListenAddress( 146 addresses, 147 rm.Handler, 148 goetty.WithAppLogger(logutil.GetGlobalLogger()), 149 goetty.WithAppHandleSessionFunc(mo.handleMessage), 150 goetty.WithAppSessionOptions( 151 goetty.WithSessionCodec(codec), 152 goetty.WithSessionLogger(logutil.GetGlobalLogger()), 153 goetty.WithSessionRWBUfferSize(DefaultRpcBufferSize, DefaultRpcBufferSize), 154 goetty.WithSessionAllocator(NewSessionAllocator(pu))), 155 goetty.WithAppSessionAware(rm), 156 //when the readTimeout expires the goetty will close the tcp connection. 157 goetty.WithReadTimeout(pu.SV.SessionTimeout.Duration)) 158 if err != nil { 159 logutil.Panicf("start server failed with %+v", err) 160 } 161 err = initVarByConfig(ctx, pu) 162 if err != nil { 163 logutil.Panicf("start server failed with %+v", err) 164 } 165 mo.app = app 166 return mo 167 } 168 169 // handleMessage receives the message from the client and executes it 170 func (mo *MOServer) handleMessage(rs goetty.IOSession) error { 171 received := uint64(0) 172 option := goetty.ReadOptions{Timeout: mo.readTimeout} 173 for { 174 msg, err := rs.Read(option) 175 if err != nil { 176 if err == io.EOF { 177 return nil 178 } 179 180 logutil.Error("session read failed", 181 zap.Error(err)) 182 return err 183 } 184 185 received++ 186 187 err = mo.rm.Handler(rs, msg, received) 188 if err != nil { 189 if skipClientQuit(err.Error()) { 190 return nil 191 } else { 192 logutil.Error("session handle failed, close this session", zap.Error(err)) 193 } 194 return err 195 } 196 } 197 } 198 199 func initVarByConfig(ctx context.Context, pu *config.ParameterUnit) error { 200 var err error 201 if strings.ToLower(pu.SV.SaveQueryResult) == "on" { 202 err = GSysVariables.SetGlobalSysVar(ctx, "save_query_result", pu.SV.SaveQueryResult) 203 if err != nil { 204 return err 205 } 206 } 207 208 err = GSysVariables.SetGlobalSysVar(ctx, "query_result_maxsize", pu.SV.QueryResultMaxsize) 209 if err != nil { 210 return err 211 } 212 213 err = GSysVariables.SetGlobalSysVar(ctx, "query_result_timeout", pu.SV.QueryResultTimeout) 214 if err != nil { 215 return err 216 } 217 218 err = GSysVariables.SetGlobalSysVar(ctx, "lower_case_table_names", pu.SV.LowerCaseTableNames) 219 if err != nil { 220 return err 221 } 222 return err 223 }