5.9. Factory client & server

Example 5-40. factory.idl


module Examples {

	module Factory {

		interface AbstractService {
			void doit (in string mesg);
			void destroy ();
		};

		interface Producer {
			AbstractService produce (in string id);
		};
	};
};
$ orbit-idl-2 --skeleton-impl factory.idl geenrates all the files we will use in this example.

FileUsage for ClientUsage for Server
factory.hreadonlyreadonly
factory-common.creadonlyreadonly
factory-stubs.creadonly-
factory-skels.c-readonly
factory-skelimpl.c-template for user code

Files remaining to write are listed in following table, starting with factory-client.c in following chapter.

factory-client.cwrite the client code
factory-server.cwrite the generic code for servant creation

5.9.1. Factory client

Example 5-41. factory-client.c

/* factory-client.c hacked by Frank Rehberger
 * <F.Rehberger@xtradyne.de>.  */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <orbit/orbit.h>

#include "examples-toolkit.h" /* etk_ functions */ 
#include "factory.h"


static CORBA_ORB  global_orb = CORBA_OBJECT_NIL; /* global orb */
 
/* Is called in case of process signals. it invokes CORBA_ORB_shutdown()
 * function, which will terminate the processes main loop.
 */
static
void
client_shutdown (int sig)
{
        CORBA_Environment  local_ev[1];
        CORBA_exception_init(local_ev);
 
        if (global_orb != CORBA_OBJECT_NIL)
        {
                CORBA_ORB_shutdown (global_orb, FALSE, local_ev);
                etk_abort_if_exception (local_ev, "caught exception");
        }
}
 
        
/* Inits ORB @orb using @argv arguments for configuration. For each
 * ORBit options consumed from vector @argv the counter of @argc_ptr
 * will be decremented. Signal handler is set to call
 * echo_client_shutdown function in case of SIGINT and SIGTERM
 * signals.  If error occures @ev points to exception object on
 * return.
 */
