The Gnorba library

Introduction

gnorba is mainly a wrapper around two corba functions (CORBA_ORB_init and CORBA_ORB_resolve_initial_services) and implements an Activation Directory. The Activation Directory is a filesystem which holds a list of the available CORBA servers on a machine which are not necessarily running.

Initialisation

Gnome applications usually have a GTK graphic interface. GTK uses a special event loop to handle all the X server events and all its own events. ORBit uses also its own event loop. This means that graphical applications need a way to have these two loops run together. This is basically why some special initialisation needs to be done.

The gnome_CORBA_init function is used and is simply a wrapper around the CORBA_ORB_init and gnome_init functions. It will integrate ORBit event loop into GTK's own event loop. The following code will show its use:

#include <orb/orbit.h>
#include <libgnorba/gnorba.h>
#include <gnome.h>

int main (int argc, char **argv)
{
  CORBA_ORB orb;
  CORBA_Environment ev;

  CORBA_exception_init (&ev);
  orb = gnome_CORBA_init ("a simple gnorba test prgm", 
                          "v 1.0", 
                          &argc, 
                          argv, 
                          &ev);

  return 0;
}

Naming Services

We already seen why the Name Service of ORBit has a few problems: 1) one needs to launch the orbit-name-server by hand and 2) the Name Service does not work with CORBA_ORB_resolve_initial_reference.

GNOME implements the gnome_name_service_get function which will return a CORBA::Object representing the Root NamingContext as it should be returned by CORBA_ORB_resolve_initial_references. Its use is straightforward:

#include <orb/orbit.h>
#include <libgnorba/gnorba.h>
#include <gnome.h>

int main (int argc, char **argv)
{
  CORBA_Object name_server;
  CORBA_Environment ev;

  CORBA_exception_init (&ev);
  orb = gnome_CORBA_init ("a simple gnorba test prgm", 
                          "v 1.0", 
                          &argc, 
                          argv, 
                          &ev);


  name_server = gnome_name_service_get ();
  return 0;
}

This function will first check if a name server was launched then it will launch it if not already and it will return the Object's Object reference. To do so, it stores information on the Root Window of the X window system which is why this function was not added to ORBit code: it will not work outside of a graphical X system.

The GOAD

Introduction

The GOAD allows you to list the CORBA servers ready to run and to eventually launch them. For example, the help system of GNOME is listed in the GOAD repository and may be launched by activating it.

This is necessary because CORBA provides a mean to use active servers but, to be active, they need to be fed in memory which may lead to memory shortage. There are ways in CORBA to get around this problem by using servant managers but on the whole, the GOAD is a simpler solution.

It is possible to look at this repository without having to code anything: the "goad-browser" program is distributed with libgnorba and will list the servers and allow you to activate them.

Using the GOAD

To use the GOAD, one has access to a simple yet powerful api:

Table 5-1. The GOAD api

Function nameFunction use
goad_server_list_getThis function will return a GoadServerList * which lists all the servers registered against the goad.
goad_server_list_freeThis will free the GoadServerList allocated by goad_server_list_get.
goad_server_activateThis function will return the CORBA_Object corresponding to the GoadServer passed as a parameter.
goad_server_activate_with_idThis function will ultimately call goad_server_activate but it needs other parameters.
goad_server_activate_with_repo_idThis function will ultimately call goad_server_activate but it needs other parameters.

These functions play with some well known structures: GoadServer and GoadServerList.

typedef struct {
          GoadServerType type;
          /* only GOAD_ACTIVATE_NEW_ONLY
             currently parsed in */
          GoadActivationFlags flags; 
          char     **repo_id;
          char     *server_id;
          char     *description;

          /*
           * Executable/shlib path, relayer IOR, 
           * whatever. This field may disappear 
           * at any time. You have been warned ;-)
           */
          char     *location_info;
  } GoadServer;

typedef struct {
    GoadServer *list;
    GHashTable *by_goad_id;
  } GoadServerList;

typedef enum {
          GOAD_SERVER_SHLIB = 1,
          GOAD_SERVER_EXE = 2,
          GOAD_SERVER_RELAY = 3,
          GOAD_SERVER_FACTORY = 4
  } GoadServerType;

typedef enum {
          /* these two are mutually exclusive */
          /* prefer shlib activation */
          GOAD_ACTIVATE_SHLIB = 1 << 0,
          /* prefer remote activation */
          GOAD_ACTIVATE_REMOTE = 1 << 1,  

          /* these two are mutually exclusive */
          /* Only do lookup in name
           * service for currently running
           * version. */
          GOAD_ACTIVATE_EXISTING_ONLY = 1 << 2,
          /* No lookup in name service. */
          GOAD_ACTIVATE_NEW_ONLY = 1 << 3,
          /* Just make sure that the object is running */
          GOAD_ACTIVATE_ASYNC = 1 << 4 
  } GoadActivationFlags;

Here is sample code using these...

/* this function will return a clist widget 
 * which holds a list of the available servers
 */
GtkWidget *get_list (void)
{
  GoadServer *tmp;
  char *titles[2] = {"Description", "Activated ?"};
  GtkWidget *clist;
  GtkWidget *popup;

  list = goad_server_list_get ();
  tmp = list->list;

  clist = gtk_clist_new_with_titles (2, titles);
  gtk_signal_connect (GTK_OBJECT(clist), 
                      "select_row",
                      select_row_cb, 
                      NULL);
  gtk_clist_set_column_width (GTK_CLIST(clist), 0, 250);
  gtk_clist_set_column_width (GTK_CLIST(clist), 1, 30);
  gtk_clist_set_selection_mode (GTK_CLIST(clist), 
                                GTK_SELECTION_EXTENDED);
  gtk_widget_show (clist);

  for (tmp=tmp; tmp->repo_id; ++tmp) {
    gchar *table[2] = {tmp->description, is_active(tmp)?"yes":"no"};
    gtk_clist_append(GTK_CLIST(clist), table);
  }

  return (clist);
}

The Right Thing to do now is to browse the goad-browser code: gnome-libs/gnorba/goad-browser.c .

Adding servers to the GOAD

To add servers to the GOAD, one should use .gnorba files. Upon the GOAD startup during GNOME's session initialization, the GOAD reads a special directory (/etc/CORBA or /usr/etc/CORBA or...). Each file in this directory may contain one or more server definition. Here is one such file:

[gnome_panel]
type=exe
repo_id=IDL:GNOME/Panel:1.0
description=GNOME Panel
location_info=panel

The mapping of these informations to the GoadServer structure fields is straightforward. The first [gnome_panel] is the name the server will be registered against in the name server. The second type=exe is used internally by the GOAD to determine how to launch the server.The last location_info=panel is used to find the corresponding implementation of the server. Here, the gnome_panel was implemented in the panel executable.