TableOfContents

omniORB4.0

omniORB 4.0 is the current major release. This page started out as documentation of what was available when 4.0 was the development release, but it still contains some useful information.

Snapshots of updates since the last release are available at http://omniorb.sourceforge.net/snapshots .

Platforms Tested

Tested by us

  1. Redhat 6.2 (egcs-1.1.2, glibc-2.1)
  2. Windows 2000 (MSVC++ 6.0)
  3. Solaris 2.7 (Forte C++ 6.0)
  4. Solaris 2.6 (Sun C++ 4.2) (compile OK)

Tested by others

  1. Solaris 2.6 (GCC 2.95.3)
  2. Solaris 2.6 (GCC 3.2.2)
  3. Solaris 8 (GCC 3.2.2)
  4. Debian Sid (GCC 3.2.2)
  5. FreeBSD 4.5/4.6 (GCC 2.95.3)
  6. FreeBSD 5.0/5.1 (GCC 3.2.1)

If you use any other platforms, some minor changes may be needed to make the source compile. Please report these changes to be added to the source tree.

Known bugs and limitations

None at the moment!

Implemented New Features

ORB Configuration Parameters

In pre-omniORB4 versions, the ORB configurable parameters are accessed via the ORB_init argv arguments or the variables and functions in the omniORB:: namespace. This ad-hoc mechanism is now replaced with a more systematic approach.

When ORB_init is called, the ORB will initialise its configurable parameters from a number of sources.

On Unix platforms, the sources are read in this order:

1. The configuration file (omniORB.cfg). This file has a new format. The file <top>/sample.cfg contains all the available parameters and the explanations of their usage. You could copy sample.cfg, change the copied file to the setting you want, then set the environment variable OMNIORB_CONFIG to be the pathname of the file. This will instruct the ORB to read the configuration file in ORB_init.

2. From the environment variable. For instance,

     export ORBlcdMode=1
   or
     export ORBstrictIIOP=1

This is equivalent to setting lcdMode = 1 and strictIIOP = 1 in the configuration file.

3. An optional parameter list can be passed to ORB_init(). In your application code, when you call ORB_init, you can pass an optional argument containing the parameter strings. E.g.

           const char* options[][2] = { { "lcdMode", "1" }, { 0, 0 } };
           CORBA::ORB_init(argc,argv,"omniORB4",options);

4. From the command line. If your application passes argv to ORB_init, you can

       ./application -ORBlcdMode 1

One of the new configuration options is dumpConfiguration. If you do something like this:

    ./application -ORBdumpConfiguration 1

The ORB will dump the full settings when it starts up.

On Win32, the ORB behaves in the same way as on Unices except in step 1). The difference is as follows:

If the environment variable OMNIORB_CONFIG is set, the ORB will read the configuration file specified in the variable.

If the environment variable is not set, the ORB will read the registry key [HKEY_LOCAL_MACHINE\SOFTWARE\ATT\omniORB] for the settings. The file <top>/sample.reg is provided to make it easy to populate and change the registry entries. Just modify the content and execute the command:

  regedit sample.reg

Notice that regedit only adds or modifies the registry entries, it does not remove the values that are not present in sample.reg. To remove the values one has to use the GUI of regedt32 (or regedit).

Backward Compatibility

To maintain backward compatibility, the ORB will read the old format configuration file. It will also read the old win32 registry entries if the new registry key is not present.

Configuration parameters

Here is the list of configurable parameters and the explanations of their usage: SampleCfg.

GIOP version 1.1 and 1.2

By default, the ORB supports GIOP version 1.2, 1.1 and 1.0. Earlier versions, e.g. omniORB 3.0, supports only GIOP 1.0. The new ORB can interoperate with all previous versions of omniORB. For new features, such as wchar and wstring, the ORB must use GIOP 1.2 or above.

The maximum GIOP protocol the ORB should support can be specified by the ORB initialisation option:

-ORBmaxGIOPVersion <major no>.<minor no.>

e.g. to support only GIOP 1.0, -ORBmaxGIOPVersion 1.0

