Chapter 6 The omniORB API
In this chapter, we introduce the omniORB API. The purpose of this API
is to provide access points to omniORB specific functionality that is
not covered by the CORBA specification. Obviously, if you use this
API in your application, that part of your code is not going to be
portable to run unchanged on other vendors' ORBs. To make it easier to
identify omniORB dependent code, this API is defined under the name
space `omniORB'1.
6.1 ORB initialisation options
CORBA::ORB_init() accepts the following standard command-line
arguments:
|
-ORBid omniORB3 |
The identifier must be `omniORB3'. |
-ORBInitRef <ObjectId>=<ObjectURI> |
See section 4.2. |
-ORBDefaultInitRef <Default URI> |
See section 4.2.
|
and the following omniORB-specific arguments:
|
-ORBtraceLevel <level> |
See section 6.3. |
-ORBtraceInvocations |
See section 6.3. |
-ORBstrictIIOP |
See section 6.9. |
-ORBtcAliasExpand <0 or 1> |
See section 9.2. |
-ORBgiopMaxMsgSize <size in bytes> |
See section 6.5. |
-ORBobjectTableSize <number of entries> |
See section 6.6. |
-ORBserverName <string> |
See section 6.4. |
-ORBno_bootstrap_agent |
See section 6.8. |
-ORBdiiThrowsSysExceptions <0 or 1> |
See section 11.4. |
-ORBabortOnInternalError <0 or 1> |
See section 6.11. |
-ORBverifyObjectExistsAndType <0 or 1> |
See section 6.9. |
-ORBinConScanPeriod <0--max integer> |
See section 8.3. |
-ORBoutConScanPeriod <0--max integer> |
See section 8.3. |
-ORBclientCallTimeOutPeriod <0--max integer> |
See section 8.3. |
-ORBserverCallTimeOutPeriod <0--max integer> |
See section 8.3. |
-ORBscanGranularity <0--max integer> |
See section 8.3. |
-ORBlcdMode |
See section 6.9. |
-ORBpoa_iiop_port <port no.> |
See section 6.2. |
-ORBpoa_iiop_name_port <hostname[:port no.]> |
See section 6.2. |
-ORBhelp |
Lists all ORB command line options. |
and these two obsolete omniORB-specific arguments:
|
-ORBInitialHost <string> |
See section 6.8. |
-ORBInitialPort <1--65535>] |
See section 6.8. |
As defined in the CORBA specification, any command-line
arguments understood by the ORB will be removed from argv when
the initialisation functions return. Therefore, an application is not
required to handle any command-line arguments it does not understand.
6.2 Hostname and port
Normally, omniORB lets the operating system pick which port number it
should use to listen for IIOP calls. Alternatively, you can specify a
particular port using -ORBpoa_iiop_port. If you specify
-ORBpoa_iiop_port more than once, omniORB will listen on
all the ports you specify.
By default, the ORB can work out the IP address of the host machine.
This address is recorded in the object references of the local
objects. However, when the host has multiple network interfaces and
multiple IP addresses, it may be desirable for the application to
control what address the ORB should use. This can be done by defining
the environment variable OMNIORB_USEHOSTNAME to contain the
preferred host name or IP address in dot-numeric form. Alternatively,
the same can be achieved using the -ORBpoa_iiop_name_port
option. You can optionally specify a port number too. Again, you can
specify more than one host name by using
-ORBpoa_iiop_name_port more than once.
6.3 Run-time Tracing and Diagnostic Messages
omniORB can output tracing and diagnostic messages to the standard
error stream. To avoid conflicts between old-style iostream.h
and new-style iostream, omniORB uses neither. Some or all of
these messages can be turned on/off by setting the variable
omniORB::traceLevel. The type definition of the variable is:
CORBA::ULong omniORB::traceLevel = 1; // The default value is 1
At the moment, the following trace levels are defined:
|
level 0 |
turn off all tracing and informational messages |
level 1 |
informational messages only |
level 2 |
the above plus configuration information |
level 5 |
the above plus notifications when server threads are
created or communication endpoints are shutdown |
level 10--20 |
the above plus execution and exception traces |
level 25 |
the above plus hex dumps of all data sent and received
by the ORB via its network connections. |
The variable can be changed by assignment inside your
applications. It can also be changed by specifying the command-line
option: -ORBtraceLevel <level>. For instance:
$ eg2_impl -ORBtraceLevel 5
New in omniORB 3, you can also trace operation invocations by setting
omniORB::traceInvocations to true, or with the
-ORBtraceInvocations command line argument.
6.4 Server Name
Applications can optionally specify a name to identify the server
process. At the moment, this name is only used by the host-based
access control module. See section 8.5 for details. The
name is stored in the variable omniORB::serverName.
CORBA::String_var omniORB::serverName;
The variable can be changed by assignment inside your
applications. It can also be changed by specifying the command-line
option: -ORBserverName <string>.
6.5 GIOP Message Size
omniORB sets a limit on the GIOP message size that can be sent or
received. The value can be obtained by calling:
size_t omniORB::MaxMessageSize();
and can be changed by:
void omniORB::MaxMessageSize(size_t newvalue);
or by the command-line option -ORBgiopMaxMsgSize.
The exact value is somewhat arbitrary. The reason such a limit exists
is to provide some way to protect the server side from resource
exhaustion. Think about the case when the server receives a rogue
GIOP(IIOP) request message that contains a sequence length field set
to 231. With a reasonable message size limit, the server can
reject this rogue message straight away.
6.6 Object table size
omniORB uses a hash table to store the mapping from object keys to
servant objects. Normally, it dynamically re-sizes the hash table when
it becomes too full or too empty. This is the most efficient trade-off
between performance and memory usage. However, since all POA
operations which add or remove objects from the table can (very
occasionally) cause the object table to resize, the time spent in POA
operations is much less predictable than if the table size was fixed.
To prevent omniORB from resizing its object table, set the variable
omniORB::objectTableSize to the number of hash table
entries you require before calling CORBA::ORB_init().
Alternatively, use the -ORBobjectTableSize argument. Note
that omniORB uses an open hash table so you can have any number of
objects active, no matter what size table you specify. If you have
many more active objects than hash table entries, object look-up
performance will become linear with the number of objects.
6.7 POA request holding timeout
POAs can be put into the holding state, which means that
incoming requests are queued until the POA is set to a different
state. Normally, queued requests are held for ever (or until the
client times out as described in section 8.3). If you set
omniORB::poaHoldRequestTimeout to a non-zero time in seconds,
held requests will be cancelled after that time. When requests are
cancelled in this way, the caller is sent a TRANSIENT
exception.
6.8 Obsolete Initial Object Reference Bootstrapping
Starting from 2.6.0, but superseded by the Interoperable Naming
Service in omniORB 3, a mechanism is available for the ORB runtime to
obtain the initial object references to CORBA services. The bootstrap
service is a special object with the object key `INIT' and the
following interface2:
// IDL
module CORBA {
interface InitialReferences {
Object get(in ORB::ObjectId id);
// returns the initial object reference of the service
// identified by <id>. For example the id for the
// Naming service is "NameService".
ORB::ObjectIdList list();
// returns the list of service ids that this agent knows
};
};
By default, all omniORB servers contain an instance of this object and
are able to respond to remote invocations. To prevent the ORB from
instantiating this object, the command-line option
-ORBno_bootstrap_agent should be specified.
In particular, the Naming Service omniNames is able to respond to a
query through this interface and return the object reference of its
root context. In effect, the bootstrap agent provides a level of
indirection. All omniORB clients still have to be supplied with the
address of the bootstrap agent. However, the information is much
easier to specify than a stringified IOR! Another advantage of this
approach is that it is completely compatible with JavaIDL. This makes
it possible for programs written for JavaIDL to share a Naming
Service with omniORB.
The address of the bootstrap agent is given by the
ORBInitialHost and ORBInitialPort parameter in the
omniORB configuration file (section 1.2). The parameters can
also be specified as command-line options
(section 6.1). The parameter
ORBInitialPort is optional. If it is not specified, port
number 900 will be used.
During initialisation, the ORB reads the parameters in the omniORB
configuration file. If the parameter NAMESERVICE is
specified, the stringified IOR is used as the object reference of the
root naming context. If the parameter is absent and the parameter
ORBInitialHost is present, the ORB contacts the bootstrap
agent at the address specified to obtain the root naming context when
the application calls resolve_initial_references(). If neither is
present, resolve_initial_references() returns a nil object
reference. Finally, the command line argument
-ORBInitialHost overrides any parameters in the
configuration file. The ORB always contacts the bootstrap agent at the
address specified to obtain the root naming context.
Now we are ready to describe a simple way to set up omniNames.
-
Start omniNames for the first time on a machine (e.g. wobble):
$ omniNames -start 1234
- Add to omniORB.cfg:
ORBInitialHost wobble
ORBInitialPort 1234
- All omniORB applications will now be able to contact omniNames.
Alternatively, the command line options can be used, for example:
$ eg3_impl -ORBInitialHost wobble -ORBInitialPort 1234 &
$ eg3_clt -ORBInitialHost wobble -ORBInitialPort 1234
6.9 GIOP Lowest Common Denominator Mode
Sometimes, to cope with bugs in another ORB, it is necessary to
disable various GIOP and IIOP features in order to achieve
interoperability. If the command line option -ORBlcdMode is
present or the function omniORB::enableLcdMode() is called, the ORB
enters the so-called `lowest common denominator mode'. It bends over
backwards to cope with bugs in the ORB at the other end. This is
purely a transitional measure. The long term solution is to report the
bugs to the other vendors and ask them to fix them expediently.
In some (sloppy) IIOP implementations, the message size value in the
IIOP header can be larger than the actual body size, i.e. there is
garbage at the end. As the spec does not say the message size must
match the body size exactly, this is not a clear violation of the
spec. omniORB's default policy is to expect incoming messages to be
formatted properly. Any messages that have garbage at the end will be
rejected.
-ORBlcdMode and omniORB::enableLcdMode() set omniORB to
silently skip the unread part of such invalid messages. Alternatively,
you can just change this policy with the -ORBstrictIIOP 0
command line, or by setting omniORB::strictIIOP to zero.
The problem with doing this is that the header message size may
actually be garbage, caused by a bug in the sender's code. The
receiving thread may block forever as it tries to read more data from
the connection. In this case the sender won't send any more as it
thinks it has marshalled in all the data.
By default, omniORB uses the GIOP LOCATE_REQUEST message to verify
the existence of an object prior to the first invocation. If another
vendor's ORB is known not to be able to handle this GIOP message, set
the variable omniORB::verifyObjectExistsAndType to 0 to
disable this feature, and hence achieve interoperability. The command
line option -ORBverifyObjectExistsAndType has the same
effect.
6.10 GIOP Requesting Principal field
In versions 1.0 and 1.1 of the GIOP specification, request messages
contain a `principal' field which was intended to identify the client.
The meaning of the principal field was never specified, and its use is
now deprecated. The field is not present in GIOP 1.2. omniORB normally
uses the string `nobody' in the principal field. However,
some systems (e.g. the GNOME desktop environment) use the principal
field as an authentication mechanism, so omniORB allows you to
configure the principal by setting the OMNIORB_PRINCIPAL
environment variable.
6.11 Trapping omniORB Internal Errors
class fatalException {
public:
const char *file() const;
int line() const;
const char *errmsg() const;
};
When omniORB detects an internal problem that is most likely to be
caused by a bug in the runtime, it raises the exception
omniORB::fatalException. When this exception is raised, it is
not sensible to proceed with any operation that involves the ORB's
runtime. It is best to exit the program immediately. The exception
structure carried by omniORB::fatalException contains the exact
location (the file name and the line number) where the exception is
raised. You are strongly encouraged to file a bug report and point out
the location.
It may help to cause a core-dump and look at the stack trace to locate
where the exception was thrown. This can be done by setting the
variable omniORB::abortOnInternalError to 1. The variable
can also be set via the command line option
-ORBabortOnInternalError.
6.12 System Exception Handlers
By default, all system exceptions which are raised during an operation
invocation, with the exception of CORBA::TRANSIENT, are
propagated to the application code. Some applications may prefer to
trap these exceptions within the proxy objects so that the application
logic does not have to deal with the error condition. For example,
when a CORBA::COMM_FAILURE is received, an application may
just want to retry the invocation until it finally succeeds. This
approach is useful for objects that are persistent and their
operations are idempotent.
omniORB provides a set of functions to install exception handlers.
Once they are installed, proxy objects will call these handlers when
the associated system exceptions are raised by the ORB runtime.
Handlers can be installed for CORBA::TRANSIENT,
CORBA::COMM_FAILURE and CORBA::SystemException. This
last handler covers all system exceptions other than the two covered
by the first two handlers. An exception handler can be installed for
individual proxy objects, or it can be installed for all proxy objects
in the address space.
6.12.1 CORBA::TRANSIENT handlers
When a CORBA::TRANSIENT exception is raised by the ORB runtime,
the default behaviour of the proxy objects is to retry indefinitely
until the operation succeeds. Successive retries will be delayed
progressively by multiples of
omniORB::defaultTransientRetryDelayIncrement. The delay
will be limited to the maximum specified by
omniORB::defaultTransientRetryDelayMaximum. The unit of both
values are in seconds.
The ORB runtime will raise CORBA::TRANSIENT under the following
conditions:
- When a cached network connection is broken while an
operation invocation is in progress. The ORB will try to open a new
connection at the next invocation.
- When the proxy object has been redirected by a location forward
message by the remote object to a new location and the object at the
new location cannot be contacted. In addition to the
CORBA::TRANSIENT exception, the proxy object also resets its
internal state so that the next invocation will be directed at the
original location of the remote object.
- When the remote object reports CORBA::TRANSIENT.
Applications can override the default behaviour by installing their
own exception handler. The API to do so is summarised below:
class omniORB {
public:
typedef CORBA::Boolean (*transientExceptionHandler_t)(void* cookie,
CORBA::ULong n_retries,
const CORBA::TRANSIENT& ex);
static void installTransientExceptionHandler(void* cookie,
transientExceptionHandler_t fn);
static void installTransientExceptionHandler(CORBA::Object_ptr obj,
void* cookie,
transientExceptionHandler_t fn);
static CORBA::ULong defaultTransientRetryDelayIncrement;
static CORBA::ULong defaultTransientRetryDelayMaximum;
}
The overloaded function installTransientExceptionHandler() can be
used to install the exception handlers for CORBA::TRANSIENT.
Two forms are available: the first form installs an exception handler
for all object references except for those which have an exception
handler installed by the second form, which takes an additional
argument to identify the target object reference. The argument
cookie is an opaque pointer which will be passed on by the ORB
when it calls the exception handler.
An exception handler will be called by proxy objects with three
arguments. The cookie is the opaque pointer registered by
installTransientExceptionHandler(). The argument n_retries
is the number of times the proxy has called this handler for the same
invocation. The argument ex is the value of the exception
caught. The exception handler is expected to do whatever is
appropriate and returns a boolean value. If the return value is
TRUE(1), the proxy object retries the operation. If the return value
is FALSE(0), the CORBA::TRANSIENT exception is propagated into
the application code.
The following sample code installs a simple exception handler for all
objects and for a specific object:
CORBA::Boolean my_transient_handler1 (void* cookie,
CORBA::ULong retries,
const CORBA::TRANSIENT& ex)
{
cerr << "transient handler 1 called." << endl;
return 1; // retry immediately.
}
CORBA::Boolean my_transient_handler2 (void* cookie,
CORBA::ULong retries,
const CORBA::TRANSIENT& ex)
{
cerr << "transient handler 2 called." << endl;
return 1; // retry immediately.
}
static Echo_ptr myobj;
void installhandlers()
{
omniORB::installTransientExceptionHandler(0,my_transient_handler1);
// All proxy objects will call my_transient_handler1 from now on.
omniORB::installTransientExceptionHandler(myobj,0,my_transient_handler2);
// The proxy object of myobj will call my_transient_handler2 from now on.
}
6.12.2 CORBA::COMM_FAILURE
When the ORB runtime fails to establish a network connection to the
remote object and none of the conditions listed above for raising a
CORBA::TRANSIENT is applicable, it raises a
CORBA::COMM_FAILURE exception.
The default behaviour of the proxy objects is to propagate this
exception to the application. Applications can override the default
behaviour by installing their own exception handlers. The API to do so
is summarised below:
class omniORB {
public:
typedef CORBA::Boolean (*commFailureExceptionHandler_t)(void* cookie,
CORBA::ULong n_retries,
const CORBA::COMM_FAILURE& ex);
static void installCommFailureExceptionHandler(void* cookie,
commFailureExceptionHandler_t fn);
static void installCommFailureExceptionHandler(CORBA::Object_ptr obj,
void* cookie,
commFailureExceptionHandler_t
fn);
}
The functions are equivalent to their counterparts for
CORBA::TRANSIENT.
6.12.3 CORBA::SystemException
To report an error condition, the ORB runtime may raise other system
exceptions. If the exception is neither CORBA::TRANISENT nor
CORBA::COMM_FAILURE, the default behaviour of the proxy
objects is to propagate this exception to the application.
Applications can override the default behaviour by installing their
own exception handlers. The API to do so is summarised below:
class omniORB {
public:
typedef CORBA::Boolean (*systemExceptionHandler_t)(void* cookie,
CORBA::ULong n_retries,
const CORBA::SystemException& ex);
static void installSystemExceptionHandler(void* cookie,
systemExceptionHandler_t fn);
static void installSystemExceptionHandler(CORBA::Object_ptr obj,
void* cookie,
systemExceptionHandler_t fn);
}
The functions are equivalent to their counterparts for
CORBA::TRANSIENT.
6.13 Location forwarding
Any CORBA operation invocation can return a LOCATION_FORWARD
message to the caller, indicating that it should retry the invocation
on a new object reference. The standard allows ServantManagers to
trigger LOCATION_FORWARDs by raising the
PortableServer::ForwardRequest exception, but it does not
provide a similar mechanism for normal servants. omniORB provides the
omniORB::LOCATION_FORWARD exception for this purpose. It can
be thrown by any operation implementation.
class LOCATION_FORWARD {
public:
LOCATION_FORWARD(CORBA::Object_ptr objref);
};
The exception object consumes the object reference it is
passed.
- 1
- omniORB is a class name if the
C++ compiler does not support the namespace keyword.
- 2
- This interface was first defined by Sun's
NEO and is in used in Sun's JavaIDL.