ORBit2 Frequently Asked Questions - FAQs

Michael Meeks

Michael Rumpf

Frank Rehberger


Table of Contents
CORBA
How does a client connect to a server?
How can I specify default parameters in IDL?
How can I get the IP address of a cient/server object in CORBA?
Who is responsible ?
Why can't I keep a pointer to an argument ?
ORBit2
What is ORBit2?
When and who started the project?
How is ORBit2 better than ORBit 'stable' ?
How can I install a version of ORBit without affecting my GNOME desktop
Where can I get the CVS HEAD version of ORBit2?
What is the difference between the CVS version and the GNOME package?
I can't connect to my remote objects ?
Which parameters are supported by CORBA_ORB_init() ?
Calling ORB_init(), what is string "orbit-local-orb" good for?
Is ORBit2 thread safe ?
How do I debug memory leaks?
What is this re-enterancy thing ?
Can I invoke methods from multiple threads ?
Can I receive invocations in multiple threads ?
Can I have each invocation handled by a different thread ?
How does the new 'type' system work ?
What do you mean by 'type' data ?
How do we get type data for an interface ?
Type data from an object reference ?
Type data from a type library ?
What is a type library (or imodule) ?
How do I find what type libraries are installed ?
Why bother generating type information from an interface ?
Why is a type based ORB better ?
Why is a type based ORB potentialy faster ?
What is the "purify cleanliness" autoconf option ?
How do I use CORBA_strings?
My skels leak memory - why ?
Why should I not use the _release flag?
Why is the IOR from ORB XYZ not understood by ORBit?
Help
Is there a mailing list HOWTO?
How can I subscribe to the mailing list?
How can I unsubscribe from the mailing list?
How can I send an e-mail to the mailing list?
Is there a mailing list archive?
I'm new to CORBA. What books are available?

CORBA

How does a client connect to a server?

This is a well known problem in CORBA (more precisely in any distributed object system). It is commonly known under the term "bootstrapping". In general, object references can be obtained from a Name Service (or a Trading Object Service), but a name service (thanks to the clear design of CORBA) is itself an object. So, how do you get the reference to the name service if it is itself an object ?

The standard solution for a client, finding a first object reference to a server is by exchanging an Interoperable Object Reference (IOR). The server process produces an IOR of the created object by using the method

CORBA_string CORBA_ORB_object_to_string(CORBA_ORB orb, const CORBA_Object obj, CORBA_Environment* env);

The generated string, also called stringified object reference, can be transfered by any kind of media, like email, HTTP, NFS, filesystem, or even as a message in a bottle ;-) . The client process reads the IOR from the medium and converts it back into its binary representation via

CORBA_Object CORBA_ORB_string_to_object(CORBA_ORB orb, const CORBA_char *str, CORBA_Environment *env);

Afterwards the client holds a valid object reference to the server and thus is able to invoke methods in the usual way.

Until now non-standard ways to solve this bootstrapping issue have been introduced by different ORBs. One example is the Visibroker Location Service. The ORB registers each object at a central service by a proprietary _bind() method. The discovery of the service is done by network broadcasts. The drawback of this mechanism is that the information about the objects is stored in a central table. The table needs to be updated on a regular basis. This is necessary because of malicious objects not cleanly deregistering. If the broadcast interval is to short the updates will cause a lot of noise on the network. If the interval is to long the table contains zombie objects. Such kind of proprietary solutions exists for many major CORBA implementations.

Ideally the method resolve_initial_references() could be used to find a reference to the naming service. Therefore the ORB must be able to read IORs without requiring the developer to write some additional code. In the past each ORB had its own command line parameters to pass IORs to the ORB's core (ORBit: ORBNamingIOR=IOR:.....). The Interoperable Naming Service (INS) specification introduces the standardized command line parameter -ORBInitRef to achieve this.


    bash$appname -ORBInitRef NameService=IOR_of_naming_service 

The only trick is to pass argc and argv to the ORB_init() call of the ORB, so that the ORB's core can extract the relevant parameters. Afterwards the call

nsobj = resolve_initial_references("NameService"); returns the desired object reference. The INS specification defines, besides the IOR, other human readable object references. corbaloc:iiop://IIOPVersion@hostname:port/ObjectKey