GIOP 1.2 allows a request to be split into multiple fragments and the fragments from multiple calls can be interleaved. This opens a possibility of abuse in that an ill-behaved client could send out a lot of the beginning call fragments but never send the end bits of the calls. An unsuspecting server may allocate resources to handle each of these calls until all the resources are consumed. To protect the server from this expliotation, the ORB sets a limit on how many of these incomplete and interleaved calls can be outstanding. If the limit is exceeded, the ORB closes the connection. This limit is contolled by configuration variable maxInterleavedCallsPerConnection and the ORB initialisation equivalent is:

-ORBmaxInterleavedCallsPerConnection <n requests>

wchar, wstring and codeset support

wchar and wstring are fully supported. Moreoever, automatic codeset conversion is fully supported. By default, the ORB uses ISO-8859-1 and UTF-16 as the native codeset for char and wchar respectively. This can be changed with the configuration variables nativeCharCodeSet and nativeWCharCodeSet, or use the ORB initialisation options:

-ORBnativeCharCodeSet <code set>
-ORBnativeWCharCodeSet <code set>

Where <code set> is a code set name. The names available are printed out at start-up if you use ORB trace level 15 or greater.

Extra code sets can be made available by linking with the omniCodeSets library. If you dynamically link the library, it initialises itself automatically; with static linking, you must #include <omniORB4/optionalFeatures.h>. See the comments in that file for information about other optional features.

long long support

Long long is fully suppported if the platform compiler can support 64-bit integer.

Fixed support

The IDL type Fixed is fully supported.

PortableServer::Current

POACurrent is fully supported. This feature is missing in omniORB 3's POA support. The implementation is correct even in a nested call chain where all servants are in the same address space.

Current support adds some overhead to each call. You can turn it off by the ORB option:

-ORBsupportCurrent 0

Proper ServantLocator semantics

The POA specification says that if a ServantLocator's postinvoke() function throws a CORBA system exception, the exception should be propagated to the caller instead of the result of the operation invocation. omniORB 3 does not support this -- it ignores any exceptions thrown from postinvoke(). omniORB 4 supports the proper semantics.

Optimised Same Address Space Call to Default Servant

Clients calling a default servant or servant locator in the same address space no longer go through the tcp loopback interface. This results in an order of magnitude improvement in performance.

Multiple alternative IIOP addresses

A new way to specify <hostname>:<port number> to the ORB:

 -ORBendPoint <endpoint uri>
 -ORBendPointNoPublish <endpoint uri>
 -ORBendPointNoListen <endpoint uri>
         <endpoint uri> = "giop:tcp:<host>:<port>" |
                         *"giop:ssl:<host>:<port>" |
                         *"giop:unix:<filename>"   |
                         *"giop:fd:<no.>"          |
                         *"<other protocol>:<network protocol>:<options>"
                         * may not be supported on the platform.

-ORBendPoint tells the ORB to listen on the endpoint and publish it in its IORs. The transport type is specified by the first 2 fields, e.g. giop:tcp selects IIOP, giop:ssl selects GIOP over ssl.

-ORBendPointNoPublish tells the ORB to listen on the endpoint but do not publish the endpoint in its IORs.

-ORBendPointNoListen tells the ORB to publish the endpoint in its IORs but do not listen on it. This option can be used to specify another host port combination so that the client can try the endpoint if others fail.

Multiple IIOP endpoints are encoded in the TAG_ALTERNATE_IIOP_ADDRESS components of the IORs.

SSL endpoints are encoded in the TAG_SSL_SEC_TRANS component.

SSL transport

SSL transport over OpenSSL 0.9.6a is now supported. By default it is not built.

The ssl transport is built only if the make variable OPEN_SSL_ROOT is defined and points to the root directory of the openssl library.

For example, on linux with glibc2.1, the platform file i586_linux_2.0_glibc2.1.mk contains these lines at the end of the file:

# To build the SSL transport, OPEN_SSL_ROOT must be defined and points
# the top level directory of the openssl library.
#
#OPEN_SSL_ROOT = /usr/local/openssl
#
OPEN_SSL_CPPFLAGS = -I$(OPEN_SSL_ROOT)/include
OPEN_SSL_LIB = -L$(OPEN_SSL_ROOT)/lib -lssl -lcrypto
OMNIORB_SSL_LIB += $(OPEN_SSL_LIB)
OMNIORB_SSL_CPPFLAGS += $(OPEN_SSL_CPPFLAGS)

