IRpcHanlderApiCallSeq

From Grid-Appliance Wiki

Jump to: navigation, search

Contents

API call sequence

You can refer to the source code comment for detailed explaination. Here, I will explain api calling sequence for reference. This section may not be useful if you are not interested in how inside brunet rpc handler works.

Add hander to RpcManager of currently connected brunet node

1. Add handler to the Rpc Manager of currently connected brunet node. XML rpc call, whose prefix is "HwRpc", will be forwarded to this class.

_node.Rpc.AddHandler("HwRpc", this);

2. RpcManager.AddHandler() method saves the prefix name space and handler to the local hash table(brunet/src/protocol/RpcManager.cs).

public void AddHandler(string name_space, object handler) {
  IRpcHandler h = handler as IRpcHandler;
  _method_handlers.Add(name_space, h);
  _method_cache.Clear();
}


Receiving rpc call from local user

1. local proxy is called when the user invokes rpc call. Local proxy method calls proxy method.(brunet/src/xmlrpc/XmlRpcManager.cs)

public object localproxy(string method, params object[] args) {
  object[] results = this.Proxy(_node, 1, method, args);
  return results[0];
}


2. Proxy method invokes the rpc call to the StructuredNode. Until response time expires, it checks queue. If response arrives at the queue, this method dequeues the response, and return it. (brunet/src/xmlrpc/XmlRpcManager)

private object[] Proxy(ISender sender,int maxResultsToWait, string method, object[] args) {
  foreach(object a in args){
    _rpc.Invoke(sender, q, method, args);
  }
  do {
    RpcResult rpcRs = (RpcResult)q.Dequeue();
    rsSender = rpcRs.ResultSender;  
    object val = rpcRs.Result;
    object xmlrpc_val = AdrXmlRpcConverter.Adr2XmlRpc(val); 
    allValues.Add(xmlrpc_val);
  } while (maxResultsToWait < 0 ? true : (counter < maxResultsToWait));  
  return allValues.ToArray();
}


3. At the RpcManager.Invoke() method, it creates new object which is suitable for SendRequest using method name and argument. Then, it sends the request using ReqrepManager.It also registers itself as an reply handler to handle reply when it comes back.(brunet/src/protocol/RpcManager.cs)

virtual public void Invoke(ISender target, Channel q, string method,params object[] args){
  object[] rpc_call = new object[2];
  rpc_call[0] = method;
  rpc_call[1] = args;
  AdrCopyable req_copy = new AdrCopyable(rpc_call);
  ICopyable rrpayload = new CopyList( PType.Protocol.Rpc, req_copy ); 
  int reqid = _rrman.SendRequest(target, ReqrepManager.ReqrepType.Request,rrpayload, this, rs);
}


4. This method sends request to the address specified at the sender object.(brunet/src/protocol/ReqrepManager.cs)