This offers the possibility for a client to point to a server object just by providing a human readable address. Another proposed naming scheme is corbaname, which refers to a naming service running on the host the, specified by hostname. corbaname://hostname#a/b/obj The a/b/obj specifies a Name, i.e. a sequence of NameComponents, which resolves to an object reference. These mechanisms will extremly improve the whole bootstrapping process and finally solve the problem, as it has been one of the most annoying issues in the past. There are are also a few critics of the human readable object reference corbaloc. They think that the fact of having opaque IORs is weakened by the INS specification. Specifying protocol details, like port numbers or protocol version numbers, can result in references to become invalid when the protocol, used for transportation is exchanged. The Object URLs have to be extended to support the new protocol information, whereas IORs always remain the same, a sequence of numbers.

The CVS HEAD version of ORBit has a partial implementation of the INS specification. Michi Henning has a more elaborate description of the problem here.


How can I specify default parameters in IDL?

IDL does not allow to specifiy default parameters. There are mainly two reasons for that. First, IDL is some kind of least common denominator of all the languages for which a CORBA mapping is available. Many languages do not support the concept of default parameters and thus have difficulties in supporting this feature in the mapping. And second, default parameters are not really necessary. The designer of an interface can easily split such funtionality into two or more separate methods (Attention: Overloading is not supported for the same reasons, so that methods must have different names).


How can I get the IP address of a cient/server object in CORBA?

The IP address (as well as the port number or any other protocol related feature) is hidden in the IOR (Interoperable Object Reference). The reason for this opacity is that CORBA can use any protocol for transportation of requests between object instances. The GIOP (General Inter ORB Protocol) is independent from any special network protocol. The IIOP (Internet Inter ORB Protocol) is a translation of GIOP into TCP/IP. IIOP support is not a mandatory feature of an ORB, but because of the Internet it has become a must for any ORB to implement. If we start relying on the presence of a specific protocol the original intention becomes weakened and may render object references, valid today, invalid in the future. (see TAO (The ACE ORB, ACE - Adaptive Communication Environment) for an ORB which supports pluggable protocols)


Who is responsible ?

The bulk of the initial work is down to Elliot Lee, and various people whose ideas he fused liberaly Kennard White, Sebastian Wilhelmi - the polishing and recent work down to Mark McLoughlin, Martin Baulig and Michael Meeks.


Why can't I keep a pointer to an argument ?

If you are implementing a CORBA method, often you are sent data and wish to keep it around; one scenario might be where you are sent a sequence as an 'in' or 'inout' argument:

static void
impl_MyModule_myMethod (PortableServer_Servant            servant,
      const CORBA_sequence_CORBA_octet *data,
      CORBA_Environment                *ev)
{
  /* This code contains an error */
  g_hash_table_insert (my_hash, data);
}
The lifetime of the 'data' variable is only that of the method invocation. What this means is that when the invocation comes in across the wire - the arguments are de-marshaled to temporary storage. The method is then invoked - on the data, and then the data is freed after the invocation ( to avoid leaking it, or the user having to explicitely free it ).

Thus - if you want to keep a pointer to data; you need to copy it to insert it into the table. ORBit2 provides a helpful convenience function to copy any value, specified by type:

{
  CORBA_sequence_CORBA_octet *copy;

  copy = ORBit_copy_value (data, TC_CORBA_sequence_CORBA_octet);
  g_hash_table_insert (my_hash, copy);
}
is correct.

ORBit2

What is ORBit2?

ORBit2 is the next revision in the ORBit development plan. It is substantialy re-written, and contains a number of new, advanced features. One of these is an abstract IO layer split out into the separate 'linc' library. This allows features such as SSL operation and multiple new connection types.


When and who started the project?

The project was started by Elliot Lee and Dick Porter around February 1998.


How is ORBit2 better than ORBit 'stable' ?

