Implementing RPC using reflection
From Grid-Appliance Wiki
Contents |
Intorduction
Before staring this section, if you are not familiar with Brunet, you can refer to Brunet page first. This page shows a way to use rpc in the brunet without rpc handler. Instead, it uses reflection rpc hanlder which is already implemented in RpcManager class. Before going further, if you are not familiar with Reflection, I encourage you to read this page or this page.
Compiling and running
Compile using existing library
You can download library and source code here. You should compile "HwRpcHandlerUsingReflection.cs" with Brunet.dll and BrunetApp.dll files.
For example, you can type "gmcs -r:Brunet.dll,BrunetApp.dll HwRpcHandlerUsingReflection.cs" in the colsole. You can also use mono compiler other than "gmcs".
Compile using your own brunet source code
If you want to use your brunet source code, you should create a folder under Applications directory, and copy HwRpcHandlerUsingReflection.cs and default.build files to the directory.
For example, create folder "HelloWorld" under the Brunet-Application directory (i.e.,brunet/src/Brunet/Applications/HelloWorld/), and copy two files to (brunet/src/Brunet/Applications/HelloWorld/). Run "nant" in the directory, and new executable will reference your own brunet source code.
If you have compile problem, you can download new version of brunet soucre code here
Running the application
1. Run HwRpcHandlerUsingReflection.exe with input argument local.config (Linux: mono HelloWorldNodeDataHandler local.config, Windows: HelloWorldNodeDataHandler.exe local.config)
2. Run python command shell. Type command as follows.
>>> import sys,xmlrpclib >>> rpc=xmlrpclib.Server("http://127.0.0.1:10000/xm.rem") >>> print rpc.localproxy("HwRpc.Test",xmlrpclib.Binary("Hello World")) Hello World >>>
- Here, you should be careful for the local host port number(127.0.0.1:10000). The port number should be same as XmlRpcManager Port number element at the local.config file.
- HelloWorldRpcSHandler sends the first input argument back as a result for rpc call. Thus, You should insert at least one argument for the rpc call to get correct result.
3. You can see the result at the application console as well as the python command shell.
Source code description
In this section, you will see how reflection is used for rpc handler instead of IRpcHandler.
Reflection source code description
1. "AddHandler" method checks whether input handler implemented RpcHandler or not. If not, it register ReflectionRpc Hanler for the given name space. .(brunet/src/protocol/RpcManager.cs)
public class RpcManager : IReplyHandler, IDataHandler { public void AddHandler(string name_space, object handler){ IRpcHandler h = handler as IRpcHandler; if( h == null ) { h = new ReflectionRpcHandler(this, handler, false); } _method_handlers.Add(name_space, h); } }
2. This is the constructor of ReflectionRpcHandler. It saves the input handler's(rpc handling class) type in the _type field.(brunet/src/protocol/RpcManager.cs)
protected class ReflectionRpcHandler : IRpcHandler { public ReflectionRpcHandler(RpcManager rpc, object handler, bool use_sender) { _handler = handler; _type = _handler.GetType(); } }
3. If rpc with given name space, which was registered to reflection rpc handler, arrives, the call is processed at the ReflectionRpcHandler.HandleRpc() method. It gets the method of given method name using Type.GetMethod(). Then, invoke desired method using given parameters.
public void HandleRpc(ISender caller, string methname, IList arguments, object request_state) { MethodInfo mi = null; mi = _type.GetMethod(methname); arguments.CopyTo(arg_array, 0); result = mi.Invoke(_handler, arg_array); _rpc.SendResult(request_state, result); }
Hello World source code
1. As you can see here, HelloWorldRpcHandler class does not inherit IRpcHandler class. Thus, if rpc with name space "HwRpc" comes in, proper method is called through ReflectionRpcHandler. In this example, user command "HwRpc.Test", so Test() method is called through ReflectionRpcHandler. ()
public class HelloWorldRpcHandler : BasicNode{ public override void Run() { _node.Rpc.AddHandler("HwRpc", this); } public object Test(byte[] arg){ return arg; } }

