ORBit2 and DSI



Hi, 
	i'm playing around with handling corba requests in a C server
without generating skeletons. the way outlined in the standard docs
(chapter 8 of the corba spec and 1.27 of the C mapping) do not appear
to be directly supported.  
	so several questions: 
	1. am i missing an easier way of doing this?
	2. is there anything helpful in libIDL i should look at for
		building TC structures procedurally
	3. any general comments on supporting DSI or the example below?
		(it seems like it will be fairly trivial to 
		 build the ServerRequest object)
		

	thanks, 
	rob

here's a crude example client/server that i'm developing (using orbit
2.6):

::::::::::::::
test-server.c
::::::::::::::
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t;c-basic-offset: 4 -*- */
#include "dsi.h"



void
invoke_handler(PortableServer_Servant * _o_servant,
                           gpointer _o_retval,
                           gpointer * _o_args,
                           CORBA_Context _o_ctx,
                           CORBA_Environment * _o_ev,
                           char * name)
{
        static int flag = 0; 
        if (strcmp(name, "shutdown")==0) { 
                exit_main();
        } else if (strcmp(name, "release") == 0) { 
                exit_main();
        } else if (strcmp(name, "get_flag") == 0) { 
                *(int *)_o_retval = flag;
        } else if (strcmp(name, "set_flag") == 0) { 
                flag = *(int*)_o_args[0];
        }
                
}



PortableServer_Servant *
dsi_poa_init(CORBA_Environment * env)
{
        ORBit_IInterface * iface;
        PortableServer_Servant * servant;
        static PortableServer_ClassInfo * class_info = NULL;
        static int first_time = 1; 

        servant = dsi_default_init(&class_info,
                                   "DSI", "IDL:POA/DSII:1.0",
                                   invoke_handler, 4, 
                                   env);
        /* turns out we can set these ok after registering the class */
        if (first_time) {
                iface = class_info->idata;
                imethod_set(iface, 0, "shutdown", TC_void, 0);
                imethod_set(iface, 1, "release", TC_void, 0);
                imethod_set(iface, 2, "set_flag", TC_void, 1);
                imethod_arg_set(iface, 2, 0,  
                                TC_CORBA_long, 
                                ORBit_I_ARG_IN | ORBit_I_COMMON_FIXED_SIZE, 
                                "value");
                imethod_set(iface, 3, "get_flag", TC_CORBA_long, 0);
                first_time = 0; 
        }
        return servant;
}


int
main(int argc, char ** argv)
{
        CORBA_Environment ev;   
        PortableServer_Servant * servant;

        orb_init(argc, argv, &ev);

        servant = dsi_poa_init(&ev);    
        write_ior_to_file(servant, "ior", &ev);

        run();
        return 0;
}

::::::::::::::
client-test.py
::::::::::::::
#!/usr/bin/python


import ORBit
import CORBA



if __name__ == "__main__":
    print "Starting up..."
    orb = CORBA.ORB_init()
    ior = open("ior").readline()
    obj = orb.string_to_object(ior)
    print obj
    names = dir(obj)
    # just get the non-hidden names in the object
    print filter(lambda x: x[0] != '_', names)

    val = -1
    while (val < 100):
            val = obj.get_flag()
            print "flag was "+str(val)
            obj.set_flag(val+1)
    # end while
    obj.shutdown()
# end if
::::::::::::::
dsi.h
::::::::::::::

#ifndef __DSI_H__
#define __DSI_H__

#define ORBIT2_STUBS_API
#include <stdlib.h>
#include <orbit/orbit.h>


#include "util.h"

PortableServer_Servant *
servant_struct_alloc(int num_methods, 
                     int additional_base_classes,
                     int sizeof_servant_extra_data);

// repo id must be the same in both of these 
PortableServer_ClassInfo * class_info_construct(void * get_skeleton_func, 
                                                char * repo_id, 
                                                ORBit_IInterface * iiface);
PortableServer_ClassInfo *
class_info_construct_with_default_get_skel(void * impl_fun, 
                                           char * class_name, 
                                           ORBit_IInterface * iiface);
struct CORBA_TypeCode_struct * typecode_construct(char * name, char * repo_id);

ORBit_IInterface *
iinterface_alloc(struct CORBA_TypeCode_struct * tc, 
                 int num_funcs, 
                 int num_base_interfaces);  


void imethod_set(ORBit_IInterface * iiface, int index, 
                 char * name, CORBA_TypeCode return_tc, int args);