If you have openssl installed in /usr/local/openssl, just uncomment the line and build the whole distribution. (In fact, you can just go into <top>/src/lib/omniORB/orbcore/ssl and do a gmake export.)

If you are using another platform, just copy the lines above into your platform file, e.g. for Solaris 2.5, copy the lines into <top>/mk/platform/sun4_sosV_5.5.mk.

The example <top>/src/examples/ssl_echo/ illustrates how to tell the ORB to use the ssl transport. Read the README file in the directory for details.

Dealing with multiplexed calls on the same connection

On the server side, previous omniORB versions only dispatch 1 upcall per connection at any time. This normally isn't a problem except in the following scenerio:

Client A calls server B. As part of the call in B, B calls A. As part of the call in A, A calls B again. In this nested call, if the client side ORB is omniORB it is fine. If however the client ORB is not omniORB and the ORB multiplexes all its calls from A to B on the same connection irrespective of whether this is part of a nested call or not, a deadlock occurs.

omniORB4 now deals with this situation properly. If a server upcall does not return in a pre-defined period of time, the connection is put under watch and if another request arrives, a new thread is dispatched to handle this request. The delay in putting the connection under watch is currently set to 50 to 100ms. This parameter will be tunable in future. If an upcall takes less time to finish than this delay, the watch mechanism does not kick in. The delay also provides a throttle to prevent calls from a connection to consume excessive server resources.

There is a limit on how many server threads the ORB will dispatch for a connection through this mechanism. Again this is a protection of the ORB resources. The limit is set by the configuration variable maxServerThreadPerConnection. It can also be changed using the ORB initialisation option:

-ORBmaxServerThreadPerConnection <n threads>.

Multiplex calls onto the same connection

On the client side, previous omniORB versions only use a connection to carry 1 call at any time. If another call is in progress to the same server at the same time, another connection will be opened automatically to carry the call.

While this is the most efficent policy, it is not appropriate in certain situations. For example, if the connection is used to carry bi-directional calls (GIOP BiDir) through a firewall, it makes more sense to use the connection to carry multiple calls simultaneously. OmniORB4 continues to use the same policy as previous versions but also provide the option to switch to call multiplexing if necessary.

The configuration variable oneCallPerConnection is a boolean which controls the ORB behaviour. If the value is TRUE(1), which is the default, omniORB4 behaves in the same way as previous versions. Otherwise, it multiplexes calls onto the same connection if necessary. The option can also be changed using the ORB initialisation option:

-ORBoneCallPerConnection <0|1>.

A related configuration variable is maxGIOPConnectionPerServer. This controls the maximum no. of connections the ORB will open to talk to a server.

For example, if one wants to have only 1 connection to carry all the calls to a server, the following ORB initialisation options are appropriate:

-ORBoneCallPerConnection 1 -ORBmaxGIOPConnectionPerServer 1

Thread pool & thread-per-connection policy

Pervious omniORB versions only support the thread-per-connection policy to serve calls on the server side. This is a sensible policy that provides good speed and fair resource allocation. However, in extreme conditions, for example when the number of connections is much greater than a sensible number of server threads, it makes sense to switch to use the thread pool policy.

omniORB4 supports both the thread-per-connection, which is the default, and the thread pool policy. In fact, it will dynamically switch between the 2 when the number of connections rises above or falls below 2 thresholds.

The configuration variable threadPerConnectionPolicy controls the threading policy of the ORB. If the variable is set to TRUE(1), it uses the thread-per-connection policy. Otherwise, it uses the thread pool policy.

The number of threads in the thread pool is controlled by the configuration variable maxServerThreadPoolSize.

Even when the ORB is using the thread-per-connection policy, it will switch to thread pool when the number of connections exceeds the threshold set by the configuration variable threadPerConnectionUpperLimit. Subsequently if the number drops below threadPerConnectionLowerLimit, the ORB will revert back to thread-per-connection. Notice that the switch betwen policies only affect new connections that are established after the switch. Existing connections are fixed to one policy throughout their life times.

All the configuration variables have their ORB initialisation equivalent:

-ORBthreadPerConnectionPolicy <0 | 1>
-ORBmaxServerThreadPoolSize <n threads>
-ORBthreadPerConnectionLowerLimit <n connections>
-ORBthreadPerConnectionUpperLimit <n connections>

