What is ROBIN?
ROBIN is a freeware,
CORBA-2.1-based
ORB with additional support for:
Remote Procedure Calls defined in IDL
Load-balancing
Redundancy (virtual synchrony model)
ROBIN simplifies CORBA, using an architecture like this:
Object Adapters and the DSI are not supported,
because they are not needed.
Instead, ROBIN implements a dynamic server-side ORB
which invokes static skeletons directly.
These are true skeletons;
the user simply adds code in the marked places to complete them.
ROBIN's CORBA Simplifications
Notice that CORBA says nothing about constructors,
generally requiring the "4-step program":
On the server, obtain a reference for the desired object:
ref = CORBA::BOA::create(..)
"Stringify" it:
str = CORBA::ORB::object_to_string(ref)
Somehow copy the string to the client
The client then uses:
obj = CORBA::ORB::string_to_object(str)
Difficult, error-prone, and NOT scalable!
Why not just use constructors?
ROBIN defines constructors, on both client and service side:
More familiar to programmers - more transparency
"default" constructors only (no user-defined arguments)
Client stub's constructors hide all CORBA calls
[CORBA::ORB::init() and CORBA::ORB::resolve_initial_references()]
This does NOT limit flexibility -
"construction" of a CORBA object
does not imply that a new instance of the REAL object must be created
each time (the CORBA object could be a "front end" to a controlled
set of real objects).
ROBIN Client-side Constructors
C:
CORBA_Object <module>_<interface>__alloc(
int *argc, char **argv, CORBA_ORBid orb_id,
CORBA_Environment *ev );
argc/argv: passed to CORBA::ORB::init() - notice argc is
pointer (ORB removes ORB-specific arguments and "compresses" argv)
orb_id: a string specifying the ORB ID (more on this later)
ev: the CORBA_Environment * for catching exceptions in C
"ROBIN" C++:
<module>_<interface>( int *argc, char **argv,
CORBA_ORBid orb_id, CORBA_Environment *ev );
Unofficial Java Mapping:
public <interface>( String args[], String orb_id ) throws
omg.corba.CORBAException;
args: string array of command-line arguments
orb_id: a string specifying the ORB ID (more on this later)
Official Java Mapping:
public <interface>Client( String args[] )
throws org.omg.CORBA.ORBPackage.InvalidName;
public <interface>Client( String args[],
java.util.Properties props )
throws org.omg.CORBA.ORBPackage.InvalidName;
public <interface>Client( String args[], String orb_id )
throws org.omg.CORBA.ORBPackage.InvalidName;
ROBIN Server-side Constructors
C:
void *<module>_<interface>__alloc();
ROBIN's IDL compiler generates code
to malloc() space for the interface's attributes and some internal data.
Implementor can add further "construction" code.
The returned pointer serves as the "registration" mechanism;
returning anything other than NULL registers the object.
Implementations must be linked as shared libraries
(DSOs on UNIX; DLLs on Windows) and use specific filenames.
This allows the ROBIN server to automatically activate them.
ROBIN ORB IDs
Another thing left "wide open" in the CORBA spec is the
definition of ORB ID:
it is a string specifying what ORB to use.
ROBIN is a bit more precise - an ORB ID specifies:
a specific server (name or IP address - can be "localhost"); OR
a multicast group (name or IP address).
It can also have special tags for:
IP port number to match server's (both default to 50038)
connection timeout (defaults to 30 secs)
how many "ROBIN groups" to use (redundancy - more on this later)
ROBIN's Load Balancing
ROBIN's interpretation of ORB IDs allows support for
rudimentary load-balancing.
When constructing a new object with a multicast group as the ORB ID:
A request-for-service packet is sent on the multicast address
The object will be constructed on the first server to respond
All other response packets for the request are dropped
ROBIN's Redundancy
Building on part of the load-balancing mechanism,
ROBIN also supports redundancy.
Each server which registers in a multicast group can be given
a "ROBIN group number" from 1 to 4.
When constructing a new object with a multicast group as the ORB ID
and using 2 ROBIN groups:
A request-for-service packet is sent on the multicast address;
its "# groups" field has 2
The object will be constructed on the first "group 1"
server AND the first "group 2" server to respond
All other response packets for the request are dropped
The client sends all requests to both servers;
if one server dies,
it is marked "bad" and no further requests are sent to it
ROBIN Features
ROBIN 2.3's other features include:
Development of services in C
Development of clients in C, C++ or Java
the CORBA Interface Definition Language (IDL)
+ extension for remote procedure calls
the CORBA Dynamic Invocation Interface (DII)
an almost-fully-compliant ORB
(no structs, unions, contexts or exceptions)
most of the ORB Interface
the CORBA C mapping, but with simpler sequences
a simpler C++ mapping with real classes,
C-style argument passing, no namespaces or C++ exceptions
the unofficial Java mapping + my own inventions
(there was no official mapping at the time...)
"unshared server" activation policy
"trivial" authentication (clients hosts "on the list" allowed in)
ROBIN 2.4 (due any day now...) adds:
the official C mapping (CORBA sequences)
the official Java mapping
struct and exception support
the CORBA Interface Repository Interface
automatic support for "singletons"
GUI-based server configuration and launching
The Road ahead...
ROBIN 2.5 plans:
Official C++ mapping
Services in C++, Java
IIOP (official protocol for ORBs to interoperate)
Finer-grained authentication (at the user level)
and access control (at the object level)
There are NO plans for:
CORBA contexts - luxury item
"server-per-method" activation policy
Example C Client
main( argc, argv )
int argc;
char **argv;
{
int our_argc;
char server[64];
CORBA_Object ourADMEM;
CORBA_Environment env;
long status;
long constants[8192];
.
.
/* get a copy of argc so we can pass its address */
our_argc = argc;
.
/* hard-wire the server to use */
strcpy( server, "b0sgh.fnal.gov" );
.
/* construct the object */
ourADMEM = CDFonline_ADMEM__alloc( &our_argc, argv, server, &env );
.
/* set detector to COT */
CDFonline_ADMEM__set_DetectorSubsystem( ourADMEM, "COT" );
.
.
/* do our stuff */
status = CDFonline_ADMEM_Initialize( ourADMEM, 1, &env );
status = CDFonline_ADMEM_Calibrate( ourADMEM, constants, &env );
.
.
/* destroy the object */
CDFonline_ADMEM__free( ourADMEM, &env );
}
Example C++ Client
main( argc, argv )
int argc;
char **argv;
{
int our_argc;
char server[64];
CDFonline_ADMEM *ourADMEM;
CORBA_Environment env;
long status;
long constants[8192];
.
.
// get a copy of argc so we can pass its address
our_argc = argc;
.
// hard-wire server to use
strcpy( server, "b0sgh.fnal.gov" );
.
// construct object
ourADMEM = new CDFonline_ADMEM( &our_argc, argv, server, &env );
.
// set detector to COT
ourADMEM->DetectorSubsystem( "COT" );
.
.
// do our stuff
status = ourADMEM->Initialize( 1 );
status = ourADMEM->Calibrate( constants );
.
.
// destroy object
delete ourADMEM;
}
Example Java Client
import omg.corba.*;
import CDFonline.*;
public class CORBAtest {
.
.
public void main( String args[] ) {
CDFonline.ADMEM ourADMEM;
int status;
int constants[8192];
.
.
// hard-wire server to use
String server = "b0sgh.fnal.gov";
.
try {
// construct object
ourADMEM = new CDFonline.ADMEM( args, server );
.
// set detector to COT
ourADMEM.DetectorSubsystem( "COT" );
.
.
// do our stuff
status = ourADMEM.Initialize( 1 );
status = ourADMEM.Calibrate( constants );
.
} catch( omg.corba.CORBAException exc ) {
System.out.println( "Something went wrong!" );
}
}
}