ROMP - The Ruby Object Message Proxy
(C) Copyright 2001 Paul Brannan (cout at rm-f.net)
ROMP is a set of classes for providing distributed object support to a
Ruby program. You may distribute and/or modify it under the same terms as
Ruby (see http://www.ruby-lang.org/en/LICENSE.txt). Example:
Client
------
client = ROMP::Client.new('localhost', 4242)
obj = client.resolve("foo")
puts obj.foo("foo")
obj.oneway(:foo, "foo")
Server
------
class Foo
def foo(x); return x; end
end
obj = Foo.new
server = ROMP::Server.new('localhost', 4242)
server.bind(obj, "foo")
server.thread.join
You can do all sorts of cool things with ROMP, including passing blocks to
the functions, throwing exceptions and propogating them from server to
client, and more. Unlike CORBA, where you must create an interface
definition and strictly adhere to it, ROMP uses marshalling, so you can
use almost any object with it. But, alas, it is not as powerful as CORBA.
On a fast machine, you should expect around 7000 messages per second with
normal method calls, up to 10000 messages per second with oneway calls with
sync, and up to 40000 messages per second for oneway calls without sync.
The ROMP message format is broken into 3 components:
[ msg_type, obj_id, message ]
For each msg_type, there is a specific format to the message. Additionally,
certain msg_types are only valid when being sent to the server, and others
are valid only when being sent back to the client. Here is a summary:
msg_type send to meaning of obj_id msg format
----------------------------------------------------------------------------
REQUEST server obj to talk to [:method, *args]
REQUEST_BLOCK server obj to talk to [:method, *args]
ONEWAY server obj to talk to [:method, *args]
ONEWAY_SYNC server obj to talk to [:method, *args]
RETVAL client always 0 retval
EXCEPTION client always 0 $!
YIELD client always 0 [value, value, ...]
SYNC either 0=request, 1=response nil
NULL_MSG either always 0 n/a
BUGS:
- On a 2.2 kernel, oneway calls without sync is very slow.
- UDP support does not currently work.
Author: Paul Brannan
Version: 0.1
module ROMP
class Server < Object
The ROMP server class. Like its drb equivalent, this class spawns off
a new thread which processes requests, allowing the server to do other
things while it is doing processing for a distributed object. This
means, though, that all objects used with ROMP must be thread-safe.
Methods
initialize(endpoint, acceptor=nil, debug=false)
endpoint | An endpoint for the server to listen on; should be specified in URI notation. |
acceptor | A proc object that can accept or reject connections; it should take a Socket as an argument and returns true or false. |
debug | Turns on debugging messages if enabled. |
Start a ROMP server.
create_reference(obj)
obj | The object to register. |
Returns: A new Object_Reference that should be returned to the client.
Register an object with the server. The object will be given an
id of @next_id, and @next_id will be incremented. We could use the
object's real id, but this is insecure. The supplied object must
be thread-safe.
delete_reference(obj)
obj | The object to unregister. |
Find an object in linear time and unregister it. Be careful with
this function, because the client may not know the object has
gone away.
bind(obj, name)
obj | The object to bind. |
name | The name of to bind the object to. |
Register an object with the server and bind it to name.
This keeps the client from seeing our objects when they call inspect
Methods
inspect()
server_loop(session)
session | The session to run the loop with. |
The server_loop function is the guts of the server. It takes in
requests from the client and forwards them to already-registered
objects.
class Client < Object
The ROMP client class. A ROMP server must be started on the given
host and port before instantiating a ROMP client.
Methods
initialize(endpoint, sync=true)
endpoint | The endpoint the server is listening on. |
sync | Specifies whether to synchronize between threads; turn this off to get a 20% performance boost. |
Connect to a ROMP server
resolve(object_name)
object_name | The name of the object to resolve. |
Returns: A Proxy_Object that can be used to make method calls on the object in the server.
Given a string, return a proxy object that will forward requests
for an object on the server with that name.
class Null_Mutex < Object
In case the user does not want synchronization.
Methods
synchronize
lock
unlock
class Functions < Object
All the special functions we have to keep track of
Constants
class Object_Reference < Object
A ROMP::Object_Reference is created on the server side to represent an
object in the system. It can be returned from a server object to a
client object, at which point it is converted into a ROMP::Proxy_Object.
Methods
initialize(object_id)
class Proxy_Object < Object
A ROMP::Object acts as a proxy; it forwards most methods to the server
for execution. When you make calls to a ROMP server, you will be
making the calls through a Proxy_Object.
Methods
method_missing(function, *args)
The method_missing function is called for any method that is not
defined on the client side. It will forward requests to the server
for processing, and can iterate through a block, raise an exception,
or return a value.
onweway(function, *args)
The oneway function is called to make a oneway call to the server
without synchronization.
oneway_sync(function, *args)
The oneway_sync function is called to make a oneway call to the
server with synchronization (the server will return a null message
to the client before it begins processing). This is slightly safer
than a normal oneway call, but it is slower (except on a linux 2.2
kernel; see the bug list above).
sync()
The sync function will synchronize with the server. It sends a sync
request and waits for a response.
#{method}(*args)
#{method}(*args)
#{method}(*args)
#{method}(arg, *args)
class Resolve_Server < Object
The Resolve_Server class registers objects for the server. You will
never have to use this class directly.
Methods
initialize
register(obj)
get_object(object_id)
unregister(obj)
bind(name, id)
resolve(name)
delete_obj_from_array_private(array, obj)
class Resolve_Obj < Object
The Resolve_Obj class handles resolve requests for the client. It is
a special ROMP object with an object id of 0. You will never have to
make calls on it directly, but will instead make calls on it through
the Client object.
Methods
initialize(resolve_server)
resolve(name)
class Generic_Server < Object
A Generic_Server creates an endpoint to listen on, waits for connections,
and accepts them when requested. It can operate on different kinds of
connections. You will never have to use this object directly.
Methods
initialize(endpoint)
accept
class Generic_Client < Object
A Generic_Client connects to a Generic_Server on a given endpoint.
You will never have to use this object directly.
Methods
self.new(endpoint)
self.print_exception(exc)
exc | The exception object to print. |
Print an exception to the screen. This is necessary, because Ruby does
not give us access to its error_print function from within Ruby.
class Session < Object
The Sesssion class is defined in romp_helper.so. You should never have
to use it directly.
Requires / Includes
socket
thread
fcntl
romp_helper