Main Thread policy

omniORB now supports the MAIN_THREAD_MODEL POA ThreadPolicy. This causes all upcalls to a main thread POA to be performed with the main thread, rather than a thread created by omniORB. This is necessary in some awkward systems which are extremely non thread-safe.

To be able to dispatch calls on the main thread, omniORB obviously needs to have control of the main thread. Therefore, ORB::run(), ORB::work_pending() and ORB::perform_work() now actually do something if called from the main thread. In the past, it was never necessary to call any of these functions. Of course, if you don't use the main thread policy, there is still no need to give the main thread to omniORB.

It is not necessarily obvious which thread the 'main' thread is. By default, omniORB uses whichever thread was used to initialise the omnithread library via its static initialiser. In a simple program where omniORB is linked at compile time (even if using dynamic libraries), omnithread is initialised before main by the C++ runtime, so the thread will definitely be the main thread. If you use the dynamic loader to load omniORB after main() runs, omnithread might be initialised by some other thread.

To force omniORB to treat a particular thread as the 'main' thread, call omniORB::setMainThread() from the desired 'main' thread.

BiDirectionalGIOP

Useful in conjunction with SSL to do callbacks over the wide area network and through a firewall. More documentation to be written by some kind soul...

Unix Socket Transport

A transport to use the unix domain socket can be instantiated on unix platforms. This is omniORB specific and therefore cannot be used to interoperate with other ORBs. Nevertheless, the transport can be used in conjunction with IIOP to provide speed up for clients & servers running on the same machine.

To use the transport, the ORB initialisation option -ORBendPoint is used, for example:

-ORBendPoint giop:tcp:: -ORBendPoint giop:unix:

The above options will cause the ORB to instantiate an IIOP endpoint and a unix domain socket endpoint. On the other hand, if only the unix endpoint is specified, like this:

-ORBendPoint giop:unix:

then only a unix domain socket endpoint will be instantiated and only omniORB4 clients running on the same machine will be able to contact this server. This may be the desirable effect if only local communication is allowed.

In the examples above, the ORB chooses a filename for the unix domain socket. The ORB picks a name in this form "/tmp/omni-<uid>/<pid>-<timestamp>". One can also specify a filename explicitly, for example:

-ORBendPoint giop:unix:/tmp/foo

This will causes the ORB to use the filename /tmp/foo for the unix domain socket.

The application can also tell the ORB to use a different directory to create the file. This is done by setting the configuration variable unixTransportDirectory or the ORB initialisation option:

-ORBunixTransportDirectory /home/sll/.omni

The option above cause the ORB to create the unix domain socket in /home/sll/.omni instead of /tmp/omni-sll.

Finally, the permission bits of the unix domain socket can be controlled using the configuration variable unixTransportPermission or the ORB initialisation option:

-ORBunixTransportPermission 0700

The option above set the permission bits to read, write and executable by the owner and nobody else. The default mode bits is 0777, i.e. everyone can connect to the socket.

Important note: the file associated with the unix domain socket will be deleted when the ORB is shutdown properly. If however, the server is killed by say typing Ctrl-C at the terminal, the file will be left in the file system. In future, the ORB may install its own signal handler to clean up the file under these conditions. In the meantime, the files have to be deleted manually.

Server Side Connection Acceptance Policy

In pre-omniORB 4.0, the gatekeeper mechanism is provided on some platforms to control which client machines can connect to the server. This is now replaced by the serverTransportRules in the ORB configuration parameters (see SampleCfg).

When the server sees a connection request from a client, it looks at the client's address and uses the rules in serverTransportRule to determine if the connection should be accepted.

There can be more than one configuration line of this type. Each line adds one rule to the selection process. The rules are applied in the order they are defined until one matching rule is found.

The syntax of a rule is as follows:

    serverTransportRule =   [^]<address mask>      [action]+

        <address mask> can be:
            1. localhost            if the address is this machine
            2. w.x.y.z/m1.m2.m3.m4  IPv4 address with the bits selected by
                                    the mask. e.g. 172.16.0.0/255.240.0.0
            3. *                    the wildcard that matches any address

        <action>+ can be one or more of the following:
            1. none              Do not accept this connection.
            2. tcp,ssl,unix      Accept if the transport is any of the
                                 3 specified.
            3. bidir             Allow bidirectional requests if the
                                 client requests it.

         The optional prefix ^ before <address mask>, if present, causes
         the ORB to remove previously declared clientTransportRules from
         its internal store because adding the current rule.