In many ways:

  • Targets CORBA 2.4 instead of CORBA 2.2

  • Theoreticaly thread safe - see later.

  • In conjunction with linc allows all manner of new transports

  • Protection against malicious / badly formed wire data

  • Type centric

    • smaller - stubs / skels are tiny: ~50% smaller.

    • generic operation, eg. method tracing

    • fast in-proc language bindings

    • marginaly slower currently



  • Uses glib mainloop

  • "URL for IOR" to allow retrieving an IOR via HTTP

  • Cleaner

    • lots of code cleaning and re-factoring

    • most CORBA interfaces generated from pseudo-IDL

    • a more pleasant directory structure

    • more complete implementations of many things



  • Tested - fairly comprehensive stress testing.

  • No resource leakage of TypeCodes

  • Lots of bugs fixed, and new ones created.



How can I install a version of ORBit without affecting my GNOME desktop

Configure the package with the following command: ./configure --prefix=~/orbit_test_dir --exec-prefix=~/orbit_test_dir Where orbit_test_dir is an arbitrary subdirectory. Then call make and make install, which will copy ORBit to the specified directory. Finally you just need to adapt your PATH and LD_LIBRARY_PATH environment variables by adding ~/orbit_test_dir/bin to PATH and ~/orbit_test_dir/lib to LD_LIBRARY_PATH respectively.


Where can I get the CVS HEAD version of ORBit2?

The gnome developer site has a description on how to use the anonymous CVS access. After logging on you just need to type "cvs -z3 co ORBit2", whereas "ORBit2" is the name of the module


What is the difference between the CVS version and the GNOME package?

The Roadmap for GNOME version 2.x requires ORBit2 to be binary and source-code compatible. Therefore updates on the ORBit2 package are accepted as long as these requirements are not violated.


I can't connect to my remote objects ?

