/// <exception cref="System.Exception"/> public virtual IWritable Call(RPC.Server server, string protocol, IWritable writableRequest , long receiveTime) { ProtobufRpcEngine.RpcRequestWrapper request = (ProtobufRpcEngine.RpcRequestWrapper )writableRequest; ProtobufRpcEngineProtos.RequestHeaderProto rpcRequest = request.requestHeader; string methodName = rpcRequest.GetMethodName(); string protoName = rpcRequest.GetDeclaringClassProtocolName(); long clientVersion = rpcRequest.GetClientProtocolVersion(); if (server.verbose) { Log.Info("Call: protocol=" + protocol + ", method=" + methodName); } RPC.Server.ProtoClassProtoImpl protocolImpl = GetProtocolImpl(server, protoName, clientVersion); BlockingService service = (BlockingService)protocolImpl.protocolImpl; Descriptors.MethodDescriptor methodDescriptor = service.GetDescriptorForType().FindMethodByName (methodName); if (methodDescriptor == null) { string msg = "Unknown method " + methodName + " called on " + protocol + " protocol."; Log.Warn(msg); throw new RpcNoSuchMethodException(msg); } Message prototype = service.GetRequestPrototype(methodDescriptor); Message param = prototype.NewBuilderForType().MergeFrom(request.theRequestRead).Build (); Message result; long startTime = Time.Now(); int qTime = (int)(startTime - receiveTime); Exception exception = null; try { server.rpcDetailedMetrics.Init(protocolImpl.protocolClass); result = service.CallBlockingMethod(methodDescriptor, null, param); } catch (ServiceException e) { exception = (Exception)e.InnerException; throw (Exception)e.InnerException; } catch (Exception e) { exception = e; throw; } finally { int processingTime = (int)(Time.Now() - startTime); if (Log.IsDebugEnabled()) { string msg = "Served: " + methodName + " queueTime= " + qTime + " procesingTime= " + processingTime; if (exception != null) { msg += " exception= " + exception.GetType().Name; } Log.Debug(msg); } string detailedMetricsName = (exception == null) ? methodName : exception.GetType ().Name; server.rpcMetrics.AddRpcQueueTime(qTime); server.rpcMetrics.AddRpcProcessingTime(processingTime); server.rpcDetailedMetrics.AddProcessingTime(detailedMetricsName, processingTime); } return(new ProtobufRpcEngine.RpcResponseWrapper(result)); }
/// <summary>This is the client side invoker of RPC method.</summary> /// <remarks> /// This is the client side invoker of RPC method. It only throws /// ServiceException, since the invocation proxy expects only /// ServiceException to be thrown by the method in case protobuf service. /// ServiceException has the following causes: /// <ol> /// <li>Exceptions encountered on the client side in this method are /// set as cause in ServiceException as is.</li> /// <li>Exceptions from the server are wrapped in RemoteException and are /// set as cause in ServiceException</li> /// </ol> /// Note that the client calling protobuf RPC methods, must handle /// ServiceException by getting the cause from the ServiceException. If the /// cause is RemoteException, then unwrap it to get the exception thrown by /// the server. /// </remarks> /// <exception cref="Com.Google.Protobuf.ServiceException"/> public virtual object Invoke(object proxy, MethodInfo method, object[] args) { long startTime = 0; if (Log.IsDebugEnabled()) { startTime = Time.Now(); } if (args.Length != 2) { // RpcController + Message throw new ServiceException("Too many parameters for request. Method: [" + method. Name + "]" + ", Expected: 2, Actual: " + args.Length); } if (args[1] == null) { throw new ServiceException("null param while calling Method: [" + method.Name + "]" ); } TraceScope traceScope = null; // if Tracing is on then start a new span for this rpc. // guard it in the if statement to make sure there isn't // any extra string manipulation. if (Trace.IsTracing()) { traceScope = Trace.StartSpan(RpcClientUtil.MethodToTraceString(method)); } ProtobufRpcEngineProtos.RequestHeaderProto rpcRequestHeader = ConstructRpcRequestHeader (method); if (Log.IsTraceEnabled()) { Log.Trace(Thread.CurrentThread().GetId() + ": Call -> " + remoteId + ": " + method.Name + " {" + TextFormat.ShortDebugString((Message)args[1]) + "}"); } Message theRequest = (Message)args[1]; ProtobufRpcEngine.RpcResponseWrapper val; try { val = (ProtobufRpcEngine.RpcResponseWrapper)client.Call(RPC.RpcKind.RpcProtocolBuffer , new ProtobufRpcEngine.RpcRequestWrapper(rpcRequestHeader, theRequest), remoteId , fallbackToSimpleAuth); } catch (Exception e) { if (Log.IsTraceEnabled()) { Log.Trace(Thread.CurrentThread().GetId() + ": Exception <- " + remoteId + ": " + method.Name + " {" + e + "}"); } if (Trace.IsTracing()) { traceScope.GetSpan().AddTimelineAnnotation("Call got exception: " + e.Message); } throw new ServiceException(e); } finally { if (traceScope != null) { traceScope.Close(); } } if (Log.IsDebugEnabled()) { long callTime = Time.Now() - startTime; Log.Debug("Call: " + method.Name + " took " + callTime + "ms"); } Message prototype = null; try { prototype = GetReturnProtoType(method); } catch (Exception e) { throw new ServiceException(e); } Message returnMessage; try { returnMessage = prototype.NewBuilderForType().MergeFrom(val.theResponseRead).Build (); if (Log.IsTraceEnabled()) { Log.Trace(Thread.CurrentThread().GetId() + ": Response <- " + remoteId + ": " + method.Name + " {" + TextFormat.ShortDebugString(returnMessage) + "}"); } } catch (Exception e) { throw new ServiceException(e); } return(returnMessage); }