public int SendRequest(ISender sender, ReqrepType reqt, ICopyable data,IReplyHandler reply, object state{
  RequestState rs = new RequestState();
  rs.Sender = sender;      
  rs.Send();
  return rs.RequestID;
}

5. Request is passed to ReqrepManager class. Sender is set at the previous method(ReqrepManager.SendReqeust) as the ISender object.(brunet/src/protocol/ReqrepManager.cs)

public void Send() {
  Sender.Send( Request );
}

6. Node.Send() method is invoked at the previous step. This method invokes HandleData to enqueue the request.(brunet/src/protocol/Node.cs)

public void Send(ICopyable data) {
  this.HandleData(mb, this, null);
}

7. Create AnnounceState instance and enqueue the instance. (brunet/src/protocol/Node.cs)

public void HandleData(MemBlock data, ISender return_path, object state) {
  AnnounceState astate = new AnnounceState(this, data, return_path);
  EnqueueAction(astate);
}


7.5. I cannot notice how this enqueued request arrived at the ReqrepManager class. Your comments would be appreciated.

8. The request arrived at ReqrepManger object's HandleData method.(brunet/src/protocol/ReqrepManager.cs)

public void HandleData(MemBlock p, ISender from, object state){
  HandleRequest(rt, idnum, rest, from);
}

9. HandleRequest method invokes Handle of already subcribed handler.(brunet/src/protocol/ReqrepManager.cs)

protected void HandleRequest(ReqrepType rt, int idnum, MemBlock rest, ISender retpath){
  _sub.Handle(rest, rs);
}

10. This method passes data to the subscribed handler and call HandleData method of each handler.(brunet/src/protocol/Util/Source.cs)

public void Handle(MemBlock b, ISender retpath) {
  Handler.HandleData(b, retpath, State);
}

11. Request arrives at RpcManager.HandleData. This method calls IRpcHandler.HandleRpc.(brunet/src/protocol/RpcManager.cs)

public void HandleData(MemBlock payload, ISender ret_path, object state){
  handler.HandleRpc(ret_path, mname, pa, ret_path);
}


12. HandleRpc method in HelloWorldRpcHandler class prints result in the console, and it sends back the result. (HelloWorldRpcSHandler.cs)

public void HandleRpc(ISender caller, string method, IList arguments, object request_state){
  Console.WriteLine(caller + ": " + method + " : " + Encoding.ASCII.GetString(arguments[0] as byte[]));
  _node.Rpc.SendResult(request_state, arguments[0]);
}


Sending rpc call result back to the user

1. HandleRpc method at HelloWorldRpcHandler calls RpcManager.SendResult() method to send result back.(HelloWorldRpcSHandler.cs)

public void HandleRpc(ISender caller, string method, IList arguments, object request_state){
  _node.Rpc.SendResult(request_state, arguments[0]);
}

2. RpcManager send the result to the return path.(brunet/src/protocol/RpcManager.cs)

public virtual void SendResult(object request_state, object result) {
  ret_path.Send( new CopyList( PType.Protocol.Rpc, r_copy ) );
}

3. Previously called Send method is forwarded to Node.Send() method.(brunet/src/protocol/Node.cs)

public void Send(ICopyable data) {
  this.HandleData(mb, this, null);
}

4. Node.HandleData() method creates AnnounceState instance and enqueue the instance. (brunet/src/protocol/Node.cs)

public void HandleData(MemBlock data, ISender return_path, object state) {
  AnnounceState astate = new AnnounceState(this, data, return_path);
  EnqueueAction(astate);
}

4.5. I cannot notice how this enqueued response arrived at the Source class. Your comments would be appreciated.

5. Previously enqueued response arrived at the Source.Handle(). This method passes data to the subscribed handler and call HandleData method of each handler.(brunet/src/protocol/Util/Source.cs)

public void Handle(MemBlock b, ISender retpath) {
  Handler.HandleData(b, retpath, State);
}

6. ReqrepManager.HandleData() is invoked. This is a response, so HandleReply method is invoked,(brunet/src/protocol/ReqrepManager.cs)

public void HandleData(MemBlock p, ISender from, object state){
  HandleReply(rt, idnum, rest, from);
}

7. This method inquries appropriate reply handler, and invokes HandleReply method of the handler.(brunet/src/protocol/ReqrepManager.cs)

protected void HandleReply(ReqrepType rt, int idnum, MemBlock rest, ISender ret_path) {
  RequestState reqs = (RequestState)_req_state_table[idnum];
  IReplyHandler handler = reqs.ReplyHandler;
  bool continue_listening = handler.HandleReply(this, rt, idnum, pt, payload, ret_path, statistics, reqs.UserState);
}

8. RpcManager.HandleReply() is invoked. It enqueues the result which will be dequeued by XMLRpcManager.(brunet/src/protocol/RpcManager.cs)

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;
  Channel bq = rs.Results;
  RpcResult res = new RpcResult(ret_path, data, statistics);
  bq.Enqueue(res);
}

9. XMLRpcManager.Proxy() dequeues the result, and return the result to the requestor. (brunet/src/xmlrpc/XmlRpcManager)

private object[] Proxy(ISender sender,int maxResultsToWait, string method, object[] args) {
  do {
    RpcResult rpcRs = (RpcResult)q.Dequeue();
    rsSender = rpcRs.ResultSender;  
    object val = rpcRs.Result;
    object xmlrpc_val = AdrXmlRpcConverter.Adr2XmlRpc(val); 
    allValues.Add(xmlrpc_val);
  } while (maxResultsToWait < 0 ? true : (counter < maxResultsToWait));  
  return allValues.ToArray();
}
Personal tools