github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/allegrosql/server/rpc_server.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "context" 18 "fmt" 19 20 "github.com/whtcorpsinc/ekvproto/pkg/diagnosticspb" 21 "github.com/whtcorpsinc/ekvproto/pkg/einsteindbpb" 22 "github.com/whtcorpsinc/ekvproto/pkg/interlock" 23 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb" 24 "github.com/whtcorpsinc/milevadb/causetstore/mockstore/entangledstore" 25 "github.com/whtcorpsinc/milevadb/causetstore/mockstore/mockeinsteindb" 26 "github.com/whtcorpsinc/milevadb/config" 27 "github.com/whtcorpsinc/milevadb/interlock" 28 "github.com/whtcorpsinc/milevadb/petri" 29 "github.com/whtcorpsinc/milevadb/privilege" 30 "github.com/whtcorpsinc/milevadb/privilege/privileges" 31 "github.com/whtcorpsinc/milevadb/soliton" 32 "github.com/whtcorpsinc/milevadb/soliton/logutil" 33 "github.com/whtcorpsinc/milevadb/soliton/memory" 34 "github.com/whtcorpsinc/milevadb/stochastik" 35 "github.com/whtcorpsinc/sysutil" 36 "go.uber.org/zap" 37 "google.golang.org/grpc" 38 ) 39 40 // NewRPCServer creates a new rpc server. 41 func NewRPCServer(config *config.Config, dom *petri.Petri, sm soliton.StochastikManager) *grpc.Server { 42 defer func() { 43 if v := recover(); v != nil { 44 logutil.BgLogger().Error("panic in MilevaDB RPC server", zap.Reflect("r", v), 45 zap.Stack("stack trace")) 46 } 47 }() 48 49 s := grpc.NewServer() 50 rpcSrv := &rpcServer{ 51 DiagnosticsServer: sysutil.NewDiagnosticsServer(config.Log.File.Filename), 52 dom: dom, 53 sm: sm, 54 } 55 // For redirection the cop task. 56 mockeinsteindb.GRPCClientFactory = func() mockeinsteindb.Client { 57 return einsteindb.NewTestRPCClient(config.Security) 58 } 59 entangledstore.GRPCClientFactory = func() entangledstore.Client { 60 return einsteindb.NewTestRPCClient(config.Security) 61 } 62 diagnosticspb.RegisterDiagnosticsServer(s, rpcSrv) 63 einsteindbpb.RegisterEinsteinDBServer(s, rpcSrv) 64 return s 65 } 66 67 // rpcServer contains below 2 services: 68 // 1. Diagnose service, it's used for ALLEGROALLEGROSQL diagnose. 69 // 2. Coprocessor service, it reuse the EinsteinDBServer interface, but only support the Coprocessor interface now. 70 // Coprocessor service will handle the cop task from other MilevaDB server. Currently, it's only use for read the cluster memory causet. 71 type rpcServer struct { 72 *sysutil.DiagnosticsServer 73 einsteindbpb.EinsteinDBServer 74 dom *petri.Petri 75 sm soliton.StochastikManager 76 } 77 78 // Coprocessor implements the EinsteinDBServer interface. 79 func (s *rpcServer) Coprocessor(ctx context.Context, in *interlock.Request) (resp *interlock.Response, err error) { 80 resp = &interlock.Response{} 81 defer func() { 82 if v := recover(); v != nil { 83 logutil.BgLogger().Error("panic when RPC server handing interlock", zap.Reflect("r", v), 84 zap.Stack("stack trace")) 85 resp.OtherError = fmt.Sprintf("panic when RPC server handing interlock, stack:%v", v) 86 } 87 }() 88 resp = s.handleCopRequest(ctx, in) 89 return resp, nil 90 } 91 92 // CoprocessorStream implements the EinsteinDBServer interface. 93 func (s *rpcServer) CoprocessorStream(in *interlock.Request, stream einsteindbpb.EinsteinDB_CoprocessorStreamServer) (err error) { 94 resp := &interlock.Response{} 95 defer func() { 96 if v := recover(); v != nil { 97 logutil.BgLogger().Error("panic when RPC server handing interlock stream", zap.Reflect("r", v), 98 zap.Stack("stack trace")) 99 resp.OtherError = fmt.Sprintf("panic when when RPC server handing interlock stream, stack:%v", v) 100 err = stream.Send(resp) 101 if err != nil { 102 logutil.BgLogger().Error("panic when RPC server handing interlock stream, send response to stream error", zap.Error(err)) 103 } 104 } 105 }() 106 107 se, err := s.createStochastik() 108 if err != nil { 109 resp.OtherError = err.Error() 110 return stream.Send(resp) 111 } 112 defer se.Close() 113 114 h := interlock.NewCoprocessorPosetDagHandler(se) 115 return h.HandleStreamRequest(context.Background(), in, stream) 116 } 117 118 // BatchCommands implements the EinsteinDBServer interface. 119 func (s *rpcServer) BatchCommands(ss einsteindbpb.EinsteinDB_BatchCommandsServer) error { 120 defer func() { 121 if v := recover(); v != nil { 122 logutil.BgLogger().Error("panic when RPC server handing batch commands", zap.Reflect("r", v), 123 zap.Stack("stack trace")) 124 } 125 }() 126 for { 127 reqs, err := ss.Recv() 128 if err != nil { 129 logutil.BgLogger().Error("RPC server batch commands receive fail", zap.Error(err)) 130 return err 131 } 132 133 responses := make([]*einsteindbpb.BatchCommandsResponse_Response, 0, len(reqs.Requests)) 134 for _, req := range reqs.Requests { 135 var response *einsteindbpb.BatchCommandsResponse_Response 136 switch request := req.Cmd.(type) { 137 case *einsteindbpb.BatchCommandsRequest_Request_Coprocessor: 138 cop := request.Coprocessor 139 resp, err := s.Coprocessor(context.Background(), cop) 140 if err != nil { 141 return err 142 } 143 response = &einsteindbpb.BatchCommandsResponse_Response{ 144 Cmd: &einsteindbpb.BatchCommandsResponse_Response_Coprocessor{ 145 Coprocessor: resp, 146 }, 147 } 148 case *einsteindbpb.BatchCommandsRequest_Request_Empty: 149 response = &einsteindbpb.BatchCommandsResponse_Response{ 150 Cmd: &einsteindbpb.BatchCommandsResponse_Response_Empty{ 151 Empty: &einsteindbpb.BatchCommandsEmptyResponse{ 152 TestId: request.Empty.TestId, 153 }, 154 }, 155 } 156 default: 157 logutil.BgLogger().Info("RPC server batch commands receive unknown request", zap.Any("req", request)) 158 response = &einsteindbpb.BatchCommandsResponse_Response{ 159 Cmd: &einsteindbpb.BatchCommandsResponse_Response_Empty{ 160 Empty: &einsteindbpb.BatchCommandsEmptyResponse{}, 161 }, 162 } 163 } 164 responses = append(responses, response) 165 } 166 167 err = ss.Send(&einsteindbpb.BatchCommandsResponse{ 168 Responses: responses, 169 RequestIds: reqs.GetRequestIds(), 170 }) 171 if err != nil { 172 logutil.BgLogger().Error("RPC server batch commands send fail", zap.Error(err)) 173 return err 174 } 175 } 176 } 177 178 // handleCopRequest handles the cop posetPosetDag request. 179 func (s *rpcServer) handleCopRequest(ctx context.Context, req *interlock.Request) *interlock.Response { 180 resp := &interlock.Response{} 181 se, err := s.createStochastik() 182 if err != nil { 183 resp.OtherError = err.Error() 184 return resp 185 } 186 defer se.Close() 187 188 h := interlock.NewCoprocessorPosetDagHandler(se) 189 return h.HandleRequest(ctx, req) 190 } 191 192 func (s *rpcServer) createStochastik() (stochastik.Stochastik, error) { 193 se, err := stochastik.CreateStochastikWithPetri(s.dom.CausetStore(), s.dom) 194 if err != nil { 195 return nil, err 196 } 197 do := petri.GetPetri(se) 198 is := do.SchemaReplicant() 199 pm := &privileges.UserPrivileges{ 200 Handle: do.PrivilegeHandle(), 201 } 202 privilege.BindPrivilegeManager(se, pm) 203 se.GetStochastikVars().TxnCtx.SchemaReplicant = is 204 // This is for disable parallel hash agg. 205 // TODO: remove this. 206 se.GetStochastikVars().SetHashAggPartialConcurrency(1) 207 se.GetStochastikVars().SetHashAggFinalConcurrency(1) 208 se.GetStochastikVars().StmtCtx.MemTracker = memory.NewTracker(memory.LabelForCoprocessor, -1) 209 se.SetStochastikManager(s.sm) 210 return se, nil 211 }