static
void
client_init (int               *argc_ptr,
	     char              *argv[],
             CORBA_ORB         *orb,
             CORBA_Environment *ev)
{
        /* init signal handling */
 
        signal(SIGINT,  client_shutdown);
        signal(SIGTERM, client_shutdown);
         
        /* create Object Request Broker (ORB) */
         
        (*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-mt-orb", ev);
        if (etk_raised_exception(ev)) return;
}

/* Releases @servant object and finally destroys @orb. If error
 * occures @ev points to exception object on return.
 */
static
void
client_cleanup (CORBA_ORB                 orb,
                CORBA_Object              servant,
                CORBA_Environment        *ev)
{
        /* releasing managed object */
        CORBA_Object_release(servant, ev);
        if (etk_raised_exception(ev))
		return;
 
        /* tear down the ORB */
        if (orb != CORBA_OBJECT_NIL)
        {
                /* going to destroy orb.. */
                CORBA_ORB_destroy(orb, ev);
                if (etk_raised_exception(ev)) 
			return;
        }
}

/**
 *
 */
static
void
client_run (Examples_Factory_Producer     factory,
	    CORBA_Environment            *ev)
{
	#define MAX_ID_LEN 100

	CORBA_char  service_id [MAX_ID_LEN+1] = "";
	gint i = 0;
	gint j = 0;

	for (i = 0; i<20; ++i)
	{
		snprintf (service_id, MAX_ID_LEN, "id-%d", i);

		g_printf ("abstract-service: create,");
		Examples_Factory_AbstractService service 
			= Examples_Factory_Producer_produce (factory, 
							     service_id, 
							     ev);
		if (etk_raised_exception (ev)) 
			return;
		
		for (j = 0; j < 5; ++j)
		{
			g_printf (" apply,");

			CORBA_char *mesg = "hallo welt";
			Examples_Factory_AbstractService_doit (service, 
							       mesg, 
							       ev);
			if (etk_raised_exception (ev)) 
				return;
		}

		g_printf (" destroy\n");

		Examples_Factory_AbstractService_destroy (service, ev);
		if (etk_raised_exception (ev)) 
			return;

		CORBA_Object_release ((CORBA_Object) service, ev);
		if (etk_raised_exception (ev)) 
			return;

	}
	#undef MAX_IDL_LEN
}

/*
 * main 
 */
int
main(int argc, char* argv[])
{
        CORBA_char filename[] = "factory.ref";
         
        Examples_Factory_Producer producer = CORBA_OBJECT_NIL;
 
        CORBA_Environment ev[1];
        CORBA_exception_init(ev);
 
        client_init (&argc, argv, &global_orb, ev);
        etk_abort_if_exception(ev, "init failed");
 
        g_print ("Reading service reference from file \"%s\"\n", filename);
 
        producer 
          = (Examples_Factory_Producer) 
		etk_import_object_from_file (global_orb,
					     filename,
					     ev);
        etk_abort_if_exception(ev, "import service failed");
 
        client_run (producer, ev);
        etk_abort_if_exception(ev, "service not reachable");
  
        client_cleanup (global_orb, producer, ev);
        etk_abort_if_exception(ev, "cleanup failed");
  
        exit (0);
}

5.9.2. Factory server

Example 5-42. factory-server.c

/*
 * factory-server program. Hacked by Frank
 * Rehberger <F.Rehberger@xtradyne.de>
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <orbit/orbit.h>
#include <ORBitservices/CosNaming.h>

#include "factory.h"
#include "factory-skelimpl.c" 

#include "examples-toolkit.h" /* etk_ functions */ 

static CORBA_ORB          global_orb = CORBA_OBJECT_NIL; /* global orb */
static PortableServer_POA root_poa   = CORBA_OBJECT_NIL; /* root POA
	
/* Is called in case of process signals. it invokes CORBA_ORB_shutdown()
 * function, which will terminate the processes main loop.
 */
static
void
server_shutdown (int sig)
{
	CORBA_Environment  local_ev[1];
	CORBA_exception_init(local_ev);

        if (global_orb != CORBA_OBJECT_NIL)
        {
                CORBA_ORB_shutdown (global_orb, FALSE, local_ev);
                etk_abort_if_exception (local_ev, "caught exception");
        }
}

/* Inits ORB @orb using @argv arguments for configuration. For each
 * ORBit options consumed from vector @argv the counter of @argc_ptr
 * will be decremented. Signal handler is set to call
 * echo_server_shutdown function in case of SIGINT and SIGTERM
 * signals.  If error occures @ev points to exception object on
 * return.
 */static 
void 
server_init (int                 *argc_ptr, 
	     char                *argv[],
	     CORBA_ORB           *orb,
	     PortableServer_POA  *poa,
	     CORBA_Environment   *ev)
{
	PortableServer_POAManager  poa_manager = CORBA_OBJECT_NIL; 

	CORBA_Environment  local_ev[1];
	CORBA_exception_init(local_ev);

	/* init signal handling */
	signal(SIGINT,  server_shutdown);
	signal(SIGTERM, server_shutdown);
	
	/* create Object Request Broker (ORB) */
	
        (*orb) = CORBA_ORB_init(argc_ptr, argv, "orbit-local-mt-orb", ev);
	if (etk_raised_exception(ev)) 
		goto failed_orb;

        (*poa) = (PortableServer_POA) 
		CORBA_ORB_resolve_initial_references(*orb, "RootPOA", ev);
	if (etk_raised_exception(ev)) 
		goto failed_poa;

        poa_manager = PortableServer_POA__get_the_POAManager(*poa, ev);
	if (etk_raised_exception(ev)) 
		goto failed_poamanager;

	PortableServer_POAManager_activate(poa_manager, ev);
	if (etk_raised_exception(ev)) 
		goto failed_activation;

        CORBA_Object_release ((CORBA_Object) poa_manager, ev);
	return;

 failed_activation:
 failed_poamanager:
        CORBA_Object_release ((CORBA_Object) poa_manager, local_ev);
 failed_poa:
	CORBA_ORB_destroy(*orb, local_ev);		
 failed_orb:
	return;
}

/* Entering main loop @orb handles incoming request and delegates to
 * servants. If error occures @ev points to exception object on
 * return.
 */
static void 
server_run (CORBA_ORB          orb,
	    CORBA_Environment *ev)
{
        /* enter main loop until SIGINT or SIGTERM */
	
        CORBA_ORB_run(orb, ev);
	if (etk_raised_exception(ev)) return;

        /* user pressed SIGINT or SIGTERM and in signal handler
	 * CORBA_ORB_shutdown(.) has been called */
}

/* Releases @servant object and finally destroys @orb. If error
 * occures @ev points to exception object on return.
 */
static void 
server_cleanup (CORBA_ORB           orb,
		PortableServer_POA  poa,
		CORBA_Object        ref,
		CORBA_Environment  *ev)
{
	PortableServer_ObjectId   *objid       = NULL;

	objid = PortableServer_POA_reference_to_id (poa, ref, ev);
	if (etk_raised_exception(ev)) return;
		
	/* Servant: deactivatoin - will invoke  __fini destructor */
	PortableServer_POA_deactivate_object (poa, objid, ev);
	if (etk_raised_exception(ev)) return;

	PortableServer_POA_destroy (poa, TRUE, FALSE, ev);
	if (etk_raised_exception(ev)) return;

	CORBA_free (objid);

        CORBA_Object_release ((CORBA_Object) poa, ev);
	if (etk_raised_exception(ev)) return;
	
        CORBA_Object_release (ref, ev);
	if (etk_raised_exception(ev)) return;

        /* ORB: tear down the ORB */
        if (orb != CORBA_OBJECT_NIL)
        {
                /* going to destroy orb.. */
                CORBA_ORB_destroy(orb, ev);
		if (etk_raised_exception(ev)) return;
        }
}

/* Creates servant and registers in context of ORB @orb. The ORB will
 * delegate incoming requests to specific servant object.  @return
 * object reference. If error occures @ev points to exception object
 * on return.
 */
static CORBA_Object
server_activate_service (CORBA_ORB           orb,
			 PortableServer_POA  poa,
			 CORBA_Environment  *ev)
{
	Examples_Factory_Producer ref = CORBA_OBJECT_NIL; 

	ref = impl_Examples_Factory_Producer__create (poa, ev);
	if (etk_raised_exception(ev)) 
		return CORBA_OBJECT_NIL;
	
	return ref;
}

/* 
 * main 
 */

int
main (int argc, char *argv[])
{
	CORBA_Object servant = CORBA_OBJECT_NIL;
	
	CORBA_char filename[] = "factory.ref";

	CORBA_Environment  ev[1];
	CORBA_exception_init(ev);
	
	server_init (&argc, argv, &global_orb, &root_poa, ev);
	etk_abort_if_exception(ev, "failed ORB init");

	servant = server_activate_service (global_orb, root_poa, ev);
	etk_abort_if_exception(ev, "failed activating service");

	g_print ("Writing service reference to: %s\n\n", filename);

	etk_export_object_to_file (global_orb, 
				   servant, 
				   filename, 
				   ev);
	etk_abort_if_exception(ev, "failed exporting IOR");
	
	server_run (global_orb, ev);
	etk_abort_if_exception(ev, "failed entering main loop");

	server_cleanup (global_orb, root_poa, servant, ev);
	etk_abort_if_exception(ev, "failed cleanup");

	exit (0);
}

Example 5-43. factory-skelimpl.c

/*
 * This is a template file generated by command 
 * orbit-idl-2 --skeleton-impl name-resolve.idl 
 * User must edit this file, inserting servant 
 * specific code between markers. 
 */

#include "factory.h"

/*** App-specific servant structures ***/

typedef struct
{
  POA_Examples_Factory_AbstractService servant;
  PortableServer_POA poa;

  /* ------ add private attributes here ------  */
  CORBA_char *id;
  CORBA_long counter;
  /* ------ ---------- end ------------ ------  */
} impl_POA_Examples_Factory_AbstractService;

typedef struct
{
  POA_Examples_Factory_Producer servant;
  PortableServer_POA poa;

  /* ------ add private attributes here ------ */
  /* ------ ---------- end ------------ ------ */
} impl_POA_Examples_Factory_Producer;

/*** Implementation stub prototypes ***/

static void
  impl_Examples_Factory_AbstractService__fini
  (impl_POA_Examples_Factory_AbstractService * servant,
   CORBA_Environment * ev);
static void
  impl_Examples_Factory_AbstractService_doit
  (impl_POA_Examples_Factory_AbstractService * servant,
   const CORBA_char * mesg, CORBA_Environment * ev);

static void
  impl_Examples_Factory_AbstractService_destroy
  (impl_POA_Examples_Factory_AbstractService * servant,
   CORBA_Environment * ev);

static void
  impl_Examples_Factory_Producer__fini
  (impl_POA_Examples_Factory_Producer * servant, CORBA_Environment * ev);
static Examples_Factory_AbstractService
  impl_Examples_Factory_Producer_produce
  (impl_POA_Examples_Factory_Producer * servant, const CORBA_char * id,
   CORBA_Environment * ev);

/*** epv structures ***/

static PortableServer_ServantBase__epv
  impl_Examples_Factory_AbstractService_base_epv = {
  NULL,				/* _private data */
  (gpointer) & impl_Examples_Factory_AbstractService__fini,	/* finalize routine */
  NULL,				/* default_POA routine */
};
static POA_Examples_Factory_AbstractService__epv
  impl_Examples_Factory_AbstractService_epv = {
  NULL,				/* _private */
  (gpointer) & impl_Examples_Factory_AbstractService_doit,

  (gpointer) & impl_Examples_Factory_AbstractService_destroy,

};
static PortableServer_ServantBase__epv
  impl_Examples_Factory_Producer_base_epv = {
  NULL,				/* _private data */
  (gpointer) & impl_Examples_Factory_Producer__fini,	/* finalize routine */
  NULL,				/* default_POA routine */
};
static POA_Examples_Factory_Producer__epv impl_Examples_Factory_Producer_epv = {
  NULL,				/* _private */
  (gpointer) & impl_Examples_Factory_Producer_produce,

};

/*** vepv structures ***/

static POA_Examples_Factory_AbstractService__vepv
  impl_Examples_Factory_AbstractService_vepv = {
  &impl_Examples_Factory_AbstractService_base_epv,
  &impl_Examples_Factory_AbstractService_epv,
};
static POA_Examples_Factory_Producer__vepv
  impl_Examples_Factory_Producer_vepv = {
  &impl_Examples_Factory_Producer_base_epv,
  &impl_Examples_Factory_Producer_epv,
};

/*** Stub implementations ***/

static Examples_Factory_AbstractService
impl_Examples_Factory_AbstractService__create (PortableServer_POA poa,
					       const CORBA_char * id,
					       CORBA_Environment * ev)
{
  Examples_Factory_AbstractService retval;
  impl_POA_Examples_Factory_AbstractService *newservant;
  PortableServer_ObjectId *objid;

  newservant = g_new0 (impl_POA_Examples_Factory_AbstractService, 1);
  newservant->servant.vepv = &impl_Examples_Factory_AbstractService_vepv;
  newservant->poa =
    (PortableServer_POA) CORBA_Object_duplicate ((CORBA_Object) poa, ev);
  POA_Examples_Factory_AbstractService__init ((PortableServer_Servant)
					      newservant, ev);
  /*
   * Before servant is going to be activated all private attributes must 
   * be initialized.  
   */

  /* ------ init private attributes here ------ */
  newservant->id = CORBA_string_dup (id);
  newservant->counter = 0;
  /* ------ ---------- end ------------- ------ */

  objid = PortableServer_POA_activate_object (poa, newservant, ev);
  CORBA_free (objid);
  retval = PortableServer_POA_servant_to_reference (poa, newservant, ev);

  return retval;
}

/**
 * impl_Exampels_Factory_AbstractService__fini
 * 
 * Destructor called after servant has been deactivated finally.
 * In case any operation invocation, method invoation is being delayed.
 * Note, in former versions of ORBit2 this function would have been 
 * named impl_Exampels_Factory_AbstractService__destroy.
**/
static void
  impl_Examples_Factory_AbstractService__fini
  (impl_POA_Examples_Factory_AbstractService * servant,
   CORBA_Environment * ev)
{
  CORBA_Object_release ((CORBA_Object) servant->poa, ev);

  /*
   * No further remote method calls are delegated to servant and you
   * may free your private attributes. 
   */
  /* ------ free private attributes here ------  */
  CORBA_free (servant->id);
  /* ------ ---------- end ------------- ------  */

  POA_Examples_Factory_AbstractService__fini ((PortableServer_Servant)
					      servant, ev);

  g_free (servant);
}

static void
  impl_Examples_Factory_AbstractService_doit
  (impl_POA_Examples_Factory_AbstractService * servant,
   const CORBA_char * mesg, CORBA_Environment * ev)
{
  /* ------ insert method code here ------ */
  g_print ("service-id=\"%s\", nth-call=\"%d\", \n", 
	   servant->id, 
	   servant->counter);
  ++(servant->counter);
  /* ------ ---------- end ------------ ------  */
}


static void
deactivate_servant (PortableServer_POA poa,
		    PortableServer_Servant servant, CORBA_Environment * ev)
{
  PortableServer_ObjectId *id
    = PortableServer_POA_servant_to_id (poa, servant, ev);

  if (etk_raised_exception (ev))
    return;

  PortableServer_POA_deactivate_object (poa, id, ev);

  /* free id in any case  */
  g_free (id);
}

static void
  impl_Examples_Factory_AbstractService_destroy
  (impl_POA_Examples_Factory_AbstractService * servant,
   CORBA_Environment * ev)
{
  /* ------ insert method code here ------ */
  deactivate_servant (servant->poa, servant, ev);
  /* ------ ---------- end ------------ ------ */
}

static Examples_Factory_Producer
impl_Examples_Factory_Producer__create (PortableServer_POA poa,
					CORBA_Environment * ev)
{
  Examples_Factory_Producer retval;
  impl_POA_Examples_Factory_Producer *newservant;
  PortableServer_ObjectId *objid;

  newservant = g_new0 (impl_POA_Examples_Factory_Producer, 1);
  newservant->servant.vepv = &impl_Examples_Factory_Producer_vepv;
  newservant->poa =
    (PortableServer_POA) CORBA_Object_duplicate ((CORBA_Object) poa, ev);
  POA_Examples_Factory_Producer__init ((PortableServer_Servant)
				       newservant, ev);
  /*
   * Before servant is going to be activated all private attributes must 
   * be initialized.  
   */

  /* ------ init private attributes here ------ */ 
  /* ------ ---------- end ------------- ------ */

  objid = PortableServer_POA_activate_object (poa, newservant, ev);
  CORBA_free (objid);
  retval = PortableServer_POA_servant_to_reference (poa, newservant, ev);

  return retval;
}

/**
 * impl_Examples_Factory_Producer__fini
 * 
 * Destructor called after servant has been deactivated finally.
 * In case any operation invocation, method invoation is being delayed.
 * Note, in former versions of ORBit2 this function would have been 
 * named impl_Exampels_Factory_Producer__destroy
**/
static void
  impl_Examples_Factory_Producer__fini
  (impl_POA_Examples_Factory_Producer * servant, CORBA_Environment * ev)
{
  CORBA_Object_release ((CORBA_Object) servant->poa, ev);

  /*
   * No further remote method calls are delegated to servant and you
   * may free your private attributes. 
   */ 
  /* ------ free private attributes here ------  */
  /* ------ ---------- end ------------- ------ */

  POA_Examples_Factory_Producer__fini ((PortableServer_Servant) servant, ev);

  g_free (servant);
}

static Examples_Factory_AbstractService
  impl_Examples_Factory_Producer_produce
  (impl_POA_Examples_Factory_Producer * servant, const CORBA_char * id,
   CORBA_Environment * ev)
{
  Examples_Factory_AbstractService retval;

  /* ------ insert method code here ------ */
  retval =
    impl_Examples_Factory_AbstractService__create (servant->poa, id, ev);
  if (etk_raised_exception (ev))
    {
      retval = CORBA_OBJECT_NIL;
    }
  /* ------ ---------- end ------------ ------  */

  return retval;
}

5.9.3. Compiling client & server

Example 5-44. Makefile

PREFIX ?= /usr
CC = gcc
TARGETS=factory-client factory-server
ORBIT_IDL=$(PREFIX)/bin/orbit-idl-2
CFLAGS=-g -DORBIT2=1 -D_REENTRANT -I$(PREFIX)/include/orbit-2.0 \
         -I$(PREFIX)/include/linc-1.0 -I$(PREFIX)/include/glib-2.0 \
         -I$(PREFIX)/lib/glib-2.0/include 
LDFLAGS= -Wl,--export-dynamic  -L$(PREFIX)/lib -lORBitCosNaming-2 -lORBit-2 -llinc -lgmodule-2.0 \
             -ldl -lgobject-2.0 -lgthread-2.0 -lpthread -lglib-2.0 -lm
IDLOUT=factory-common.c factory-stubs.c factory-skels.c factory.h

all: $(IDLOUT) factory-client factory-server

factory-server.o: factory-server.c factory-skelimpl.c

factory-client : factory-client.o factory-stubs.o factory-common.o examples-toolkit.o
factory-server : factory-server.o factory-skels.o factory-common.o examples-toolkit.o

$(IDLOUT): factory.idl
	$(ORBIT_IDL) factory.idl

%-skelimpl.c: %.idl
	$(ORBIT_IDL) --skeleton-impl $^

clean:
	rm -rf *.o *~ $(IDLOUT) *.ior *.ref

distclean: clean
	rm -rf factory-client factory-server