By default, no rule is defined. The ORB implicitly uses the following rule:

        serverTransportRule =    *     unix,tcp,ssl

If any rule is specified, the implicit rule will not be applied.

Here are some example usages:

  1. Only accept connections from our intranet

        serverTransportRule = localhost                  unix,tcp,ssl
                            = 172.16.0.0/255.240.0.0 tcp,ssl
                            = *                          none
  1. Only accept ssl connections if the client is not on our intranet

        serverTransportRule = localhost                  unix,tcp,ssl
                            = 172.16.0.0/255.240.0.0 tcp,ssl
                            = *                          bidir,ssl

Client Side Transport Selection

When the client receives an IOR that defines 1 or more ways to contact the server, the rules in clientTransportRule filter and prioritise the order in which the transports are used. ClientTransportRules can be specified in the ORB configuration parameters(see SampleCfg).

There can be more than one configuration line of this type. Each line adds one rule to the selection process. The rules are applied in the order they are defined. The relative positions of the rules define the relative priority. The first rule has the highest priority.

The syntax of a rule is as follows:

     clientTransportRule =   [^]<address mask>      [action]+

        <address mask> can be:
            1. localhost            if the address is this machine
            2. w.x.y.z/m1.m2.m3.m4  IPv4 address with the bits selected by
                                    the mask. e.g. 172.16.0.0/255.240.0.0
            3. *                    the wildcard that matches any address

        <action>+ can be one or more of the following:
            1. none              Do not use this address
            2. tcp,ssl,unix      Use the 3 transports in the specified order
                                 if any or all of them are available
            3. bidir             Any connection to this address should be
                                 used bidirectionally.

         The optional prefix ^ before <address mask>, if present, causes
         the ORB to remove previously declared clientTransportRules from
         its internal store because adding the current rule.

By default, no rule is defined. The ORB implicitly uses the following rule:

        clientTransportRule =     *   unix,tcp,ssl

If any rule is specified, no implicit rule will be applied.

Given an IOR, for each of the addresses within it, the ORB matches the address to the rules. If one is found, the position of the matched rule and the action is noted. If the action is none, the address is discarded. If the action does not contain the transport the address is specified for, e.g. the action is "ssl" but the address is "tcp", the address is discarded. Otherwise, the address and action is entered as one of the candidates to use. Having gone through all the addresses, the candidiates available are then ordered based on the priority of the matching rules and used accordingly.

Here are some example usages:

  1. Restrict to only contacting server on the same host:

           clientTransportRule = localhost      unix,tcp
                               =   *            none
  1. Use tcp to contact servers in the intranet and must use bidirectional
    • ssl otherwise.

           clientTransportRule = 172.16.0.0/255.240.0.0  unix,tcp
                               =            *            bidir,ssl
  1. When a fast network (192.168.1.0) exists in the cluster, use it in preference to
    • the external network.

           clientTransportRule = 192.168.1.0/255.255.255.0  unix,tcp
           clientTransportRule = 172.16.0.0/255.240.0.0 unix,tcp
                               =       *                none

Client side call timeout

The ORB parameter clientCallTimeOutPeriod can be set to the maximum time (in milliseconds) a remote call takes. If the time limit is exceeded, the ORB will shutdown the connection. A TRANSIENT exception is raised.

Note the change from omniORB 3. omniORB 3's timeout was specified in seconds. omniORB 4's in in milliseconds.

Complete freeing of all heap allocations

Previous versions of omniORB would allocate a significant number of singleton objects on the heap, which would never be freed. This caused MSVC (but not Purify) to report memory leaks, and caused problems for people using dlopen() and similar functions. omniORB now deallocates everything it has allocated.

Full deallocation only occurs if orb->destroy() is called. It happens when the last source file that has #included any omniORB header is unloaded. This means that if you wish to dynamically load/unload code which uses omniORB, you must make sure no omniORB headers are #included by the code doing the loading/unloading.

If you run with trace level 15, you will see some indication of the things cleaned up at shutdown/destroy.

Thread id logging

