#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <orbit/orbit.h>
#include <orb-core-export.h>
#include <orbit-debug.h>
#include "../util/orbit-purify.h"
#include "../orb-core/orbit-debug.h"
#include "../GIOP/giop-debug.h"
#include "../GIOP/giop-recv-buffer.h"
#include "poa-macros.h"
#include "poa-private.h"
#include "orbit-poa.h"
#ifdef DEBUG_LOCKS
# define LOCK_DEBUG(a) g_printerr("%p: %6s file %s: line %d (%s)\n", \
poa, a, __FILE__, __LINE__, __PRETTY_FUNCTION__);
#else
# define LOCK_DEBUG(a)
#endif
#define POA_LOCK(poa) G_STMT_START { \
LOCK_DEBUG("lock") \
LINK_MUTEX_LOCK(poa->base.lock); \
} G_STMT_END
#define POA_UNLOCK(poa) G_STMT_START { \
LINK_MUTEX_UNLOCK(poa->base.lock); \
LOCK_DEBUG("unlock") \
} G_STMT_END
static GMutex *ORBit_class_assignment_lock = NULL;
static GHashTable *ORBit_class_assignments = NULL;
static guint ORBit_class_assignment_counter = 0;
static PortableServer_Servant ORBit_POA_ServantManager_use_servant(
PortableServer_POA poa,
ORBit_POAObject pobj,
CORBA_Identifier opname,
PortableServer_ServantLocator_Cookie *the_cookie,
PortableServer_ObjectId *oid,
CORBA_Environment *ev );
static void ORBit_POA_ServantManager_unuse_servant(
PortableServer_POA poa,
ORBit_POAObject pobj,
CORBA_Identifier opname,
PortableServer_ServantLocator_Cookie cookie,
PortableServer_ObjectId *oid,
PortableServer_Servant servant,
CORBA_Environment *ev );
static void ORBit_POA_handle_request (PortableServer_POA poa,
GIOPRecvBuffer *recv_buffer,
ORBit_ObjectKey *objkey);
static void ORBit_POAObject_invoke (ORBit_POAObject pobj,
gpointer ret,
gpointer *args,
CORBA_Context ctx,
gpointer data,
CORBA_Environment *ev);
static void ORBit_POAObject_handle_request (ORBit_POAObject pobj,
CORBA_Identifier opname,
gpointer ret,
gpointer *args,
CORBA_Context ctx,
GIOPRecvBuffer *recv_buffer,
CORBA_Environment *ev);
static void ORBit_POA_deactivate_object_T (PortableServer_POA poa,
ORBit_POAObject pobj,
CORBA_boolean do_etherealize,
CORBA_boolean is_cleanup);
static CORBA_Object
ORBit_POA_obj_to_ref (PortableServer_POA poa,
ORBit_POAObject pobj,
const CORBA_char *intf,
CORBA_Environment *ev);
static void
ORBit_POA_invocation_stack_push (PortableServer_POA poa,
ORBit_POAObject pobj)
{
LINK_MUTEX_LOCK (poa->orb->lock);
poa->orb->current_invocations =
g_slist_prepend (poa->orb->current_invocations, pobj);
LINK_MUTEX_UNLOCK (poa->orb->lock);
}
static void
ORBit_POA_invocation_stack_pop (PortableServer_POA poa,
ORBit_POAObject pobj)
{
/* FIXME, we know it is the top element to be removed */
LINK_MUTEX_LOCK (poa->orb->lock);
poa->orb->current_invocations =
g_slist_remove (poa->orb->current_invocations, pobj);
LINK_MUTEX_UNLOCK (poa->orb->lock);
}
static PortableServer_ObjectId*
ORBit_POA_invocation_stack_lookup_objid (PortableServer_POA poa,
PortableServer_ServantBase *servant)
{
PortableServer_ObjectId *objid = NULL;
GSList *l;
LINK_MUTEX_LOCK (poa->orb->lock);
for (l = poa->orb->current_invocations; l; l = l->next) {
ORBit_POAObject pobj = l->data;
if (pobj->servant == servant)
objid = ORBit_sequence_CORBA_octet_dup (pobj->object_id);
}
LINK_MUTEX_UNLOCK (poa->orb->lock);
return objid;
}
static CORBA_Object
ORBit_POA_invocation_stack_lookup_objref (PortableServer_POA poa,
PortableServer_ServantBase *servant)
{
CORBA_Object result = CORBA_OBJECT_NIL;
GSList *l;
LINK_MUTEX_LOCK (poa->orb->lock);
for (l = poa->orb->current_invocations; l; l = l->next) {
ORBit_POAObject pobj = l->data;
if (pobj->servant == servant)
result = ORBit_POA_obj_to_ref (poa, pobj, NULL, NULL);
}
LINK_MUTEX_UNLOCK (poa->orb->lock);
return result;
}
/* FIXME, I would prefer if argument would be of type PortableServer_POA */
static ORBit_POAObject
ORBit_POA_invocation_stack_peek (CORBA_ORB orb)
{
ORBit_POAObject pobj = CORBA_OBJECT_NIL;
LINK_MUTEX_LOCK (orb->lock);
if (orb->current_invocations == NULL)
pobj = CORBA_OBJECT_NIL;
else
pobj = (ORBit_POAObject) orb->current_invocations->data;
LINK_MUTEX_UNLOCK (orb->lock);
return pobj;
}
/* PortableServer_Current interface */
static void
ORBit_POACurrent_free_fn (ORBit_RootObject obj_in)
{
PortableServer_Current poacur = (PortableServer_Current) obj_in;
ORBit_RootObject_release_T (poacur->orb);
poacur->orb = NULL;
p_free (poacur, struct PortableServer_Current_type);
}
static const ORBit_RootObject_Interface ORBit_POACurrent_epv = {
ORBIT_ROT_POACURRENT,
ORBit_POACurrent_free_fn
};
PortableServer_Current
ORBit_POACurrent_new (CORBA_ORB orb)
{
PortableServer_Current poacur;
poacur = (PortableServer_Current)
g_new0 (struct PortableServer_Current_type, 1);
ORBit_RootObject_init (&poacur->parent, &ORBit_POACurrent_epv);
poacur->orb = ORBit_RootObject_duplicate (orb);
return ORBit_RootObject_duplicate (poacur);
}
static ORBit_POAObject
ORBit_POACurrent_get_object (PortableServer_Current obj,
CORBA_Environment *ev)
{
ORBit_POAObject pobj = CORBA_OBJECT_NIL;
g_assert (obj && obj->parent.interface->type == ORBIT_ROT_POACURRENT);
if ( ! (pobj = ORBit_POA_invocation_stack_peek (obj->orb)))
CORBA_exception_set_system
(ev, ex_PortableServer_Current_NoContext,
CORBA_COMPLETED_NO);
return pobj;
}
PortableServer_ClassInfo *
ORBit_classinfo_lookup (const char *type_id)
{
PortableServer_ClassInfo *ci = NULL;
LINK_MUTEX_LOCK (ORBit_class_assignment_lock);
if (ORBit_class_assignments)
ci = g_hash_table_lookup (ORBit_class_assignments, type_id);
LINK_MUTEX_UNLOCK (ORBit_class_assignment_lock);
return ci;
}
/* Deprecated & not thread-safe */
void
ORBit_classinfo_register (PortableServer_ClassInfo *ci)
{
if (*(ci->class_id) != 0)
return; /* already registered! */
/* This needs to be pre-increment - we don't want to give out
* classid 0, because (a) that is reserved for the base Object class
* (b) all the routines allocate a new id if the variable
* storing their ID == 0
*/
*(ci->class_id) = ++ORBit_class_assignment_counter;
if (!ORBit_class_assignments)
ORBit_class_assignments = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (ORBit_class_assignments,
(gpointer) ci->class_name, ci);
}
#define VEPV_CACHE_SIZE(c) (c)[0]
void
ORBit_skel_class_register (PortableServer_ClassInfo *ci,
PortableServer_ServantBase *servant,
void (*opt_finalize) (PortableServer_Servant,
CORBA_Environment *),
CORBA_unsigned_long class_offset,
CORBA_unsigned_long first_parent_id,
...)
{
va_list args;
CORBA_unsigned_long id;
va_start (args, first_parent_id);
/*
* FIXME: a double check/lock/write barrier pattern
* would be far faster here.
*/
LINK_MUTEX_LOCK (ORBit_class_assignment_lock);
ORBit_classinfo_register (ci);
if (!ci->vepvmap) {
CORBA_unsigned_long offset;
CORBA_unsigned_long epvmap_size;
epvmap_size = *(ci->class_id) + 1;
ci->vepvmap = g_new0 (ORBit_VepvIdx, epvmap_size);
VEPV_CACHE_SIZE(ci->vepvmap) = epvmap_size;
ci->vepvmap[*(ci->class_id)] = class_offset;
for (id = first_parent_id; id;) {
offset = va_arg (args, CORBA_unsigned_long);
g_assert (id <= *(ci->class_id));
ci->vepvmap [id] = offset;
id = va_arg (args, CORBA_unsigned_long);
}
}
LINK_MUTEX_UNLOCK (ORBit_class_assignment_lock);
if (!servant->vepv[0]->finalize)
servant->vepv[0]->finalize = opt_finalize;
ORBIT_SERVANT_SET_CLASSINFO (servant, ci);
va_end (args);
}
static void
check_child_poa_inuse_T (char *name,
PortableServer_POA poa,
gboolean *is_inuse)
{
if (ORBit_POA_is_inuse (poa, CORBA_TRUE, NULL))
*is_inuse = TRUE;
}
static void
check_object_inuse_T (PortableServer_ObjectId *oid,
ORBit_POAObject pobj,
gboolean *is_inuse)
{
if (pobj->use_cnt > 0)
*is_inuse = TRUE;
}
static gboolean
ORBit_POA_is_inuse_T (PortableServer_POA poa,
CORBA_boolean consider_children,
CORBA_Environment *ev)
{
gboolean is_inuse = FALSE;
if (poa->use_cnt > 0)
return TRUE;
if (consider_children && poa->child_poas)
g_hash_table_foreach (poa->child_poas,
(GHFunc) check_child_poa_inuse_T,
&is_inuse);
if (!is_inuse && poa->oid_to_obj_map)
g_hash_table_foreach (poa->oid_to_obj_map,
(GHFunc) check_object_inuse_T,
&is_inuse);
return is_inuse;
}
gboolean
ORBit_POA_is_inuse (PortableServer_POA poa,
CORBA_boolean consider_children,
CORBA_Environment *ev)
{
gboolean inuse;
POA_LOCK (poa);
inuse = ORBit_POA_is_inuse_T (poa, consider_children, ev);
POA_UNLOCK (poa);
return inuse;
}
static PortableServer_ObjectId *
ORBit_POA_new_system_objid_T (PortableServer_POA poa)
{
PortableServer_ObjectId *objid;
g_assert (IS_SYSTEM_ID (poa));
objid = PortableServer_ObjectId__alloc ();
objid->_length = objid->_maximum = sizeof (CORBA_long) + ORBIT_OBJECT_ID_LEN;
objid->_buffer = PortableServer_ObjectId_allocbuf (objid->_length);
objid->_release = CORBA_TRUE;
ORBit_genuid_buffer (objid->_buffer + sizeof (CORBA_long),
ORBIT_OBJECT_ID_LEN, ORBIT_GENUID_OBJECT_ID);
*((CORBA_long *) objid->_buffer) = ++(poa->next_sysid);
return objid;
}
static ORBit_ObjectKey*
ORBit_POAObject_object_to_objkey (ORBit_POAObject pobj)
{
ORBit_ObjectAdaptor adaptor;
ORBit_ObjectKey *objkey;
guchar *mem;
g_return_val_if_fail (pobj != NULL, NULL);
adaptor = (ORBit_ObjectAdaptor) pobj->poa;
objkey = CORBA_sequence_CORBA_octet__alloc ();
objkey->_length = adaptor->adaptor_key._length + pobj->object_id->_length;
objkey->_maximum = objkey->_length;
objkey->_buffer = CORBA_sequence_CORBA_octet_allocbuf (objkey->_length);
objkey->_release = CORBA_TRUE;
mem = (guchar *) objkey->_buffer;
memcpy (mem, adaptor->adaptor_key._buffer, adaptor->adaptor_key._length);
mem += adaptor->adaptor_key._length;
memcpy (mem, pobj->object_id->_buffer, pobj->object_id->_length);
return objkey;
}
static ORBit_POAObject
ORBit_POA_object_id_lookup_T (PortableServer_POA poa,
const PortableServer_ObjectId *oid)
{
/* FIXME: needs some locking action */
return ORBit_RootObject_duplicate (
g_hash_table_lookup (poa->oid_to_obj_map, oid));
}
static void
ORBit_POA_set_life (PortableServer_POA poa,
CORBA_boolean etherealize_objects,
int action_do)
{
if ((poa->life_flags &
(ORBit_LifeF_DeactivateDo |
ORBit_LifeF_DestroyDo)) == 0) {
if (etherealize_objects)
poa->life_flags |= ORBit_LifeF_DoEtherealize;
}
poa->life_flags |= action_do;
}
static void
ORBit_POA_add_child (PortableServer_POA poa,
PortableServer_POA child)
{
if (!child)
return;
child->parent_poa = ORBit_RootObject_duplicate (poa);
g_hash_table_insert (poa->child_poas, child->name, child);
}
static void
ORBit_POA_remove_child (PortableServer_POA poa,
PortableServer_POA child_poa)
{
if (!child_poa->parent_poa)
return;
g_assert (child_poa->parent_poa == poa);
g_hash_table_remove (poa->child_poas, child_poa->name);
child_poa->parent_poa = NULL;
ORBit_RootObject_release (poa);
}
static gboolean
ORBit_POA_destroy_T_R (PortableServer_POA poa,
CORBA_boolean etherealize_objects,
CORBA_Environment *ev)
{
GPtrArray *adaptors;
int numobjs;
int i;
ORBit_POA_set_life (poa, etherealize_objects, ORBit_LifeF_DestroyDo);
if (poa->life_flags & ORBit_LifeF_Destroyed)
return TRUE; /* already did it */
if (poa->life_flags & (ORBit_LifeF_Deactivating|ORBit_LifeF_Destroying))
return FALSE; /* recursion */
poa->life_flags |= ORBit_LifeF_Destroying;
adaptors = poa->orb->adaptors;
LINK_MUTEX_LOCK (ORBit_RootObject_lifecycle_lock);
POA_UNLOCK (poa);
/* Destroying the children is tricky, b/c they may die
* while we are traversing. We traverse over the
* ORB's global list (rather than poa->child_poas)
* to avoid walking into dead children. */
for (i = 0; i < adaptors->len; i++) {
PortableServer_POA cpoa = g_ptr_array_index (adaptors, i);
if (cpoa && cpoa != poa) {
ORBit_RootObject_duplicate_T (cpoa);
LINK_MUTEX_UNLOCK (ORBit_RootObject_lifecycle_lock);
POA_LOCK (cpoa);
if (cpoa->parent_poa == poa)
ORBit_POA_destroy_T_R (cpoa, etherealize_objects, ev);
POA_UNLOCK (cpoa);
LINK_MUTEX_LOCK (ORBit_RootObject_lifecycle_lock);
ORBit_RootObject_release_T (cpoa);
}
}
POA_LOCK (poa);
LINK_MUTEX_UNLOCK (ORBit_RootObject_lifecycle_lock);
poa->default_servant = NULL;
if (g_hash_table_size (poa->child_poas) > 0 || poa->use_cnt ||
!ORBit_POA_deactivate (poa, etherealize_objects, ev) ) {
poa->life_flags &= ~ORBit_LifeF_Destroying;
return FALSE;
}
ORBit_POAManager_unregister_poa (poa->poa_manager, poa);
ORBit_POA_remove_child (poa->parent_poa, poa);
g_ptr_array_index (adaptors, poa->poa_id) = NULL;
poa->poa_id = -1;
/* each objref holds a POAObj, and each POAObj holds a ref
* to the POA. In addition, the app can hold open refs
* to the POA itself. */
numobjs = poa->oid_to_obj_map ? g_hash_table_size (poa->oid_to_obj_map) : 0;
g_assert (((ORBit_RootObject) poa)->refs > numobjs);
poa->life_flags |= ORBit_LifeF_Destroyed;
poa->life_flags &= ~ORBit_LifeF_Destroying;
ORBit_RootObject_release (poa);
return TRUE;
}
typedef struct TraverseInfo {
PortableServer_POA poa;
gboolean in_use;
gboolean do_etherealize;
} TraverseInfo;
static void
traverse_cb (PortableServer_ObjectId *oid,
ORBit_POAObject pobj,
TraverseInfo *info)
{
if (pobj->use_cnt > 0)
info->in_use = TRUE;
ORBit_POA_deactivate_object_T (info->poa, pobj, info->do_etherealize, TRUE);
}
static gboolean
remove_cb (PortableServer_ObjectId *oid,
ORBit_POAObject pobj,
gpointer dummy)
{
if (pobj->life_flags & ORBit_LifeF_Destroyed) {
p_free (pobj, struct ORBit_POAObject_type);
return TRUE;
}
return FALSE;
}
CORBA_boolean
ORBit_POA_deactivate (PortableServer_POA poa,
CORBA_boolean etherealize_objects,
CORBA_Environment *ev)
{
CORBA_boolean done = CORBA_TRUE;
ORBit_POA_set_life (poa, etherealize_objects, ORBit_LifeF_DeactivateDo);
if (poa->life_flags & ORBit_LifeF_Deactivated)
return TRUE; /* already did it */
if (poa->life_flags & ORBit_LifeF_Deactivating)
return FALSE; /* recursion */
poa->life_flags |= ORBit_LifeF_Deactivating;
/* bounce all pending requested (OBJECT_NOT_EXIST
* exceptions raised); none should get requeued. */
ORBit_POA_handle_held_requests (poa);
g_assert (poa->held_requests == NULL);
if (IS_RETAIN (poa)) {
TraverseInfo info;
info.poa = poa;
info.in_use = FALSE;
info.do_etherealize = (poa->life_flags & ORBit_LifeF_DoEtherealize);
g_assert (poa->oid_to_obj_map);
g_hash_table_foreach (
poa->oid_to_obj_map, (GHFunc) traverse_cb, &info);
g_hash_table_foreach_remove (
poa->oid_to_obj_map, (GHRFunc) remove_cb, NULL);
done = !info.in_use;
}
if (done)
poa->life_flags |= ORBit_LifeF_Deactivated;
poa->life_flags &= ~ORBit_LifeF_Deactivating;
return done;
}
/*
* ORBit_POA_handle_held_requests:
* @poa:
*
* Handle any requests that may been have been queued because the
* POAManager was in a HOLDING state. Note that if the POAManger
* is still in the HOLDING state, or is put into the HOLDING
* state by one of the methods invoked, requests may be re-queued.
*/
void
ORBit_POA_handle_held_requests (PortableServer_POA poa)
{
GSList *requests;
GSList *l;
requests = poa->held_requests;
poa->held_requests = NULL;
for (l = requests; l; l = l->next)
ORBit_handle_request (poa->orb, l->data);
g_slist_free (requests);
}
static void
ORBit_POA_free_fn (ORBit_RootObject obj)
{
ORBit_ObjectAdaptor adaptor = (ORBit_ObjectAdaptor) obj;
PortableServer_POA poa = (PortableServer_POA) obj;
giop_thread_key_release (obj);
if (adaptor->adaptor_key._buffer)
ORBit_free_T (adaptor->adaptor_key._buffer);
if (poa->oid_to_obj_map)
g_hash_table_destroy (poa->oid_to_obj_map);
if (poa->child_poas)
g_hash_table_destroy (poa->child_poas);
if (poa->name)
g_free (poa->name);
if (poa->base.lock)
g_mutex_free (poa->base.lock);
ORBit_RootObject_release_T (poa->orb);
ORBit_RootObject_release_T (poa->poa_manager);
p_free (poa, struct PortableServer_POA_type);
}
static const ORBit_RootObject_Interface ORBit_POA_epv = {
ORBIT_ROT_ADAPTOR,
ORBit_POA_free_fn
};
static guint
ORBit_ObjectId_sysid_hash (const PortableServer_ObjectId *object_id)
{
return *(guint *) object_id->_buffer;
}
static guint
ORBit_sequence_CORBA_octet_hash (const PortableServer_ObjectId *object_id)
{
const char *start;
const char *end;
const char *p;
guint g, h = 0;
start = (char *) object_id->_buffer;
end = (char *) object_id->_buffer + object_id->_length;
for (p = start; p < end; p++) {
h = ( h << 4 ) + *p;
g = h & 0xf0000000;
if (g != 0) {
h = h ^ (g >> 24);
h = h ^ g;
}
}
return h;
}
static gboolean
ORBit_sequence_CORBA_octet_equal (const PortableServer_ObjectId *o1,
const PortableServer_ObjectId *o2)
{
return (o1->_length == o2->_length &&
!memcmp (o1->_buffer, o2->_buffer, o1->_length));
}
static void
ORBit_POA_set_policy (PortableServer_POA poa,
CORBA_Policy obj)
{
struct CORBA_Policy_type *policy = (struct CORBA_Policy_type *) obj;
switch (policy->type) {
case PortableServer_THREAD_POLICY_ID:
poa->p_thread = policy->value;
break;
case PortableServer_LIFESPAN_POLICY_ID:
poa->p_lifespan = policy->value;
break;
case PortableServer_ID_UNIQUENESS_POLICY_ID:
poa->p_id_uniqueness = policy->value;
break;
case PortableServer_ID_ASSIGNMENT_POLICY_ID:
poa->p_id_assignment = policy->value;
break;
case PortableServer_IMPLICIT_ACTIVATION_POLICY_ID:
poa->p_implicit_activation = policy->value;
break;
case PortableServer_SERVANT_RETENTION_POLICY_ID:
poa->p_servant_retention = policy->value;
break;
case PortableServer_REQUEST_PROCESSING_POLICY_ID:
poa->p_request_processing = policy->value;
break;
default:
g_warning ("Unknown policy type, cannot set it on this POA");
break;
}
}
static void
ORBit_POA_copy_policies (const PortableServer_POA src,
PortableServer_POA dest)
{
dest->p_thread = src->p_thread;
dest->p_lifespan = src->p_lifespan;
dest->p_id_uniqueness = src->p_id_uniqueness;
dest->p_id_assignment = src->p_id_assignment;
dest->p_servant_retention = src->p_servant_retention;
dest->p_request_processing = src->p_request_processing;
dest->p_implicit_activation = src->p_implicit_activation;
}
static void
ORBit_POA_set_policies (PortableServer_POA poa,
const CORBA_PolicyList *policies,
CORBA_Environment *ev)
{
CORBA_unsigned_long i;
poa->p_thread = PortableServer_SINGLE_THREAD_MODEL;
poa->p_lifespan = PortableServer_TRANSIENT;
poa->p_id_uniqueness = PortableServer_UNIQUE_ID;
poa->p_id_assignment = PortableServer_SYSTEM_ID;
poa->p_servant_retention = PortableServer_RETAIN;
poa->p_request_processing = PortableServer_USE_ACTIVE_OBJECT_MAP_ONLY;
poa->p_implicit_activation = PortableServer_NO_IMPLICIT_ACTIVATION;
for (i = 0; policies && i < policies->_length; i++)
ORBit_POA_set_policy (poa, policies->_buffer[i]);
g_assert (ev->_major == CORBA_NO_EXCEPTION);
poa_exception_if_fail (!(IS_NON_RETAIN (poa) && IS_USE_ACTIVE_OBJECT_MAP_ONLY (poa)),
ex_PortableServer_POA_InvalidPolicy);
poa_exception_if_fail (!(IS_USE_DEFAULT_SERVANT (poa) && IS_UNIQUE_ID (poa)),
ex_PortableServer_POA_InvalidPolicy);
poa_exception_if_fail (!(IS_IMPLICIT_ACTIVATION (poa) && (IS_USER_ID (poa) || IS_NON_RETAIN (poa))),
ex_PortableServer_POA_InvalidPolicy);
}
static PortableServer_POA
ORBit_POA_new (CORBA_ORB orb,
const CORBA_char *adaptor_name,
PortableServer_POAManager manager,
const CORBA_PolicyList *policies,
CORBA_Environment *ev)
{
PortableServer_POA poa;
ORBit_ObjectAdaptor adaptor;
poa = g_new0 (struct PortableServer_POA_type, 1);
ORBit_RootObject_init ((ORBit_RootObject) poa, &ORBit_POA_epv);
/* released in ORBit_POA_destroy */
ORBit_RootObject_duplicate (poa);
ORBit_POA_set_policies (poa, policies, ev);
if (ev->_major != CORBA_NO_EXCEPTION) {
ORBit_RootObject_release (poa);
return CORBA_OBJECT_NIL;
}
if (!manager)
manager = ORBit_POAManager_new (orb);
poa->poa_manager = ORBit_RootObject_duplicate (manager);
adaptor = (ORBit_ObjectAdaptor) poa;
adaptor->handle_request = (ORBitReqHandlerFunc) ORBit_POA_handle_request;
poa->name = g_strdup (adaptor_name);
poa->child_poas = g_hash_table_new (g_str_hash, g_str_equal);
poa->orb = ORBit_RootObject_duplicate (orb);
poa->poa_id = ORBit_adaptor_setup (adaptor, orb);
if (IS_SYSTEM_ID (poa))
poa->oid_to_obj_map = g_hash_table_new (
(GHashFunc) ORBit_ObjectId_sysid_hash,
(GEqualFunc) ORBit_sequence_CORBA_octet_equal);
else /* USER_ID */
poa->oid_to_obj_map = g_hash_table_new (
(GHashFunc) ORBit_sequence_CORBA_octet_hash,
(GEqualFunc) ORBit_sequence_CORBA_octet_equal);
poa->base.lock = link_mutex_new ();
ORBit_POAManager_register_poa (manager, poa);
return ORBit_RootObject_duplicate (poa);
}
PortableServer_POA
ORBit_POA_new_from (CORBA_ORB orb,
PortableServer_POA parent,
const CORBA_char *adaptor_name,
const CORBA_PolicyList *opt_policies,
CORBA_Environment *ev)
{
PortableServer_POA poa;
g_return_val_if_fail (parent != CORBA_OBJECT_NIL, CORBA_OBJECT_NIL);
poa = ORBit_POA_new (orb, adaptor_name, parent->poa_manager, NULL, ev);
g_return_val_if_fail (poa != CORBA_OBJECT_NIL, CORBA_OBJECT_NIL);
ORBit_POA_copy_policies (parent, poa);
if (opt_policies) {
int i;
for (i = 0; i < opt_policies->_length; i++)
ORBit_POA_set_policy (poa, opt_policies->_buffer[i]);
}
ORBit_POA_add_child (parent, poa);
return poa;
}
static CORBA_Object
ORBit_POA_obj_to_ref (PortableServer_POA poa,
ORBit_POAObject pobj,
const CORBA_char *intf,
CORBA_Environment *ev)
{
const char *type_id = intf;
g_assert (pobj && !pobj->base.objref);
if (!type_id) {
g_assert (pobj->servant);
type_id = ORBIT_SERVANT_TO_CLASSINFO (pobj->servant)->class_name;
}
g_assert (type_id != NULL);
pobj->base.objref = ORBit_objref_new (poa->poa_manager->orb,
&pobj->base,
g_quark_from_string (type_id));
return ORBit_RootObject_duplicate (pobj->base.objref);
}
PortableServer_POA
ORBit_POA_setup_root (CORBA_ORB orb, CORBA_Environment *ev)
{
PortableServer_POA poa;
CORBA_Policy policybuf[1];
CORBA_PolicyList policies = {1, 1, NULL, CORBA_FALSE};
policies._buffer = (CORBA_Object *) policybuf;
policies._buffer [0] = (CORBA_Policy)
PortableServer_POA_create_implicit_activation_policy (
NULL, PortableServer_IMPLICIT_ACTIVATION, ev);
poa = ORBit_POA_new (orb, "RootPOA", CORBA_OBJECT_NIL, &policies, ev);
CORBA_Policy_destroy (policies._buffer [0], ev);
CORBA_Object_release (policies._buffer [0], ev);
return poa;
}
static gboolean
ORBit_POAObject_is_active (ORBit_POAObject pobj)
{
if (pobj && pobj->servant)
return TRUE;
return FALSE;
}
/* POAObject RootObject stuff */
static void
ORBit_POAObject_release_cb (ORBit_RootObject robj)
{
ORBit_POAObject pobj = (ORBit_POAObject) robj;
PortableServer_POA poa = pobj->poa;
PortableServer_ObjectId *object_id;
/* object *must* be deactivated */
g_assert (pobj->servant == NULL);
giop_thread_key_release (robj);
object_id = pobj->object_id;
pobj->object_id = NULL;
/*
* Don't want to remove from oid_to_obj_map if we
* are currently traversing across it !
* Just mark it as destroyed
*/
if ((poa->life_flags & ORBit_LifeF_Deactivating) == 0) {
g_hash_table_remove (poa->oid_to_obj_map, object_id);
p_free (robj, struct ORBit_POAObject_type);
} else
pobj->life_flags = ORBit_LifeF_Destroyed;
object_id->_release = CORBA_TRUE;
ORBit_free_T (object_id);
ORBit_RootObject_release_T (poa);
}
static ORBit_RootObject_Interface ORBit_POAObject_if = {
ORBIT_ROT_OAOBJECT,
ORBit_POAObject_release_cb
};
static struct
ORBit_OAObject_Interface_type ORBit_POAObject_methods = {
ORBIT_ADAPTOR_POA,
(ORBitStateCheckFunc) ORBit_POAObject_is_active,
(ORBitKeyGenFunc) ORBit_POAObject_object_to_objkey,
(ORBitInvokeFunc) ORBit_POAObject_invoke,
(ORBitReqFunc) ORBit_POAObject_handle_request
};
/*
* If USER_ID policy, {oid} must be non-NULL.
* If SYSTEM_ID policy, {oid} must ether be NULL, or must have
* been previously created by the POA. If the user passes in
* a bogus oid under SYSTEM_ID, we will assert or segfault. This
* is allowed by the CORBA spec.
*/
static ORBit_POAObject
ORBit_POA_create_object_T (PortableServer_POA poa,
const PortableServer_ObjectId *objid,
CORBA_Environment *ev)
{
ORBit_POAObject newobj;
newobj = g_new0 (struct ORBit_POAObject_type, 1);
ORBit_RootObject_init ((ORBit_RootObject)newobj, &ORBit_POAObject_if);
/* released in ORBit_POAObject_release_cb */
newobj->poa = ORBit_RootObject_duplicate (poa);
((ORBit_OAObject)newobj)->interface = &ORBit_POAObject_methods;
if (poa->p_id_assignment == PortableServer_SYSTEM_ID) {
if (objid) {
g_assert (objid->_length ==
sizeof (CORBA_unsigned_long) +
ORBIT_OBJECT_ID_LEN);
newobj->object_id = PortableServer_ObjectId__alloc ();
newobj->object_id->_length = objid->_length;
newobj->object_id->_buffer = PortableServer_ObjectId_allocbuf (objid->_length);
newobj->object_id->_release = CORBA_TRUE;
memcpy (newobj->object_id->_buffer, objid->_buffer, objid->_length);
}
else
newobj->object_id = ORBit_POA_new_system_objid_T (poa);
} else {
newobj->object_id = PortableServer_ObjectId__alloc ();
newobj->object_id->_length = objid->_length;
newobj->object_id->_buffer = PortableServer_ObjectId_allocbuf (objid->_length);
newobj->object_id->_release = CORBA_TRUE;
memcpy(newobj->object_id->_buffer, objid->_buffer, objid->_length);
}
g_hash_table_insert (poa->oid_to_obj_map, newobj->object_id, newobj);
return newobj;
}
/*
* Normally this is called for normal servants in RETAIN mode.
* However, it may also be invoked on the default servant when
* it is installed. In this later case, it may be either RETAIN
* or NON_RETAIN.
*/
static void
ORBit_POA_activate_object_T (PortableServer_POA poa,
ORBit_POAObject pobj,
PortableServer_ServantBase *servant,
CORBA_Environment *ev)
{
PortableServer_ClassInfo *class_info;
g_assert (pobj->servant == NULL);
g_assert ((poa->life_flags & ORBit_LifeF_DeactivateDo) == 0);
g_assert (pobj->use_cnt == 0);
class_info = ORBIT_SERVANT_TO_CLASSINFO (servant);
pobj->vepvmap_cache = class_info->vepvmap;
pobj->servant = servant;
pobj->next = (ORBit_POAObject) servant->_private;
servant->_private = pobj;
/* released in ORBit_POA_deactivate_object */
ORBit_RootObject_duplicate (pobj);
}
/*
* Note that this doesn't necessarily remove the object from
* the oid_to_obj_map; it just removes knowledge of the servant.
* If the object is currently in use (servicing a request),
* etherialization and memory release will occur later.
*/
static void
ORBit_POA_deactivate_object_T (PortableServer_POA poa,
ORBit_POAObject pobj,
CORBA_boolean do_etherealize,
CORBA_boolean is_cleanup)
{
PortableServer_ServantBase *servant = pobj->servant;
if (!servant) /* deactivation done, or in progress */
return;
if (do_etherealize && !(pobj->life_flags & ORBit_LifeF_DeactivateDo))
pobj->life_flags |= ORBit_LifeF_DoEtherealize;
if (is_cleanup)
pobj->life_flags |= ORBit_LifeF_IsCleanup;
if (pobj->use_cnt > 0) {
pobj->life_flags |= ORBit_LifeF_DeactivateDo;
pobj->life_flags |= ORBit_LifeF_NeedPostInvoke;
return;
}
pobj->servant = NULL;
if ((ORBit_POAObject) servant->_private == pobj)
servant->_private = pobj->next;
else {
ORBit_POAObject l = (ORBit_POAObject) servant->_private;
for (; l && l->next != pobj; l = l->next);
g_assert (l != NULL && l->next == pobj);
l->next = pobj->next;
}
pobj->next = NULL;
if (pobj->life_flags & ORBit_LifeF_DoEtherealize) {
CORBA_Environment env, *ev = &env;
CORBA_exception_init (ev);
pobj->use_cnt++; /* prevent re-activation */
if (poa->p_request_processing == PortableServer_USE_SERVANT_MANAGER) {
POA_PortableServer_ServantActivator *sm;
POA_PortableServer_ServantActivator__epv *epv;
sm = (POA_PortableServer_ServantActivator *) poa->servant_manager;
epv = sm->vepv->PortableServer_ServantActivator_epv;
epv->etherealize (sm, pobj->object_id, poa,
servant,
pobj->life_flags & ORBit_LifeF_IsCleanup,
/* remaining_activations */ CORBA_FALSE,
ev);
}
{
PortableServer_ServantBase__epv *epv = servant->vepv[0];
/* In theory, the finalize fnc should always be non-NULL;
* however, for backward compat. and general extended
* applications we dont insist on it. */
if (epv && epv->finalize) {
POA_UNLOCK (poa);
epv->finalize (servant, ev);
POA_LOCK (poa);
}
}
pobj->use_cnt--; /* allow re-activation */
if (ev->_major != 0) {
g_error ("finalize function for object %p threw an exception (%s). This is not allowed.",
pobj, CORBA_exception_id (ev));
}
CORBA_exception_free (ev);
}
pobj->life_flags &= ~(ORBit_LifeF_DeactivateDo |
ORBit_LifeF_IsCleanup |
ORBit_LifeF_DoEtherealize);
ORBit_RootObject_release (pobj);
}
struct ORBit_POA_invoke_data {
ORBitSmallSkeleton small_skel;
gpointer imp;
};
static void
ORBit_POAObject_invoke (ORBit_POAObject pobj,
gpointer ret,
gpointer *args,
CORBA_Context ctx,
gpointer data,
CORBA_Environment *ev)
{
struct ORBit_POA_invoke_data *invoke_data = (struct ORBit_POA_invoke_data *) data;
invoke_data->small_skel (pobj->servant, ret, args, ctx, ev, invoke_data->imp);
}
/*
* giop_recv_buffer_return_sys_exception:
* @recv_buffer:
* @m_data:
* @ev:
*
* Return a system exception in @ev to the client. If @m_data
* is not nil, it used to determine whether the call is a
* oneway and, hence, whether to return the exception. If
* @m_data is nil, we are not far enough along in the processing
* of the reqeust to be able to determine if this is a oneway
* method.
*/
void
ORBit_recv_buffer_return_sys_exception (GIOPRecvBuffer *recv_buffer,
CORBA_Environment *ev)
{
GIOPSendBuffer *send_buffer;
if (!recv_buffer) /* In Proc */
return;
g_return_if_fail (ev->_major == CORBA_SYSTEM_EXCEPTION);
send_buffer = giop_send_buffer_use_reply (
recv_buffer->connection->giop_version,
giop_recv_buffer_get_request_id (recv_buffer),
ev->_major);
ORBit_send_system_exception (send_buffer, ev);
tprintf ("Return exception:\n");
do_giop_dump_send (send_buffer);
giop_send_buffer_write (send_buffer, recv_buffer->connection, FALSE);
giop_send_buffer_unuse (send_buffer);
}
static void
return_exception (GIOPRecvBuffer *recv_buffer,
ORBit_IMethod *m_data,
CORBA_Environment *ev)
{
if (!recv_buffer) /* In Proc */
return;
g_return_if_fail (ev->_major == CORBA_SYSTEM_EXCEPTION);
if (m_data && m_data->flags & ORBit_I_METHOD_1_WAY) {
tprintf ("A serious exception occured on a oneway method");
return;
}
ORBit_recv_buffer_return_sys_exception (recv_buffer, ev);
}
/*
* If invoked in the local case, recv_buffer == NULL.
* If invoked in the remote cse, ret = args = ctx == NULL.
*/
static void
ORBit_POAObject_handle_request (ORBit_POAObject pobj,
CORBA_Identifier opname,
gpointer ret,
gpointer *args,
CORBA_Context ctx,
GIOPRecvBuffer *recv_buffer,
CORBA_Environment *ev)
{
PortableServer_POA poa = pobj->poa;
PortableServer_ServantLocator_Cookie cookie = NULL;
PortableServer_ObjectId *oid = NULL;
PortableServer_ClassInfo *klass;
ORBit_IMethod *m_data = NULL;
ORBitSmallSkeleton small_skel = NULL;
gpointer imp = NULL;
if (poa) {
ORBit_RootObject_duplicate (poa);
POA_LOCK (poa);
}
if (!poa || !poa->poa_manager)
CORBA_exception_set_system (
ev, ex_CORBA_OBJECT_NOT_EXIST,
CORBA_COMPLETED_NO);
else {
switch (poa->poa_manager->state) {
case PortableServer_POAManager_HOLDING:
if (recv_buffer) {
g_warning ("POAManager in holding state. "
"Queueing '%s' method request", opname);
poa->held_requests = g_slist_prepend (
poa->held_requests, recv_buffer);
goto clean_out;
} else
CORBA_exception_set_system (
ev, ex_CORBA_TRANSIENT,
CORBA_COMPLETED_NO);
break;
case PortableServer_POAManager_DISCARDING:
CORBA_exception_set_system (
ev, ex_CORBA_TRANSIENT,
CORBA_COMPLETED_NO);
break;
case PortableServer_POAManager_INACTIVE:
CORBA_exception_set_system (
ev, ex_CORBA_OBJ_ADAPTER,
CORBA_COMPLETED_NO);
break;
case PortableServer_POAManager_ACTIVE:
break;
default:
g_assert_not_reached ();
break;
}
}
if (ev->_major != CORBA_NO_EXCEPTION) {
return_exception (recv_buffer, m_data, ev);
goto clean_out;
}
oid = pobj->object_id;
if (!pobj->servant) {
switch (poa->p_request_processing) {
case PortableServer_USE_ACTIVE_OBJECT_MAP_ONLY:
CORBA_exception_set_system (
ev, ex_CORBA_OBJECT_NOT_EXIST,
CORBA_COMPLETED_NO);
break;
case PortableServer_USE_DEFAULT_SERVANT:
ORBit_POA_activate_object_T (
poa, pobj, poa->default_servant, ev);
break;
case PortableServer_USE_SERVANT_MANAGER:
ORBit_POA_ServantManager_use_servant (
poa, pobj, opname, &cookie, oid, ev);
break;
default:
g_assert_not_reached();
break;
}
}
if (ev->_major == CORBA_NO_EXCEPTION && !pobj->servant)
CORBA_exception_set_system (
ev, ex_CORBA_OBJECT_NOT_EXIST,
CORBA_COMPLETED_NO);
if (ev->_major != CORBA_NO_EXCEPTION) {
return_exception (recv_buffer, m_data, ev);
goto clean_out;
}
pobj->use_cnt++;
ORBit_POA_invocation_stack_push (poa, pobj);
klass = ORBIT_SERVANT_TO_CLASSINFO (pobj->servant);
if (klass->impl_finder)
small_skel = klass->impl_finder (
pobj->servant, opname, (gpointer *)&m_data, &imp);
/* FIXME: we can only do that in-proc (and for _is_a [and others?]) */
if (!small_skel)
small_skel = get_small_skel_CORBA_Object (
pobj->servant, opname,
(gpointer *)&m_data, &imp);
if (!small_skel || !imp) {
if (!imp && small_skel) {
tprintf ("'%s' not implemented on %p",
opname, pobj);
CORBA_exception_set_system (
ev, ex_CORBA_NO_IMPLEMENT,
CORBA_COMPLETED_NO);
} else {
tprintf ("Bad operation '%s' on %p",
opname, pobj);
CORBA_exception_set_system (
ev, ex_CORBA_BAD_OPERATION,
CORBA_COMPLETED_NO);
}
}
if (ev->_major != CORBA_NO_EXCEPTION)
return_exception (recv_buffer, m_data, ev);
else {
POA_UNLOCK (poa);
if (recv_buffer) {
struct ORBit_POA_invoke_data invoke_data;
invoke_data.small_skel = small_skel;
invoke_data.imp = imp;
ORBit_small_invoke_adaptor ((ORBit_OAObject) pobj, recv_buffer,
m_data, &invoke_data, ev);
} else
small_skel (pobj->servant, ret, args, ctx, ev, imp);
POA_LOCK (poa);
}
if (recv_buffer)
CORBA_exception_free (ev);
if (IS_NON_RETAIN (poa))
switch (poa->p_request_processing) {
case PortableServer_USE_SERVANT_MANAGER:
ORBit_POA_ServantManager_unuse_servant (
poa, pobj, opname, cookie,
oid, pobj->servant, ev);
break;
case PortableServer_USE_DEFAULT_SERVANT:
ORBit_POA_deactivate_object_T (poa, pobj, FALSE, FALSE);
break;
default:
g_assert_not_reached ();
break;
}
ORBit_POA_invocation_stack_pop (poa, pobj);
pobj->use_cnt--;
if (pobj->life_flags & ORBit_LifeF_NeedPostInvoke)
ORBit_POAObject_post_invoke (pobj);
clean_out:
if(poa) {
POA_UNLOCK (poa);
ORBit_RootObject_release (poa);
}
}
static ORBit_POAObject
ORBit_POA_object_key_lookup_T (PortableServer_POA poa,
ORBit_ObjectKey *objkey,
PortableServer_ObjectId *object_id)
{
object_id->_buffer = objkey->_buffer + ORBIT_ADAPTOR_PREFIX_LEN;
object_id->_length = objkey->_length - ORBIT_ADAPTOR_PREFIX_LEN;
object_id->_maximum = object_id->_length;
object_id->_release = CORBA_FALSE;
return ORBit_POA_object_id_lookup_T (poa, object_id);
}
static void
ORBit_POAObject_invoke_incoming_request (ORBit_POAObject pobj,
GIOPRecvBuffer *recv_buffer,
CORBA_Environment *opt_ev)
{
CORBA_Environment real_ev, *ev;
if (!opt_ev)
CORBA_exception_init ((ev = &real_ev));
else
ev = opt_ev;
if (ev->_major == CORBA_NO_EXCEPTION &&
pobj != CORBA_OBJECT_NIL) {
CORBA_Identifier opname;
opname = giop_recv_buffer_get_opname (recv_buffer);
ORBit_POAObject_handle_request (pobj, opname, NULL, NULL,
NULL, recv_buffer, ev);
}
ORBit_RootObject_release (pobj);
if (ev->_major != CORBA_NO_EXCEPTION) {
tprintf ("p %d, Method '%p' invoked with exception '%s'",
getpid (), giop_recv_buffer_get_opname (recv_buffer), ev->_id);
return_exception (recv_buffer, NULL, ev);
}
if (!opt_ev)
CORBA_exception_free (ev);
giop_recv_buffer_unuse (recv_buffer);
}
static inline void
push_request_T (GIOPThread *thread,
ORBit_POAObject *pobj,
GIOPRecvBuffer **recv_buffer)
{
giop_thread_request_push
(thread, (gpointer *)pobj, (gpointer *)recv_buffer);
}
static void
pool_push_request_for_T (gpointer key_object,
ORBit_POAObject *pobj,
GIOPRecvBuffer **recv_buffer)
{
g_assert (giop_thread_io ());
giop_thread_request_push_key
(key_object, (gpointer *)pobj, (gpointer *)recv_buffer);
}
typedef struct {
ORBit_POAObject pobj;
GIOPRecvBuffer *recv_buffer;
} PoaIdleClosure;
static gboolean
poa_invoke_at_idle (gpointer data)
{
PoaIdleClosure *pcl = data;
ORBit_POAObject_invoke_incoming_request
(pcl->pobj, pcl->recv_buffer, NULL);
pcl->pobj = NULL;
pcl->recv_buffer = NULL;
return FALSE;
}
static void
poa_destroy_idle_closure (gpointer data)
{
PoaIdleClosure *pcl = data;
if (pcl->pobj)
ORBit_RootObject_release (pcl->pobj);
if (pcl->recv_buffer)
giop_recv_buffer_unuse (pcl->recv_buffer);
g_free (pcl);
}
static void
push_request_idle (ORBit_POAObject *pobj,
GIOPRecvBuffer **recv_buffer,
GMainContext *on_context)
{
PoaIdleClosure *pcl = g_new (PoaIdleClosure, 1);
GSource *source;
pcl->pobj = *pobj;
pcl->recv_buffer = *recv_buffer;
source = g_idle_source_new ();
g_source_set_callback (source, poa_invoke_at_idle, pcl, poa_destroy_idle_closure);
g_source_attach (source, on_context);
g_source_unref (source);
*pobj = NULL;
*recv_buffer = NULL;
}
static gboolean
poa_recv_is_oneway (ORBit_POAObject pobj,
GIOPRecvBuffer *recv_buffer)
{
ORBit_IMethod *m_data = NULL;
gpointer imp = NULL;
PortableServer_ClassInfo *klass;
g_return_val_if_fail (pobj != CORBA_OBJECT_NIL, FALSE);
klass = ORBIT_SERVANT_TO_CLASSINFO (pobj->servant);
if (!klass->impl_finder)
return FALSE;
klass->impl_finder ( pobj->servant,
giop_recv_buffer_get_opname (recv_buffer),
(gpointer *)&m_data, &imp);
if (m_data && m_data->flags & ORBit_I_METHOD_1_WAY)
return TRUE;
return FALSE;
}
static void
ORBit_POA_handle_request (PortableServer_POA poa,
GIOPRecvBuffer *recv_buffer,
ORBit_ObjectKey *objkey)
{
ORBit_POAObject pobj;
CORBA_Environment env;
PortableServer_ObjectId object_id;
CORBA_exception_init (&env);
POA_LOCK (poa);
pobj = ORBit_POA_object_key_lookup_T (poa, objkey, &object_id);
if (!pobj)
switch (poa->p_request_processing) {
case PortableServer_USE_ACTIVE_OBJECT_MAP_ONLY:
CORBA_exception_set_system (
&env, ex_CORBA_OBJECT_NOT_EXIST,
CORBA_COMPLETED_NO);
goto send_sys_ex;
break;
case PortableServer_USE_DEFAULT_SERVANT: /* drop through */
case PortableServer_USE_SERVANT_MANAGER:
pobj = ORBit_POA_create_object_T (poa, &object_id, &env);
break;
default:
g_assert_not_reached ();
break;
}
if (!pobj)
CORBA_exception_set_system (
&env, ex_CORBA_OBJECT_NOT_EXIST,
CORBA_COMPLETED_NO);
else {
switch (poa->p_thread) {
case PortableServer_SINGLE_THREAD_MODEL:
if (giop_thread_io ())
push_request_T (giop_thread_get_main (),
&pobj, &recv_buffer);
break;
case PortableServer_ORB_CTRL_MODEL: {
ORBit_ObjectAdaptor adaptor = (ORBit_ObjectAdaptor) poa;
switch (adaptor->thread_hint) {
case ORBIT_THREAD_HINT_PER_OBJECT:
/* Note: If the user bound this object to a specific
* thread this thread will be called, otherwise a
* new thread will be created for handling requests
* to the object. */
pool_push_request_for_T (pobj, &pobj, &recv_buffer);
break;
case ORBIT_THREAD_HINT_PER_POA:
pool_push_request_for_T (poa, &pobj, &recv_buffer);
break;
case ORBIT_THREAD_HINT_PER_CONNECTION:
pool_push_request_for_T (recv_buffer->connection,
&pobj, &recv_buffer);
break;
case ORBIT_THREAD_HINT_PER_REQUEST:
pool_push_request_for_T (NULL, &pobj, &recv_buffer);
break;
case ORBIT_THREAD_HINT_ONEWAY_AT_IDLE:
if (!poa_recv_is_oneway (pobj, recv_buffer))
push_request_T (giop_thread_get_main (),
&pobj, &recv_buffer);
/* drop through */
case ORBIT_THREAD_HINT_ALL_AT_IDLE:
push_request_idle (&pobj, &recv_buffer, NULL);
break;
case ORBIT_THREAD_HINT_ON_CONTEXT:
push_request_idle (&pobj, &recv_buffer, adaptor->context);
break;
case ORBIT_THREAD_HINT_NONE:
if (giop_thread_io ())
push_request_T (giop_thread_get_main (),
&pobj, &recv_buffer);
break;
default:
g_warning ("Binning incoming requests in threaded mode");
giop_recv_buffer_unuse (recv_buffer);
recv_buffer = NULL;
pobj = NULL;
break;
}
break;
}
default:
g_assert_not_reached ();
break;
}
}
send_sys_ex:
POA_UNLOCK (poa);
ORBit_POAObject_invoke_incoming_request (pobj, recv_buffer, &env);
}
static PortableServer_Servant
ORBit_POA_ServantManager_use_servant (PortableServer_POA poa,
ORBit_POAObject pobj,
CORBA_Identifier opname,
PortableServer_ServantLocator_Cookie *the_cookie,
PortableServer_ObjectId *oid,
CORBA_Environment *ev)
{
PortableServer_ServantBase *retval;
if (IS_RETAIN (poa)) {
POA_PortableServer_ServantActivator__epv *epv;
POA_PortableServer_ServantActivator *sm;
sm = (POA_PortableServer_ServantActivator *) poa->servant_manager;
epv = sm->vepv->PortableServer_ServantActivator_epv;
retval = epv->incarnate (sm, oid, poa, ev);
if (retval) {
/* XXX: two POAs sharing servant and having
* different uniqueness policies ??
* see note 11.3.5.1
*/
if (IS_UNIQUE_ID (poa) && retval->_private != NULL) {
CORBA_exception_set_system (ev, ex_CORBA_OBJ_ADAPTER,
CORBA_COMPLETED_NO);
return NULL;
}
pobj->next = retval->_private;
retval->_private = pobj;
/* released by ORBit_POA_deactivate_object */
ORBit_RootObject_duplicate (pobj);
pobj->servant = retval;
}
} else {
POA_PortableServer_ServantLocator__epv *epv;
POA_PortableServer_ServantLocator *sm;
sm = (POA_PortableServer_ServantLocator *) poa->servant_manager;
epv = sm->vepv->PortableServer_ServantLocator_epv;
retval = epv->preinvoke (sm, oid, poa, opname, the_cookie, ev);
if (retval) {
/* FIXME: Is this right?
* Is it the same as above?
*/
if (IS_UNIQUE_ID (poa) && retval->_private != NULL) {
CORBA_exception_set_system (ev, ex_CORBA_OBJ_ADAPTER,
CORBA_COMPLETED_NO);
return NULL;
}
pobj->next = retval->_private;
retval->_private = pobj;
/* released by ORBit_POA_ServantManager_unuse_servant */
ORBit_RootObject_duplicate (pobj);
pobj->servant = retval;
}
}
return retval;
}
static void
ORBit_POA_ServantManager_unuse_servant (PortableServer_POA poa,
ORBit_POAObject pobj,
CORBA_Identifier opname,
PortableServer_ServantLocator_Cookie cookie,
PortableServer_ObjectId *oid,
PortableServer_Servant serv,
CORBA_Environment *ev)
{
POA_PortableServer_ServantLocator *sm;
POA_PortableServer_ServantLocator__epv *epv;
PortableServer_ServantBase *servant = serv;
g_assert (IS_NON_RETAIN (poa));
sm = (POA_PortableServer_ServantLocator *) poa->servant_manager;
epv = sm->vepv->PortableServer_ServantLocator_epv;
pobj->servant = NULL;
if ((ORBit_POAObject) servant->_private == pobj)
servant->_private = pobj->next;
else {
ORBit_POAObject l = (ORBit_POAObject) servant->_private;
for (; l && l->next != pobj; l = l->next);
g_assert (l != NULL && l->next == pobj);
l->next = pobj->next;
}
pobj->next = NULL;
ORBit_RootObject_release (pobj);
epv->postinvoke (sm, oid, poa, opname, cookie, servant, ev);
}
/*
* Was this ever exposed / can we axe it ?
*/
void
ORBit_POAObject_post_invoke (ORBit_POAObject pobj)
{
if (pobj->use_cnt > 0)
return;
if (pobj->life_flags & ORBit_LifeF_DeactivateDo) {
/* NOTE that the "desired" values of etherealize and cleanup
* are stored in pobj->life_flags and they dont need
* to be passed in again!
*/
ORBit_POA_deactivate_object_T (
pobj->poa, pobj, /*ether*/0, /*cleanup*/0);
/* WATCHOUT: pobj may not exist anymore! */
}
}
/*
* C Language Mapping Specific Methods.
* Section 1.26.2 (C Language Mapping Specification).
*/
CORBA_char *
PortableServer_ObjectId_to_string (PortableServer_ObjectId *id,
CORBA_Environment *ev)
{
CORBA_char *str;
poa_sys_exception_val_if_fail (id != NULL, ex_CORBA_BAD_PARAM, NULL);
poa_sys_exception_val_if_fail (memchr (id->_buffer, '\0', id->_length),
ex_CORBA_BAD_PARAM, NULL);
str = CORBA_string_alloc (id->_length + 1);
memcpy (str, id->_buffer, id->_length);
str [id->_length] = '\0';
return str;
}
CORBA_wchar *
PortableServer_ObjectId_to_wstring (PortableServer_ObjectId *id,
CORBA_Environment *ev)
{
CORBA_wchar *retval;
int i;
poa_sys_exception_val_if_fail (id != NULL, ex_CORBA_BAD_PARAM, NULL);
poa_sys_exception_val_if_fail (memchr (id->_buffer, '\0', id->_length),
ex_CORBA_BAD_PARAM, NULL);
retval = CORBA_wstring_alloc (id->_length + 1);
for (i = 0; i < id->_length; i++)
retval [i] = id->_buffer [i];
retval [id->_length] = '\0';
return retval;
}
PortableServer_ObjectId *
PortableServer_string_to_ObjectId (CORBA_char *str,
CORBA_Environment *ev)
{
PortableServer_ObjectId tmp;
poa_sys_exception_val_if_fail (str != NULL, ex_CORBA_BAD_PARAM, NULL);
tmp._length = strlen (str);
tmp._buffer = str;
return (PortableServer_ObjectId *) ORBit_sequence_CORBA_octet_dup (&tmp);
}
PortableServer_ObjectId *
PortableServer_wstring_to_ObjectId (CORBA_wchar *str,
CORBA_Environment *ev)
{
PortableServer_ObjectId tmp;
int i;
poa_sys_exception_val_if_fail (str != NULL, ex_CORBA_BAD_PARAM, NULL);
for (i = 0; str[i]; i++);
tmp._length = i*2;
tmp._buffer = g_alloca (tmp._length);
for (i = 0; str[i]; i++)
tmp._buffer[i] = str[i];
return (PortableServer_ObjectId *) ORBit_sequence_CORBA_octet_dup (&tmp);
}
/*
* Current Operations.
* Section 11.3.9
*/
PortableServer_POA
PortableServer_Current_get_POA (PortableServer_Current obj,
CORBA_Environment *ev)
{
ORBit_POAObject pobj;
poa_sys_exception_val_if_fail (obj != NULL, ex_CORBA_INV_OBJREF, NULL);
pobj = ORBit_POACurrent_get_object (obj, ev);
return ORBit_RootObject_duplicate (pobj->poa);
}
PortableServer_ObjectId *
PortableServer_Current_get_object_id (PortableServer_Current obj,
CORBA_Environment *ev)
{
ORBit_POAObject pobj;
poa_sys_exception_val_if_fail (obj != NULL, ex_CORBA_INV_OBJREF, NULL);
pobj = ORBit_POACurrent_get_object (obj, ev);
if (!pobj)
return NULL;
return (PortableServer_ObjectId *)ORBit_sequence_CORBA_octet_dup (pobj->object_id);
}
/*
* PortableServer::POA interface
* Section 11.3.8
*/
PortableServer_POA
PortableServer_POA_create_POA (PortableServer_POA poa,
const CORBA_char *adaptor_name,
const PortableServer_POAManager a_POAManager,
const CORBA_PolicyList *policies,
CORBA_Environment *ev)
{
PortableServer_POA retval;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (adaptor_name != NULL, ex_CORBA_BAD_PARAM, NULL);
poa_sys_exception_val_if_fail (policies != NULL, ex_CORBA_BAD_PARAM, NULL);
if (g_hash_table_lookup (poa->child_poas, adaptor_name)) {
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_AdapterAlreadyExists,
NULL);
return CORBA_OBJECT_NIL;
}
retval = ORBit_POA_new (poa->orb, adaptor_name, a_POAManager, policies, ev);
ORBit_POA_add_child (poa, retval);
return retval;
}
PortableServer_POA
PortableServer_POA_find_POA (PortableServer_POA poa,
const CORBA_char *adaptor_name,
const CORBA_boolean activate_it,
CORBA_Environment *ev)
{
PortableServer_POA child_poa = NULL;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (adaptor_name != NULL, ex_CORBA_BAD_PARAM, NULL);
if (poa->child_poas)
child_poa = g_hash_table_lookup (poa->child_poas, adaptor_name);
if (activate_it)
g_warning ("Don't yet know how to activate POA named \"%s\"",
adaptor_name);
if (!child_poa)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_AdapterNonExistent,
NULL);
return ORBit_RootObject_duplicate (child_poa);
}
void
PortableServer_POA_destroy (PortableServer_POA poa,
const CORBA_boolean etherealize_objects,
const CORBA_boolean wait_for_completion,
CORBA_Environment *ev)
{
gboolean done;
poa_sys_exception_if_fail (poa != NULL, ex_CORBA_INV_OBJREF);
ORBit_RootObject_duplicate (poa);
POA_LOCK (poa);
if (poa->life_flags & ORBit_LifeF_Destroyed)
;
else if (wait_for_completion && ORBit_POA_is_inuse_T (poa, CORBA_TRUE, ev))
CORBA_exception_set_system (ev, ex_CORBA_BAD_INV_ORDER,
CORBA_COMPLETED_NO);
else {
done = ORBit_POA_destroy_T_R (poa, etherealize_objects, ev);
g_assert (done || !wait_for_completion);
}
POA_UNLOCK (poa);
ORBit_RootObject_release (poa);
}
CORBA_string
PortableServer_POA__get_the_name (PortableServer_POA poa,
CORBA_Environment *ev)
{
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
return CORBA_string_dup (poa->name);
}
PortableServer_POA
PortableServer_POA__get_the_parent (PortableServer_POA poa,
CORBA_Environment *ev)
{
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
return ORBit_RootObject_duplicate (poa->parent_poa);
}
static void
ORBit_POAList_add_child (char *name,
PortableServer_POA poa,
PortableServer_POAList *list)
{
list->_buffer [list->_length++] = ORBit_RootObject_duplicate (poa);
}
PortableServer_POAList *
PortableServer_POA__get_the_children (PortableServer_POA poa,
CORBA_Environment *ev)
{
PortableServer_POAList *retval;
int length;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
length = g_hash_table_size (poa->child_poas);
retval = PortableServer_POAList__alloc ();
retval->_length = 0;
retval->_maximum = length;
retval->_buffer = (CORBA_Object *) PortableServer_POAList_allocbuf (length);
retval->_release = CORBA_TRUE;
g_hash_table_foreach (poa->child_poas, (GHFunc) ORBit_POAList_add_child, retval);
g_assert (retval->_length == length);
return retval;
}
PortableServer_POAManager
PortableServer_POA__get_the_POAManager (PortableServer_POA poa,
CORBA_Environment *ev)
{
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
return ORBit_RootObject_duplicate (poa->poa_manager);
}
PortableServer_AdapterActivator
PortableServer_POA__get_the_activator (PortableServer_POA poa,
CORBA_Environment *ev)
{
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
return ORBit_RootObject_duplicate (poa->the_activator);
}
void
PortableServer_POA__set_the_activator (PortableServer_POA poa,
const PortableServer_AdapterActivator activator,
CORBA_Environment * ev)
{
poa_sys_exception_if_fail (poa != NULL, ex_CORBA_INV_OBJREF);
poa_sys_exception_if_fail (activator != NULL, ex_CORBA_BAD_PARAM);
if (poa->the_activator)
ORBit_RootObject_release (poa->the_activator);
poa->the_activator = (PortableServer_AdapterActivator)
ORBit_RootObject_duplicate (activator);
}
PortableServer_ServantManager
PortableServer_POA_get_servant_manager (PortableServer_POA poa,
CORBA_Environment *ev)
{
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
return ORBit_RootObject_duplicate (poa->servant_manager);
}
void
PortableServer_POA_set_servant_manager (PortableServer_POA poa,
const PortableServer_ServantManager manager,
CORBA_Environment *ev)
{
poa_sys_exception_if_fail (poa != NULL, ex_CORBA_INV_OBJREF);
poa_sys_exception_if_fail (manager != NULL, ex_CORBA_BAD_PARAM);
poa_sys_exception_if_fail (poa->servant_manager == NULL, ex_CORBA_BAD_INV_ORDER);
poa->servant_manager = (PortableServer_ServantManager)
ORBit_RootObject_duplicate (manager);
}
PortableServer_Servant
PortableServer_POA_get_servant (PortableServer_POA poa,
CORBA_Environment *ev)
{
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
return poa->default_servant;
}
void
PortableServer_POA_set_servant (PortableServer_POA poa,
const PortableServer_Servant servant,
CORBA_Environment *ev)
{
poa_sys_exception_if_fail (poa != NULL, ex_CORBA_INV_OBJREF);
poa_sys_exception_if_fail (servant != NULL, ex_CORBA_BAD_PARAM);
poa->default_servant = servant;
}
PortableServer_ObjectId *
PortableServer_POA_activate_object (PortableServer_POA poa,
const PortableServer_Servant p_servant,
CORBA_Environment *ev)
{
PortableServer_ObjectId *result;
PortableServer_ServantBase *servant = p_servant;
ORBit_POAObject newobj;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (servant != NULL, ex_CORBA_BAD_PARAM, NULL);
POA_LOCK (poa);
/* FIXME: unlock on preconditions */
poa_exception_val_if_fail (IS_RETAIN (poa), ex_PortableServer_POA_WrongPolicy, NULL);
poa_exception_val_if_fail (IS_SYSTEM_ID (poa), ex_PortableServer_POA_WrongPolicy, NULL);
poa_exception_val_if_fail (IS_MULTIPLE_ID (poa) || (IS_UNIQUE_ID (poa) && servant->_private == NULL),
ex_PortableServer_POA_ServantAlreadyActive, NULL);
newobj = ORBit_POA_create_object_T (poa, NULL, ev);
ORBit_POA_activate_object_T (poa, newobj, servant, ev);
result = ORBit_sequence_CORBA_octet_dup (newobj->object_id);
POA_UNLOCK (poa);
return result;
}
void
PortableServer_POA_activate_object_with_id (PortableServer_POA poa,
const PortableServer_ObjectId *objid,
const PortableServer_Servant p_servant,
CORBA_Environment *ev)
{
ORBit_POAObject pobj;
PortableServer_ServantBase *servant = p_servant;
poa_sys_exception_if_fail (poa != NULL, ex_CORBA_INV_OBJREF);
poa_sys_exception_if_fail (objid != NULL, ex_CORBA_BAD_PARAM);
poa_sys_exception_if_fail (servant != NULL, ex_CORBA_BAD_PARAM);
POA_LOCK (poa);
poa_exception_if_fail (IS_RETAIN (poa), ex_PortableServer_POA_WrongPolicy);
pobj = ORBit_POA_object_id_lookup_T (poa, objid);
if (pobj && pobj->servant)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_ObjectAlreadyActive,
NULL);
else if (IS_UNIQUE_ID (poa) && servant->_private != NULL)
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_ServantAlreadyActive,
NULL);
else {
ORBit_POAObject newobj;
if (!pobj)
newobj = ORBit_POA_create_object_T (poa, objid, ev);
else
newobj = pobj;
ORBit_POA_activate_object_T (poa, newobj, servant, ev);
}
ORBit_RootObject_release (pobj);
POA_UNLOCK (poa);
}
void
PortableServer_POA_deactivate_object (PortableServer_POA poa,
const PortableServer_ObjectId *oid,
CORBA_Environment *ev)
{
ORBit_POAObject pobj;
poa_sys_exception_if_fail (poa != NULL, ex_CORBA_INV_OBJREF);
poa_sys_exception_if_fail (oid != NULL, ex_CORBA_BAD_PARAM);
POA_LOCK (poa);
poa_exception_if_fail (IS_RETAIN (poa), ex_PortableServer_POA_WrongPolicy);
pobj = ORBit_POA_object_id_lookup_T (poa, oid);
if (pobj && pobj->servant)
ORBit_POA_deactivate_object_T (poa, pobj, CORBA_TRUE, CORBA_FALSE);
POA_UNLOCK (poa);
ORBit_RootObject_release (pobj);
}
CORBA_Object
PortableServer_POA_create_reference (PortableServer_POA poa,
const CORBA_char *intf,
CORBA_Environment *ev)
{
CORBA_Object obj;
ORBit_POAObject pobj;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
POA_LOCK (poa);
poa_exception_val_if_fail (IS_SYSTEM_ID (poa), ex_PortableServer_POA_WrongPolicy, NULL);
pobj = ORBit_POA_create_object_T (poa, NULL, ev);
obj = ORBit_POA_obj_to_ref (poa, pobj, intf, ev);
POA_UNLOCK (poa);
return obj;
}
CORBA_Object
PortableServer_POA_create_reference_with_id (PortableServer_POA poa,
const PortableServer_ObjectId *oid,
const CORBA_char *intf,
CORBA_Environment *ev)
{
CORBA_Object obj;
ORBit_POAObject pobj, newobj;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (oid != NULL, ex_CORBA_BAD_PARAM, NULL);
POA_LOCK (poa);
pobj = ORBit_POA_object_id_lookup_T (poa, oid);
if (!pobj)
newobj = ORBit_POA_create_object_T (poa, oid, ev);
else
newobj = CORBA_OBJECT_NIL;
obj = ORBit_POA_obj_to_ref (poa, pobj, intf, ev);
if (!newobj)
ORBit_RootObject_release (pobj);
POA_UNLOCK (poa);
return obj;
}
PortableServer_ObjectId *
PortableServer_POA_servant_to_id (PortableServer_POA poa,
const PortableServer_Servant p_servant,
CORBA_Environment *ev)
{
PortableServer_ServantBase *servant = p_servant;
PortableServer_ObjectId *objid;
ORBit_POAObject pobj = servant->_private;
gboolean defserv = IS_USE_DEFAULT_SERVANT (poa);
gboolean retain = IS_RETAIN (poa);
gboolean implicit = IS_IMPLICIT_ACTIVATION (poa);
gboolean unique = IS_UNIQUE_ID (poa);
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (servant != NULL, ex_CORBA_BAD_PARAM, NULL);
POA_LOCK (poa);
poa_exception_val_if_fail (defserv || (retain && (unique || implicit)),
ex_PortableServer_POA_WrongPolicy, NULL);
objid = NULL;
if (retain && unique && pobj && pobj->servant == servant)
objid = ORBit_sequence_CORBA_octet_dup (pobj->object_id);
else if (retain && implicit && (!unique || !pobj)) {
pobj = ORBit_POA_create_object_T (poa, NULL, ev);
ORBit_POA_activate_object_T (poa, pobj, servant, ev);
objid = ORBit_sequence_CORBA_octet_dup (pobj->object_id);
} else {
/*
* FIXME:
* This handles case 3 of the spec; but is broader:
* it matches invokations on any type of servant, not
* just the default servant.
* The stricter form could be implemented,
* but it would only add more code...
*/
objid = ORBit_POA_invocation_stack_lookup_objid (poa, servant);
}
if (!objid)
CORBA_exception_set
(ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_ServantNotActive,
NULL);
POA_UNLOCK (poa);
return objid;
}
CORBA_Object
PortableServer_POA_servant_to_reference (PortableServer_POA poa,
const PortableServer_Servant p_servant,
CORBA_Environment *ev)
{
PortableServer_ServantBase *servant = p_servant;
ORBit_POAObject pobj = servant->_private;
CORBA_Object result;
gboolean retain = IS_RETAIN (poa);
gboolean implicit = IS_IMPLICIT_ACTIVATION (poa);
gboolean unique = IS_UNIQUE_ID (poa);
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, CORBA_OBJECT_NIL);
poa_sys_exception_val_if_fail (servant != NULL, ex_CORBA_BAD_PARAM, CORBA_OBJECT_NIL);
POA_LOCK (poa);
poa_exception_val_if_fail (retain && (unique || implicit),
ex_PortableServer_POA_WrongPolicy,
CORBA_OBJECT_NIL);
result = CORBA_OBJECT_NIL;
if (retain && unique && pobj)
if (pobj->base.objref)
result = ORBit_RootObject_duplicate (pobj->base.objref);
else
result = ORBit_POA_obj_to_ref (poa, pobj, NULL, ev);
else if (retain && implicit && (!unique || !pobj)) {
pobj = ORBit_POA_create_object_T (poa, NULL, ev);
ORBit_POA_activate_object_T (poa, pobj, servant, ev);
result = ORBit_POA_obj_to_ref (poa, pobj, NULL, ev);
} else {
/*
* FIXME:
* This case deals with "invoked in the context of
* executing a request." Note that there are no policy
* restrictions for this case. We must do a forward search
* looking for matching {servant}. If unique, we could
* go backward from servant to pobj to use_cnt, but we
* dont do this since forward search is more general
*/
result = ORBit_POA_invocation_stack_lookup_objref (poa, servant);
}
if (result == CORBA_OBJECT_NIL)
CORBA_exception_set
(ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_ServantNotActive,
NULL);
POA_UNLOCK (poa);
return result;
}
PortableServer_Servant
PortableServer_POA_reference_to_servant (PortableServer_POA poa,
const CORBA_Object reference,
CORBA_Environment *ev)
{
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (reference != NULL, ex_CORBA_BAD_PARAM, NULL);
poa_exception_val_if_fail (IS_USE_DEFAULT_SERVANT (poa) || IS_RETAIN (poa),
ex_PortableServer_POA_WrongPolicy, NULL);
if (IS_RETAIN (poa)) {
ORBit_POAObject pobj;
poa_exception_val_if_fail (reference->adaptor_obj != NULL,
ex_PortableServer_POA_WrongAdapter,
NULL);
pobj = (ORBit_POAObject) reference->adaptor_obj;
if (pobj->servant)
return pobj->servant;
} else if (poa->default_servant)
return poa->default_servant;
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_ObjectNotActive,
NULL);
return NULL;
}
PortableServer_ObjectId *
PortableServer_POA_reference_to_id (PortableServer_POA poa,
const CORBA_Object reference,
CORBA_Environment *ev)
{
ORBit_POAObject pobj;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (reference != NULL, ex_CORBA_BAD_PARAM, NULL);
poa_exception_val_if_fail (reference->adaptor_obj != NULL,
ex_PortableServer_POA_WrongAdapter,
NULL);
pobj = (ORBit_POAObject) reference->adaptor_obj;
return (PortableServer_ObjectId *)
ORBit_sequence_CORBA_octet_dup (pobj->object_id);
}
PortableServer_Servant
PortableServer_POA_id_to_servant (PortableServer_POA poa,
const PortableServer_ObjectId *object_id,
CORBA_Environment *ev)
{
PortableServer_Servant servant = NULL;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (object_id != NULL, ex_CORBA_BAD_PARAM, NULL);
POA_LOCK (poa);
poa_exception_val_if_fail (IS_USE_DEFAULT_SERVANT (poa) || IS_RETAIN (poa),
ex_PortableServer_POA_WrongPolicy, NULL);
if (IS_RETAIN (poa)) {
ORBit_POAObject pobj = ORBit_POA_object_id_lookup_T (poa, object_id);
if (pobj && pobj->servant)
servant = pobj->servant;
ORBit_RootObject_release (pobj);
} else if (poa->default_servant)
servant = poa->default_servant;
if (!servant)
CORBA_exception_set
(ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_ObjectNotActive,
NULL);
POA_UNLOCK (poa);
return NULL;
}
CORBA_Object
PortableServer_POA_id_to_reference (PortableServer_POA poa,
const PortableServer_ObjectId *object_id,
CORBA_Environment *ev)
{
CORBA_Object obj;
ORBit_POAObject pobj;
poa_sys_exception_val_if_fail (poa != NULL, ex_CORBA_INV_OBJREF, NULL);
poa_sys_exception_val_if_fail (object_id != NULL, ex_CORBA_BAD_PARAM, NULL);
POA_LOCK (poa);
poa_exception_val_if_fail (IS_RETAIN (poa), ex_PortableServer_POA_WrongPolicy, NULL);
pobj = ORBit_POA_object_id_lookup_T (poa, object_id);
if (!pobj || !pobj->servant) {
CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
ex_PortableServer_POA_ObjectNotActive, NULL);
obj = CORBA_OBJECT_NIL;
} else {
if (pobj->base.objref)
obj = ORBit_RootObject_duplicate (pobj->base.objref);
else
obj = ORBit_POA_obj_to_ref (poa, pobj, NULL, ev);
}
POA_UNLOCK (poa);
ORBit_RootObject_release (pobj);
return obj;
}
void
ORBit_poa_init (void)
{
ORBit_class_assignment_lock = link_mutex_new ();
_ORBit_poa_manager_lock = link_mutex_new ();
giop_thread_set_main_handler (ORBit_POAObject_invoke_incoming_request);
}
gboolean
ORBit_poa_allow_cross_thread_call (ORBit_POAObject pobj,
ORBit_IMethodFlag method_flags)
{
gpointer key = NULL;
GIOPThread *self;
PortableServer_POA poa = pobj->poa;
if (!poa)
return TRUE;
self = giop_thread_self ();
switch (poa->p_thread) {
case PortableServer_SINGLE_THREAD_MODEL:
break;
case PortableServer_ORB_CTRL_MODEL: {
ORBit_ObjectAdaptor adaptor = (ORBit_ObjectAdaptor) poa;
if (method_flags & ORBit_I_METHOD_1_WAY)
return FALSE;
switch (adaptor->thread_hint) {
case ORBIT_THREAD_HINT_PER_OBJECT:
key = pobj;
break;
case ORBIT_THREAD_HINT_PER_POA:
key = poa;
break;
case ORBIT_THREAD_HINT_PER_CONNECTION:
/* FIXME: ? */
case ORBIT_THREAD_HINT_PER_REQUEST:
return TRUE;
break;
case ORBIT_THREAD_HINT_ONEWAY_AT_IDLE:
case ORBIT_THREAD_HINT_ALL_AT_IDLE:
case ORBIT_THREAD_HINT_ON_CONTEXT:
/* FIXME: need GThread *g_main_context_get_owner()
to do this right ... */
case ORBIT_THREAD_HINT_NONE:
break;
}
break;
}
}
giop_thread_new_check (self);
if (!key)
return (self == giop_thread_get_main ());
else
return giop_thread_same_key (key, TRUE);
}
static gpointer
get_c_method (CORBA_Object obj,
glong class_id,
PortableServer_ServantBase **servant,
glong method_offset,
ORBit_IMethodFlag method_flags)
{
guchar *epv_start;
ORBit_POAObject pobj;
if (!obj ||
!(pobj = (ORBit_POAObject) obj->adaptor_obj) ||
!(pobj->base.interface->adaptor_type & ORBIT_ADAPTOR_POA) ||
!(*servant = (PortableServer_ServantBase *) pobj->servant))
return NULL;
if (method_offset <= 0 || class_id <= 0)
return NULL;
if (!ORBit_poa_allow_cross_thread_call (pobj, method_flags))
return NULL;
if (ORBit_small_flags & ORBIT_SMALL_FORCE_GENERIC_MARSHAL)
return NULL;
/*
* FIXME: we could propagate the size of the vepvmap_cache
* to here, and check it to avoid some really bogus stuff.
*/
if (!class_id || !pobj->vepvmap_cache ||
class_id >= VEPV_CACHE_SIZE (pobj->vepvmap_cache) )
return NULL;
epv_start = (guchar *) (*servant)->vepv [ pobj->vepvmap_cache [class_id] ];
if (!epv_start)
return NULL;
return *(gpointer *)(epv_start + method_offset);
}
void
ORBit_c_stub_invoke (CORBA_Object obj,
ORBit_IMethods *methods,
glong method_index,
gpointer ret,
gpointer args,
CORBA_Context ctx,
CORBA_Environment *ev,
glong class_id,
glong method_offset,
ORBitSmallSkeleton skel_impl)
{
gpointer method_impl;
PortableServer_ServantBase *servant;
if (method_index < 0 || method_index > methods->_length) {
CORBA_exception_set_system (ev, ex_CORBA_NO_IMPLEMENT,
CORBA_COMPLETED_NO);
return;
}
if (skel_impl &&
(method_impl = get_c_method (obj, class_id,
&servant, method_offset,
methods->_buffer[method_index].flags))) {
/* Unwound PreCall
POA_LOCK (((ORBit_POAObject)(obj)->adaptor_obj)->poa);
++( ((ORBit_POAObject)(obj)->adaptor_obj)->use_cnt );
POA_UNLOCK (((ORBit_POAObject)(obj)->adaptor_obj)->poa);
(obj)->orb->current_invocations =
g_slist_prepend ((obj)->orb->current_invocations,
(obj)->adaptor_obj);
*/
CORBA_exception_init (ev);
skel_impl (servant, ret, args, ctx, ev, method_impl);
/* Unwound PostCall
(obj)->orb->current_invocations =
g_slist_remove ((obj)->orb->current_invocations, pobj);
POA_LOCK (((ORBit_POAObject)(obj)->adaptor_obj)->poa);
--(((ORBit_POAObject)(obj)->adaptor_obj)->use_cnt);
if (((ORBit_POAObject)(obj)->adaptor_obj)->life_flags & ORBit_LifeF_NeedPostInvoke)
ORBit_POAObject_post_invoke (((ORBit_POAObject)(obj)->adaptor_obj));
POA_UNLOCK (((ORBit_POAObject)(obj)->adaptor_obj)->poa);
*/
} else
ORBit_small_invoke_stub_n
(obj, methods, method_index,
ret, args, ctx, ev);
}
syntax highlighted by Code2HTML, v. 0.9.1