A GNOME security discussion led to disabling IIOP over IP server sockets (i.e. ports) per default. Instead either UNIX domain sockets or shared memory for interprocess communication are used. This disables communcation over the network but prevents the system from Denial of Service attacks. If you want to use ORBit over the network you need to turn it on again. This can either be done in /etc/orbitrc (system-wide settings), in ~/.orbitrc (user's settings), or on a per application basis by passing a parameter to the ORB. For Solution one and two you need to put ORBIIOPIPv4=1 into one of the orbitrc files. Controlling the settings for each application can be done by providing ORBIIOPIPv4=1 at the command-line to your client/server application and passing the argc and argv parameters to the CORBA_ORB_init() call (default-handling). You can check the setting with the command: netstat -ao | grep LISTEN. You should not have any orbit related sockets in listen mode (a line: "unix 0 [ ACC ] STREAM LISTENING XXXX /tmp/orbit-USER/orb-YYYYYYYYYYYYYYYY" should not appear)


Which parameters are supported by CORBA_ORB_init() ?

ORBit specific parameters:

  • ORBDebugFlags=traces|inproc_traces|timings|types|messages|errors|objects|giop|refs The amount of debugging information to display. The modules can be combined by using , ":" as separator.

  • ORBIIOPIPv4=0|1 Disable/Enable IPv4 server sockets.

  • ORBIIOPIPv6=0|1 Disable/Enable IPv6 sockets.

  • ORBIIOPIPName=HostInterface Defines the IP host-name the server shall bind to.

  • ORBIIOPIPSock=#port Number of port to listen for IIOP connections. This parameter is required for persistent object references (PortableServer_PERSISTENT policy).

  • ORBInitialMsgLimit=# Amount of data accepted on first method invocation. Succeeding method invocations are not limited. This option is used to prevent DOS attacks - ie. opening a connection to service, sending huge amount of junk data.

  • ORBIIOPUNIX=0|1 Disable/Enable UNIX domain sockets.

  • ORBIIOPIrDA=0|1 Disable/Enable IrDA capabilities.

  • ORBIIOPSSL=0|1 Disable/Enable IIOP over SSL.

  • ORBIIOPIrDA=0|1 Disable/Enable IrDA capabilities.

  • ORBNamingIOR=IOR (Available for ORBit2.8) Define specific reference of NameService, ie. on command line define reference of NameService by -ORBNamingIOR=IOR:010000002800000.., or as human readable CORBA-Loc URL -ORBNamingIOR=corbaloc:iiop:gnome.org:8884/NameService%00. The suffix %00 terminates the char-sequence forming a C-string. If used in combination with option ORBInitRef, the option ORBInitRef dominates.

  • ORBInitRef=Id=IOR (Available for ORBit2.8) Define initial reference of generic service, ie. on command line define reference of NameService by -ORBInitRef=NameService=IOR:010000002800000..

  • ORBCorbaloc=0|1(Available for ORBit2.9) If set, object_to_string will create corbaloc URL terms instead of IORs, ie. corbaloc:iiop:1.2@gnome.org:8884/NameService%00



Calling ORB_init(), what is string "orbit-local-orb" good for?

ORBit2 supports single- and multi-threaded mode. the string is used to tell ORBit2 what mode it shall run into. Using the string "orbit-local-mt-orb" for initialization, ORBit2 will enter the multi-threaded mode:


       (*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-mt-orb", ev);
      
For single threaded application usually "orbit-local-orb" is given as argument:

       (*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-orb", ev);
      
Footnote: Since release ORBit2-2.7.5 multi-threaded setup is used by default. To force single threaded setup you must give string argument "orbit-local-non-threaded-orb", any other string will keep multi threaded settings.

       (*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-non-threaded-orb", ev);
      


Is ORBit2 thread safe ?

ORBit2 is theoreticaly thread safe, ie. we thought about it a bit during the design - which is nominaly thread safe, we added a lot of locks, and we fixed deadlocks when they were found. With release ORBit2-2.7.5 thread safe setup is used by default.


How do I debug memory leaks?

OK - if you compile ORBit2 with --enable-debug (perhaps you did this already), then export ORBIT2_DEBUG=refs, then re-run - it should show you the type of object that is leaked - which may help. Probably you are missing a CORBA_Object_release (foo, NULL); somewhere.

You might want to use memory debugger of some sort; I would recommend valgrind - google for it; you need to build ORBit2 with --enable-purify and run with --alignment=8 but it's an extremely powerful & useful tool.


What is this re-enterancy thing ?

When a method is invoked, while the ORB is waiting for a return value or exception (if applicable) the ORB processes any other incoming requests in a re-enterant fashion. This occurs even during threaded operation currently.


Can I invoke methods from multiple threads ?

Yes, this should present no particular problem.


Can I receive invocations in multiple threads ?

Yes - assuming you have a glib mainloop ( or a linc_mainloop ) running in one or several of your threads. The precice thread that the invocation is recieved in is unpredictable.


Can I have each invocation handled by a different thread ?

Yes - much effort has been put into this. POA policies must be used to define behaviour of newly created POAs; eg. 'THREAD_PER_REQUEST' policy.


How does the new 'type' system work ?

The new type system forms a fundamental part of ORBit2 and presents a major simplification.


What do you mean by 'type' data ?

By type data we mean not only structure layout information, but also full interface and method information. ie. not just value class types but interfaces as well.


How do we get type data for an interface ?

There are two answers to this. Firstly, if you have a pointer to an Object reference and you know nothing more than that it is a ORBit2 handled CORBA object, you can (via. an ORBit2 extension) request it's type id, and from this, a full interface description.

see ORBit2/include/orb/orb-core/orbit-small.h and ORBit2/include/orb/orb-core/orbit-iinterface.h (from) ORBit2/src/orb/orb-core/orbit-iinterface.idl


Type data from an object reference ?


        CORBA_char *type_id;
        ORBit_IInterface *iface;

        type_id = ORBit_small_get_type_id (obj, ev);
        iface   = ORBit_small_get_iinterface (obj, type_id, ev);
   


Type data from a type library ?

If we wish to implement an interface in our scripting language that is not currently registered with the ORB, then we can load it dynamicaly from the type library interface:

ORBit_small_load_typelib ("Bonobo");
We can then suck all the interface and TypeCode information out of the library, in order to construct local language bound peers:
CORBA_sequence_CORBA_TypeCode   *ORBit_small_get_types ("Bonobo");
CORBA_sequence_ORBit_IInterface *ORBit_small_get_iinterfaces (...);

What is a type library (or imodule) ?

Type libraries are essentialy the same generic interface information that the ORB uses to marshal and de-marshal information in the C stubs. It is contained in the -common.c file of a compiled set.

To install a type library correctly you need to have some automake a little like:


orbittypelib_LTLIBRARIES = Bonobo_module.la
orbittypelibdir = $(libdir)/orbit-2.0
IMODULE_SOURCE =        \
        Bonobo.h        \
        Bonobo-common.c \
        Bonobo-imodule.c
Bonobo_module_la_SOURCES = \
        Bonobo-imodule.c
Bonobo_module_la_LIBADD = \
        $(LIBBONOBO_LIBS)
Bonobo_module_la_LDFLAGS = \
        -export-dynamic -module

$(IMODULE_SOURCE): $(idl_DATA) $(ORBIT_IDL)
        $(ORBIT_IDL) $(idl_flags) --imodule \
                     $(top_srcdir)/idl/Bonobo.idl
   

Note that the library is installed into $(libdir)/orbit-2.0. When a typelib is loaded, an explicit path can be passed in, otherwise the ':' delimited path environment variables ORBIT_TYPELIB_PATH and GNOME_PATH are searched.


How do I find what type libraries are installed ?

There is a utility ORBit2/test/typelib-dump that will display a list of available libraries for your path setup:

Installed type libraries:


        /opt/ngnome2/lib/orbit:

                Everything
                Accessibility
                Bonobo
   
It can also rudimantarily dump the contents of a type library.


Why bother generating type information from an interface ?

With ORBit stable, language bindings had to load and parse the IDL definitions for the interface. This had several disadvantages.

  • Primarily performance - loading a load of IDL text, forking the pre-preocessor to pre-process it, resolving all the symbols as strings, converting to an internal representaton - took time. With a standard internal representation, and a simple dlopen to grab it we have a major performance win.

  • Include problems: many IDL files are grouped into a single file to build, and can cause grief when included individualy. This contrasts with a working bundle of interfaces, verified at package IDL compile time.

  • libIDL - is an unmaintained mess, and is not particularly pleasant to link against, or code to.

  • Finding the IDL files - there was no standard path structure, or method of reliably locating all the relevant IDL files. Now at least there is an ad-hoc shared standard.



Why is a type based ORB better ?

Firstly ABI reduction, in ORBit stable the API usage by the stubs was very considerable - many methods were called, and there was a considerable body of code in a stub or a skel.

With ORBit2 a stub looks like a bit like this:


Bonobo_Unknown
Bonobo_Unknown_queryInterface (Bonobo_Unknown     obj,
                               const CORBA_char  *repoid,
                               CORBA_Environment *ev)
{
        Bonobo_Unknown _ORBIT_retval;

        ... local fast case ... else ...
        { /* remote marshal */
                gpointer _args[] = {
                        (gpointer) & repoid
                };

                ORBit_small_invoke_stub (
                        obj,
                        &Bonobo_Unknown__iinterface.methods._buffer[2],
                        &_ORBIT_retval, _args, NULL, ev);

        }

        return _ORBIT_retval;
}
   
ie. we expose a single method call here 'ORBit_small_invoke_stub'. This method is passed the object reference, the arguments in a normalized form ( as an array of gpointers ) a pointer to the return value, any CORBA_Context we might be _sing and the exception environent.

The skeleton is similar, unwinding a gpointer array of arguments and invoking the C method. NB. for language bindings, you can hook the a virtual invocation pointer on the servant to recieve a method type data pointer and handle the invocation fully yourself.

The indirection and allocation semantics of the argument passing, as well as the C CORBA semantics are lucidly documented in ORBit2/docs/internals/interface-indirection.gnumeric.


Why is a type based ORB potentialy faster ?

Well - partly due to encapsulation. Encapsulation often carries a cost; in ORBit stable there are several layers. Even though the stubs and skels are substantialy unrolled, there are a considerable amount of method calls, and lots of wasteful indirection.

In ORBit2 we can hide an _extremely_ optimized, top to bottom to the wire generic marshaler behind ORBit_small_invoke_stub. This would be totaly private to the ORB, maintaining ORB encapsulation, but giving us buckets of room for optimization.

Secondarily, in ORBit stable the stubs and skels are massively unrolled, giving not only a size penalty but also a speed penalty in terms of the processors instruction cache (Icache). In contrast ORBit2 maintains a far smaller Icached working set, since the generated code that is different per method is tiny, and the same generic code is executed to do the marshaling for each method.

Hence - although currently what performance tests we have suggest that ORBit2 is ~20% slower than ORBit stable, it will be possible ( in a totaly binary compatible fashion ) to tweak and optimize the marshal / de-marshal process to make it arbitarily fast.


What is the "purify cleanliness" autoconf option ?

This (unfinished) option allows the ORB to be configured to run in a slightly slower, but 'cleaner' mode. Purify is a tool that performs advanced memory debugging, and it will detect many common errors. Some of the things ORBit2 can do eg. using uninitialized stack space as a source of randomness will flag false positives as purify errors ( an Uninitialized Memory Read or UMR ). Enabling this flag ensures that all such memory will be blanked first before being read. This also applies to initializing return values before returning them, even on exceptions - a case where CORBA specifies an uninitialized return value.

The performance impact of having a putify clean ORB is probably fairly minimal, perhaps ~10% slower max., finger in the air guestimation.


How do I use CORBA_strings?

For instance if you have a struct like so:


struct employee
{
    CORBA_string name;
}
As long as you do not permit any CORBA/ORBit to free it, you can do:

  struct employee thisemployee;
  thisemployee.name = "someone";
Otherwise / the more correct way is to use the CORBA API:

/usr/include/orbit-2.0/orbit/orb-core/corba-string.h:
  CORBA_char          *CORBA_string_dup  (const CORBA_char *str);
  CORBA_char  *CORBA_string_alloc  (CORBA_unsigned_long len);
therefore simply

  thisemployee.name = CORBA_string_dup ("someone");


My skels leak memory - why ?

Sometimes people post to the list saying I'm doing:


CORBA_sequence_CORBA_string *
get_StringSequence (PortableServer_Servant servant,
                    CORBA_Environment     *ev)
{
  int i;
  CORBA_sequence_CORBA_string *s;
         
  s = CORBA_sequence_CORBA_string__alloc ();
  s->_buffer = CORBA_sequence_CORBA_string_allocbuf (100);
  s->_length = 100;

  for (i = 0; i < 100; i++)
    s->_buffer[i] = CORBA_string_dup ("A string");

  return s;        
} 
Why am I leaking huge chunks of memory ? The answer is the _release feature. This field is set to FALSE when the sequence is allocated (s->_release), and when you return from the implementation to the skel, the skel marshals the sequence, and then CORBA_free's it. However, if the _release flag is FALSE, the _buffer and it's contents are not freed. This allows people to return static copies of their data which can be a big efficiency win.

In this case you want the release flag set; this can be done by:

 s->_release = TRUE; 
before you return, or
CORBA_sequence_set_release (s, TRUE); 
A similar scheme is used for the value of a CORBA_any being returned.


Why should I not use the _release flag?

While _release works really well out of process, if you are writing library code, or code that might be used by another component in process - then the _release flag is a nightmare. The reason is quite simple; in the remote case, the data is copied to the wire, and the client receives a copy of which he controls the lifecycle. The problem is that in-proc, the client receives only a shallow copy and has no control ( or idea ) of it's lifecycle. Thus you might return some data, and then in a later method alter the data - the client's copy then would contain bad information.


Why is the IOR from ORB XYZ not understood by ORBit?

Check whether the IOR has some whitespaces at the end. ORBit version below 0.5.x does not accept IORs with trailing whitespaces.


Help

Is there a mailing list HOWTO?

The mailing-list demon provides a short description on how to use it. Send an e-mail to with subject "help".


How can I subscribe to the mailing list?

Go to mail.gnome.org/mailman/listinfo/orbit-list.


How can I unsubscribe from the mailing list?

Go to mail.gnome.org/mailman/listinfo/orbit-list.


How can I send an e-mail to the mailing list?

Send e-mail to .


Is there a mailing list archive?

There is a searchable archive available on mail.gnome.org/archives/orbit-list.


I'm new to CORBA. What books are available?

There are a lot of books available. The major online stores have ratings and comments of almost any CORBA book on the market.

One of the best books is Michi Henning's and Steve Vinoski's book: "Advanced CORBA Programming with C++" (ISBN 0-201-37927-9). Although the title seems to address only for C++ programmers it contains explanations of many fundamental concepts and is thus useful for a general understanding.