void
base_interface_set(ORBit_IInterface * iiface, int index, 
                   char * base_interface_id);

void
dsi_init(PortableServer_ClassInfo * class_info,
         PortableServer_Servant * servant, 
         CORBA_Environment * env);

void
imethod_arg_set(ORBit_IInterface * iiface, 
                int method_index, 
                int arg_index,
                CORBA_TypeCode arg_tc, 
                ORBit_IArgFlag flags,
                char * name);

PortableServer_Servant *
dsi_default_init(PortableServer_ClassInfo ** io_class_info,
                 char * name,
                 char * repos_id,
                 void * invoke_handler, 
                 int number_functions,
                 CORBA_Environment * env);


#endif
::::::::::::::
dsi.c
::::::::::::::
#include "dsi.h"


void
imethod_set(ORBit_IInterface * iiface, int index, 
            char * name, CORBA_TypeCode return_tc, int args)
{
  iiface->methods._buffer[index].name = CORBA_string_dup(name);
  iiface->methods._buffer[index].name_len = strlen(name);
  iiface->methods._buffer[index].ret = return_tc;
  iiface->methods._buffer[index].flags = 0; 

  iiface->methods._buffer[index].arguments._length = args;
  iiface->methods._buffer[index].arguments._maximum = args;
  iiface->methods._buffer[index].arguments._release = FALSE;
  iiface->methods._buffer[index].arguments._buffer = 
    calloc(1, sizeof(ORBit_IArg)*args);
}


void
imethod_arg_set(ORBit_IInterface * iiface, 
                int method_index, 
                int arg_index,
                CORBA_TypeCode arg_tc, 
                ORBit_IArgFlag flags,
                char * name)
{
  ORBit_IArg * iargs = 
    iiface->methods._buffer[method_index].arguments._buffer;
  iargs[arg_index].tc = arg_tc; 
  iargs[arg_index].flags = flags; 
  iargs[arg_index].name = (char *)strdup(name);
}


void
base_interface_set(ORBit_IInterface * iiface, int index, 
                  char * base_interface_id)
{
  iiface->base_interfaces._buffer[index] = 
    (char*)strdup(base_interface_id);
}


/*  
 * num_methods - the number of methods the object has
 * addition_base_classes - the number of classes 
 *                   (not including CORBA::Object)
 *                   the object inherits from 
 *                   (through the whole hierarchy???)
 *                   makes more room in the vepv for manually 
 *                   putting more epv's in it
 * sizeof_servant_extra_data - the amount of memory to be allocated 
 *        in addition to the amount for a _private variable and the 
 *        pointer to the vepv in the returned servant for app specific
 *        stuff
 */
PortableServer_Servant *
servant_struct_alloc(int num_methods, 
                     int additional_base_classes,
                     int sizeof_servant_extra_data)
{
  PortableServer_ServantBase__epv * servant_base_epv;
  void ** servant;
  void ** epv; 
  void ** vepv;

  servant_base_epv = calloc(1, sizeof(PortableServer_ServantBase__epv));

  /* 
   * the epv has to hold the _private data
   * and function pointers for methods
   */
  epv = calloc(1, sizeof(void *)*(1+num_methods));
  vepv = calloc(1, sizeof(void *)*(2+additional_base_classes));
  servant = calloc(1, 2* sizeof(void *)+sizeof_servant_extra_data);
  
  vepv[0] = servant_base_epv; 

  /* the derived class should be the last in the epv */
  vepv[1+additional_base_classes] = epv; 
        
  servant[0] = NULL;
  servant[1] = vepv;
  
  return servant;
}

ORBit_IInterface *
iinterface_alloc(struct CORBA_TypeCode_struct * tc, 
                 int num_funcs, 
                 int num_base_interfaces) 
{
  ORBit_IInterface * iiface; 

  iiface = calloc(1, sizeof(ORBit_IInterface));
  iiface->tc = tc; 
  iiface->methods._length = 
    iiface->methods._maximum = num_funcs;
  iiface->methods._release = FALSE; 
  iiface->base_interfaces._length = 
    iiface->base_interfaces._maximum = num_base_interfaces;
  iiface->base_interfaces._release = FALSE; 

  iiface->methods._buffer = calloc(1, sizeof(ORBit_IMethod)*num_funcs);
  iiface->base_interfaces._buffer = 
    calloc(1, sizeof(char *)*num_base_interfaces);
  return iiface;
}

/* 
 * this function is to 
 * build a tc for an interface only
 * (not union etc)
 */

