CORBA - Iteration

A CORBA style method of enumeration can be seen in the iteration interfaces on the CORBA Naming Service. Given the code we’ve already written for the enumeration interface we can easily implement an iteration interface as well as (or, more likely, instead of).

Setting the scene

As we pointed out in a previous article, reference counting without a keep-alive protocol is not especially robust and objects may be leaked on the server. We are assuming, for the time being, that this is acceptable to us and, in this articles and the previous, examine how COM and CORBA handle the problem of allowing the client to control how a sequence of objects is returned to it.

Once we’ve the CORBA equivalent to the COM enumeration interface we’ll make them both more robust by using the Evictor Pattern on the server to ensure that our server never becomes clogged with objects that are no longer used.

The problem

As was shown in the previous article, it’s often better to allow your clients to determine how many items they process in one go when dealing with collections of objects returned from a server. Last time we showed the COM way of dealing with this problem, albeit in a CORBA environment. This article shows the CORBA way of doing the same thing. The convenient thing is that it’s only really the interface that changes, the requirements for the underlying implementation stay pretty much the same…

The CORBA solution

If you look at the CORBA NamingContext interface you’ll find that it has a list() method this is defined something like this:

typedef sequence<binding> BindingList;

interface BindingIterator;

interface NamingContext
{
// stuff that we've omitted...

   void list(
      in unsigned long how_many,
      out BindingList bl,
      out BindingIterator it);
};
interface BindingIterator
{
   boolean next_one(out binding b);

   boolean next_n(
      in unsigned long how_many,
      out BindingList bl);

   void destroy();
};

When you wish to iterate through a list of bindings you call list() which allows you to specify how many bindings you want returned in the initial BindingList sequence, any subsequent bindings can then be accessed though the BindingIterator. If you ask for more than the available number of bindings then you will get all of them in your initial sequence and the BindingIterator will be nil.

Implementing such an interface for our server is relatively easy now that we have all of the infrastructure in place to support the COM style enumeration interface.

In Enum5.zip we add a CORBA style iteration interface to the server. The client code for the iteration interface is more complex than the COM style enumeration due to the fact that the initial sequence needs to be processed and then subsequent sequences are obtained via the iteration interface. Notice that since we only need a delete() method and not fully featured reference counting we can revert to one of the methods used half-way through the reference counting articles…

At first the flexibility in the interface looks useful. The client can ask for all of the sequence in one go and avoid one additional call to the server. However, unless the client knows how many items there are in the sequence, and unless it is sure that it will always be able to handle that number of items, it must also have code to handle the overflow situation. It’s actually easier to always pass 0 for “how_many” in the initial call to list() as this means that you only need to write code to handle the iteration interface.

Read-Only Iteration

In Enum6.zip we add the corresponding read-only iteration interface. The client code is very similar and the server code has already been written for the enumeration interface.

Comparing COM and CORBA

So. Given the two methods of allowing the client some control over how to retrieve a sequence containing an unknown number of objects, which is best…

The COM version is flexible but potentially requires at least one more trip to the server than the CORBA method. The CORBA way is more flexible for the client, at the expense of more code needing to be written to take advantage of the added flexibility. A simple destroy method is fine if you can always be sure who owns the interface, whilst fully fledged reference counting means you can pass interfaces about with abandon - if you take care to strictly abide by the rules - and if your reference counting is more robust than the one shown here. Being able to clone an iterator may be useful in some circumstances, but could be implemented in both styles of interface. At the end of the day, they’re not that different, they both work and they both require similar support on the server side…

At present, both of these interfaces aren’t as robust as they could be. Due to the lack of a keep-alive protocol in CORBA the server can be left with objects that will never be destroyed if their clients terminate without releasing all of their references. We’ll address this problem in the next article when we look at the Evictor Pattern and how, in some circumstances, you can give the server control over the lifetime of a client created object.

Download

The following source was built using Visual Studio 6.0 SP3 and tested with OmniORB - the open source Corba ORB from AT&T Cambridge. You need to add OMNI_HOME to your environment so that the idl compiler, headers and libraries can be found.

To compile the IDL files you will need to change the path used in the build command for the idl files - well, you will unless you happen to have installed OMNI ORB into exactly the same location as I have… Select the IDL files in the project workspace, right click on them, select settings and edit the path to the OMNIIDL compiler.

Get OmniORB

Enum5.zip - an iteration style interface

Enum6.zip - read only iteration

Revision history