The new traceThreadId option adds the thread id of the logging thread to all log message output due to traceLevel and traceInvocations. This can be useful for tracking down race conditions.

CORBA 2.5 DynAny

DynAny has been updated from the CORBA 2.2 specification to the 2.5 specification. There are some significant differences in the interfaces, and your old DynAny code will no longer compile. See DynAnyMigration for details.

Forward-declared structs and unions

Forward declarations of structs and unions are now supported, for the creation of recursive types without anonymous sequences. For example:

    struct Tree;
    typedef sequence<Tree> TreeSeq;
    struct Tree {
      string  nodeName;
      TreeSeq children;  
    };

Note that you can only use forward declared structs/unions for declaring sequence types; any other use before the full definition is a compile-time error.

Shortcut local calls

When a servant for an object is in the same address space as the client, omniORB uses a colocation optimisation that makes the call significantly faster than a remote call. However, to adhere to the CORBA specification, there is still a fair bit of work involved in a local call, including locking to make sure everything is thread safe, per-thread data access for POACurrent, and all sorts of other things. This adds up to mean that a colocated call is significantly slower than a direct virtual function call would be.

omniORB 4 supports a proprietary POA policy that allows local calls to shortcut all of this, resulting in local calls that are almost as fast as virtual function calls. Of course, with this policy the proper POA semantics are no longer supported: the POA threading model is ignored, POACurrent is not supported, etc. Most importantly, race conditions with object deactivation can cause crashes. You must never deactivate a servant when shortcut calls are being made to it. Shortcut calls cope properly with invocations after a deactivation (with an OBJECT_NOT_EXIST exception or ServantActivator call, etc.), but deactivations during a shortcut call may delete the servant from underneath the call, leading to a crash.

An object reference is set up for shortcut calls the first time it is invoked upon. This means that the first call to the object takes marginally longer than a normal colocated call; all subsequent calls take the shortcut.

To enable shortcut calls, you must do two things. First, compile your IDL with an extra flag, -Wbshortcut:

  omniidl -bcxx -Wbshortcut foo.idl

This generates extra code in the object reference. It is turned off by default since it takes extra code space, and has a very small time overhead on all invocations. You may mix stubs compiled with and without this option, as long as all interfaces within an inheritance hierarchy either have the option or do not.

Second, you must activate your servants within a POA with the correct policy, e.g.:

  CORBA::PolicyList pl;
  pl.length(1);
  CORBA::Any v;
  v <<= omniPolicy::LOCAL_CALLS_SHORTCUT;
  pl[0] = orb->create_policy(omniPolicy::LOCAL_SHORTCUT_POLICY_TYPE, v);

  PortableServer::POA_var shortcut_poa =
    rootpoa->create_POA("shortcut", PortableServer::POAManager::_nil(), pl);

The LOCAL_CALLS_SHORTCUT policy can be mixed with any other POA policies.

To give an indication of how much difference the shortcut makes, on my 500Mhz machine a normal colocated call takes 1730 nanoseconds, or 1400 with POACurrent disabled. A shortcut call takes just 70 nanoseconds. For comparison, a virtual function call takes 30 nanoseconds. The difference between the shortcut and the virtual call sounds like a lot, but note that it's only 20 clock cycles.

These timing measurements were made in a very simple way, just timing a loop doing a large number of invocations (beween 1 million and 100 million), and dividing by the number of invocations. An empty loop doing no invocations works out to 4ns per iteration (2 clock cycles!), so all of the above figures have that overhead. The numbers are accurate in that they are stable between separate runs, and they stay the same as the number of invocations is changed, but they are probably not very representative of the actual performance a real application would get. Since the test code is doing essentially nothing, it is most likely that all of the code and data fit in the processor caches, and other things like branch prediction are probably working better than they would ever do in a real application.

long double

The long double type is now supported on platforms that have a native 128-bit long double type, and on x86 (which has a strange 79/80-bit long double type).

Limitations:

Log function

omniORB's trace messages are normally written to stderr. The new omniORB::setLogFunction function lets the application override this:

  void myLogFunction(const char* log) {
    cout << log;
  }
  int main() {
    omniORB::setLogFunction(myLogFunction);
    ...
  }

OmniOrb4DevelopmentStatus (last edited 2005-08-25 22:51:45 by cmbg-cache-5)