struct CORBA_TypeCode_struct *
typecode_construct(char * name, char * repo_id)
{
  struct CORBA_TypeCode_struct * tc; 
  struct ORBit_RootObject_struct parent={ &ORBit_TypeCode_epv, 
                                          ORBIT_REFCOUNT_STATIC}; 
  tc = calloc(1, sizeof(struct CORBA_TypeCode_struct));
  memcpy(&tc->parent, &parent, sizeof(struct ORBit_RootObject_struct));
  tc->kind = CORBA_tk_objref;
  tc->c_align = ORBIT_ALIGNOF_CORBA_POINTER;
  tc->discriminator = CORBA_OBJECT_NIL;
  tc->name = (char *)strdup(name);
  tc->repo_id = (char *)strdup(repo_id);
  tc->default_index = -1;
  return tc;
  
}

/* add our own data that we need */
typedef struct
{
  PortableServer_ClassInfo info;
  void * impl_fun;
} Extended_PortableServer_ClassInfo;

static ORBitSmallSkeleton
get_skel_small_default(PortableServer_Servant * servant,
                       const char * opname, 
                       gpointer * m_data,
                       gpointer * impl)
{
  PortableServer_ClassInfo * info = ORBIT_SERVANT_TO_CLASSINFO(servant);
  Extended_PortableServer_ClassInfo * einfo = 
    (Extended_PortableServer_ClassInfo *)info; 

  int i, n; 
  ORBit_IInterface * iface;
  if (strncmp("ORBit", opname, 5) == 0) {
    return NULL;
  };

  iface = info->idata;
  n = iface->methods._length; 
  for (i = 0; i < n; i++) { 
    if (strcmp(iface->methods._buffer[i].name, opname) == 0) { 
      *m_data = &iface->methods._buffer[i];
      *impl = iface->methods._buffer[i].name;
      return (ORBitSmallSkeleton)einfo->impl_fun;
    }
  }
  return NULL;
}



PortableServer_ClassInfo *
class_info_construct(void * get_skeleton_func, 
                     char * class_name, 
                     ORBit_IInterface * iiface)
{
  PortableServer_ClassInfo * info; 
  info = calloc(1, sizeof(Extended_PortableServer_ClassInfo));
  info->class_id = calloc(1, sizeof(CORBA_unsigned_long));
  info->small_relay_call = get_skeleton_func;
  info->class_name = (const char *)strdup(class_name);
  info->idata = iiface;
  return info;
}

PortableServer_ClassInfo *
class_info_construct_with_default_get_skel(void * impl_fun, 
                                           char * class_name, 
                                           ORBit_IInterface * iiface)

{
  Extended_PortableServer_ClassInfo * info; 
  info = (Extended_PortableServer_ClassInfo *)
    class_info_construct(get_skel_small_default, 
                         class_name, 
                         iiface);
  info->impl_fun = impl_fun;
}

void
dsi_init(PortableServer_ClassInfo * class_info,
         PortableServer_Servant * servant, 
         CORBA_Environment * env)
{

  int classid;
  /* custom final stuff ? */ 
  
  if (((PortableServer_ServantBase *) servant)->vepv[0]->finalize == 0) {
    ((PortableServer_ServantBase *) servant)->vepv[0]->finalize =
      PortableServer_ServantBase__fini;
  }

  PortableServer_ServantBase__init(((PortableServer_ServantBase *)
                                    servant), 
                                   env);
  
  ORBit_classinfo_register(class_info);
  ORBIT_SERVANT_SET_CLASSINFO(servant, class_info);
  
  classid = *class_info->class_id; 


  if (!class_info->vepvmap) {
    class_info->vepvmap = g_new0(ORBit_VepvIdx, classid + 1);
    /* the number of base class epv's there are in the vepv??? */
    class_info->vepvmap[classid] = class_info->idata->methods._length;
  }
}


/*
 * class_info is in/out param
 *        if it's NULL, then a new class info will be generated 
 *                      and returned in it
 *        if it's non-null, it is used and a new class_info is not 
 *                      generated
 *
 */
