/** * When an error comes in, this handles it */ public void HandleError(ReqrepManager man, int message_number, ReqrepManager.ReqrepError err, ISender ret_path, object state) { Exception x = null; RpcRequestState rs = (RpcRequestState)state; Channel bq = rs.Results; switch (err) { case ReqrepManager.ReqrepError.NoHandler: x = new AdrException(-32601, "No RPC Handler on remote host"); break; case ReqrepManager.ReqrepError.HandlerFailure: x = new AdrException(-32603, "The remote RPC System had a problem"); break; case ReqrepManager.ReqrepError.Timeout: //In this case we close the Channel: if (bq != null) { bq.Close(); } break; case ReqrepManager.ReqrepError.Send: //We had some problem sending, but ignore it for now break; } if (x != null && (bq != null)) { RpcResult res = new RpcResult(ret_path, x); bq.Enqueue(res); } }
/** * Implements the IReplyHandler (also provides some light-weight statistics) */ public bool HandleReply(ReqrepManager man, ReqrepManager.ReqrepType rt, int mid, PType prot, MemBlock payload, ISender ret_path, ReqrepManager.Statistics statistics, object state) { RpcRequestState rs = (RpcRequestState)state; //ISender target = rs.RpcTarget; Channel bq = rs.Results; if (bq != null) { object data = AdrConverter.Deserialize(payload); RpcResult res = new RpcResult(ret_path, data, statistics); //handle possible exception: try { bq.Enqueue(res); //Keep listening unless the queue is closed return(!bq.Closed); } catch (System.InvalidOperationException) { //The queue is closed, stop listening for more results: return(false); } } else { //If they didn't even pass us a queue, I guess they didn't want to //listen too long return(false); } }
/** * This is how you invoke a method on a remote host. * Results are put into the Channel. * * If you want to have an Event based approach, listen to the EnqueueEvent * on the Channel you pass for the results. That will be fired * immediately from the thread that gets the result. * * When a result comes back, we put and RpcResult into the Channel. * When you have enough responses, Close the queue (please). The code * will stop sending requests after the queue is closed. If you never close * the queue, this will be wasteful of resources. * * @param target the sender to use when making the RPC call * @param q the Channel into which the RpcResult objects will be placed. * q may be null if you don't care about the response. * @param method the Rpc method to call * * @throw Exception if we cannot send the request for some reason. */ virtual public void Invoke(ISender target, Channel q, string method, params object[] args) { //build state for the RPC call RpcRequestState rs = new RpcRequestState(); rs.Results = q; rs.RpcTarget = target; object[] rpc_call = new object[2]; rpc_call[0] = method; if (args != null) { rpc_call[1] = args; } else { //There are no args, which we represent as a zero length list rpc_call[1] = new object[0]; } AdrCopyable req_copy = new AdrCopyable(rpc_call); #if RPC_DEBUG Console.Error.WriteLine("[RpcClient: {0}] Invoking method: {1} on target: {2}", _rrman.Info, method, target); #endif ICopyable rrpayload = new CopyList(PType.Protocol.Rpc, req_copy); int reqid = _rrman.SendRequest(target, ReqrepManager.ReqrepType.Request, rrpayload, this, rs); //Make sure we stop this request when the queue is closed. if (q != null) { try { q.CloseEvent += delegate(object qu, EventArgs eargs) { _rrman.StopRequest(reqid, this); }; } catch { if (q.Closed) { _rrman.StopRequest(reqid, this); } else { throw; } } } }
/** * This is how you invoke a method on a remote host. * Results are put into the Channel. * * If you want to have an Event based approach, listen to the EnqueueEvent * on the Channel you pass for the results. That will be fired * immediately from the thread that gets the result. * * When a result comes back, we put and RpcResult into the Channel. * When you have enough responses, Close the queue (please). The code * will stop sending requests after the queue is closed. If you never close * the queue, this will be wasteful of resources. * * @param target the sender to use when making the RPC call * @param q the Channel into which the RpcResult objects will be placed. * q may be null if you don't care about the response. * @param method the Rpc method to call * * @throw Exception if we cannot send the request for some reason. */ virtual public void Invoke(ISender target, Channel q, string method, params object[] args) { //build state for the RPC call RpcRequestState rs = new RpcRequestState(); rs.Results = q; rs.RpcTarget = target; object[] rpc_call = new object[2]; rpc_call[0] = method; if( args != null ) { rpc_call[1] = args; } else { //There are no args, which we represent as a zero length list rpc_call[1] = new object[0]; } AdrCopyable req_copy = new AdrCopyable(rpc_call); #if RPC_DEBUG Console.Error.WriteLine("[RpcClient: {0}] Invoking method: {1} on target: {2}", _rrman.Info, method, target); #endif ICopyable rrpayload = new CopyList( PType.Protocol.Rpc, req_copy ); int reqid = _rrman.SendRequest(target, ReqrepManager.ReqrepType.Request, rrpayload, this, rs); //Make sure we stop this request when the queue is closed. if( q != null ) { try { q.CloseEvent += delegate(object qu, EventArgs eargs) { _rrman.StopRequest(reqid, this); }; } catch { if(q.Closed) { _rrman.StopRequest(reqid, this); } else { throw; } } } }