LuDO Support
LuDO stands for Lua Distributed Objects. It is an RMI technology specifically designed for use within the Lua language. Moreover, it is intended to be as simple as possible so its implementation can be easily comprehended by developers interested in development of support for other RMI technologies in OiL. Below, we describe the main characteristics of LuDO.
Configuration Options
LuDO brokers are typically created using one of the following flavors (for more information about flavors, see section Using Flavors):
ludo;base ludo;cooperative;base
LuDO accepts only two configuration options that defines the host and port where invocations must be send to, as described below.
host |
string | [optional] | Host name or IP address. If none is provided the ORB binds to all current net interfaces. |
port |
number | [optional] | Host port the ORB must listen. If none is provided, the ORB tries to bind to a port in the range [2809; 9999]. |
Below is an example that illustrates how to initiate a LuDO broker:
require "oil" oil.main(function() local broker = oil.init{ flavor = "ludo;cooperative;base", host = "myhostname", port = "8080", } ... broker:run() end)
Value Mapping
Similar to Lua, LuDO does not provide support for interfaces or method signatures. Instead, it relies on dynamic typing, and remote methods can be invoked with any number of parameters and can return any number of values. However, such values must be values serializable by method implemented by class loop.serial.Serializer, which includes Lua functions without upvalues shared with other functions. In particular, objects are transferred by copy and not by reference. Therefore, if you pass an object as parameter to a remote method, it will be copied to the remote context and all changes performed on the remote copy will not be reflected in the original object. To send objects by reference, you have to explicitly create a proxy for the object and send the proxy, which will be copied to the remote context. Such situation is illustrated in the code below.
Server
require "oil" oil.main(function() local broker = oil.init{flavor="ludo;cooperative;base"} local Invoker = {} function Invoker:invoke(object, method, ...) object[method](object, ...) end oil.writeto("invoker.ref", broker:tostring( broker:newservant(Invoker))) broker:run() end)
Client
require "oil" oil.main(function() local broker = oil.init{flavor="ludo;cooperative;base"} oil.newthread(broker.run, broker) local Hello = {} function Hello:say(who) print(string.format("Hello, %s!", tostring(who))) end local Invoker = broker:newproxy(oil.readfrom("invoker.ref")) -- object 'Hello' is copied to the remote context -- thus the message is printed on the remote host Invoker:invoke(Hello, "say", "World") -- create a proxy for a servant from object 'Hello' local proxy = broker:newproxy( broker:tostring( broker:newservant(Hello))) -- proxy to 'Hello' is copied to the remote context -- thus the message is printed locally Invoker:invoke(proxy, "say", "World") broker:shutdown() end)