PortableServer_Servant *
dsi_default_init(PortableServer_ClassInfo ** io_class_info,
                 char * name,
                 char * repos_id,
                 void * invoke_handler, 
                 int number_functions,
                 CORBA_Environment * env)
{
  ORBit_IInterface * iface;
  PortableServer_Servant * servant;
  PortableServer_ClassInfo * class_info;
  struct CORBA_TypeCode_struct * tc;
  
  class_info = *io_class_info; 

  servant =  servant_struct_alloc(number_functions, 0, 0);
  if (class_info == NULL) { 
    tc = typecode_construct(name, repos_id);
    iface = iinterface_alloc(tc, number_functions, 1);  
    class_info = 
      class_info_construct_with_default_get_skel(invoke_handler, 
                                                 repos_id, 
                                                 iface);
    base_interface_set(iface, 0, "IDL:omg.org/CORBA/Object:1.0");
    
  }
  
  dsi_init(class_info, servant, env);
  
  *io_class_info = class_info;
  return servant;
}


::::::::::::::
util.h
::::::::::::::
#ifndef __UTIL_H__
#define __UTIL_H__

#include "dsi.h"

CORBA_ORB            get_orb(void);
PortableServer_POA   get_poa(void);
void                 orb_init(int argc, 
                              char ** argv, 
                              CORBA_Environment * ev);
void                 write_ior_to_file(PortableServer_Servant * servant,
                                       char * path, 
                                       CORBA_Environment * ev);
void                 exit_main(void);
void                 run(void);


#endif
::::::::::::::
util.c
::::::::::::::
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t;c-basic-offset: 4 -*- */


#include "util.h"

static CORBA_ORB orb;

CORBA_ORB 
get_orb(void)
{
  return orb;
}

PortableServer_POA
get_poa(void)
{
  static PortableServer_POA poa = CORBA_OBJECT_NIL;
  if (poa == CORBA_OBJECT_NIL) { 
    CORBA_Environment * ev;
    CORBA_ORB orb; 
    orb = get_orb();
    poa = (PortableServer_POA)
      CORBA_ORB_resolve_initial_references(orb, 
                                           "RootPOA", 
                                           ev);
  }
  return poa;
}

void 
orb_init(int argc, 
         char ** argv, 
         CORBA_Environment * ev) 
{ 

  PortableServer_POAManager mgr;
  PortableServer_POA        poa;
 
  CORBA_exception_init(ev);  
  orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", ev);
  poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(orb, 
                                                                 "RootPOA", 
                                                                 ev);

  mgr = PortableServer_POA__get_the_POAManager(poa, ev);
  PortableServer_POAManager_activate(mgr, ev);
  CORBA_Object_release((CORBA_Object)mgr, ev);

}

void 
write_ior_to_file(PortableServer_Servant * servant,
                  char * path, 
                  CORBA_Environment * ev)
{
  PortableServer_POA poa; 
  CORBA_Object object;
  CORBA_ORB orb;
  FILE * file;
  char * s;

  orb = get_orb();  
  poa = get_poa();
  
  PortableServer_POA_activate_object (poa, servant, ev);
  
  object = PortableServer_POA_servant_to_reference (poa, servant, ev);
  if (ev->_major != CORBA_NO_EXCEPTION) {
    g_error ("servant_to_reference failed: %d\n", ev->_major);
  }
  
  file = fopen(path, "w");
  s = CORBA_ORB_object_to_string (orb, object, ev);
  fprintf (file, "%s\n",s);
  CORBA_free(s); 
  fflush (file);
  fclose (file);
}


static int state = 0; 

void
quit_timer(GMainLoop * loop)
{
        printf("shutting down....\n");
        state = 2;
}

void
exit_main(void)
{
        if (state == 0) { 
                state = 1; 
        }
}


void
run(void)
{
        int first_quit = 1;
        GMainContext * ctxt;
        GMainLoop * loop;
        ctxt = g_main_context_default();
        loop = g_main_loop_new(ctxt, FALSE);
        while (state != 2) {
                if (state == 1 && first_quit) {
                        first_quit = 0; 
                        g_timeout_add(10, (void*)quit_timer, loop);
                }
                g_main_context_iteration(ctxt, TRUE);
        }
}
::::::::::::::
Makefile
::::::::::::::
CC=gcc -g
CFLAGS=`pkg-config --cflags ORBit-2.0`
LIBS=`pkg-config --libs ORBit-2.0`

all: test-server

test-server: test-server.o dsi.o util.o
	$(CC) -o $@ test-server.o dsi.o util.o $(LIBS)



test-server.o: 
.c.o: 
	$(CC) -c $< $(CFLAGS) 


clean:
	rm -rf *~
	rm -rf *.o
	rm -rf test-server ior



----
Robert Melby
Georgia Institute of Technology, Atlanta Georgia, 30332
uucp:     ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt4255a
Internet: async@cc.gatech.edu



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]