Home | History | Annotate | Download | only in invo
      1 //
      2 // Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      3 // Use is subject to license terms.
      4 //
      5 
      6 #pragma ident	"@(#)corba.cc	1.94	08/07/05 SMI"
      7 
      8 //
      9 // $XConsortium$
     10 //
     11 
     12 //
     13 // Copyright (c) 1993-94 Silicon Graphics, Inc.
     14 // Copyright (c) 1993-94 Fujitsu, Ltd.
     15 //
     16 // Permission to use, copy, modify, distribute, and sell this software and
     17 // its documentation for any purpose is hereby granted without fee, provided
     18 // that (i) the above copyright notices and this permission notice appear in
     19 // all copies of the software and related documentation, and (ii) the names of
     20 // Silicon Graphics and Fujitsu may not be used in any advertising or
     21 // publicity relating to the software without the specific, prior written
     22 // permission of Silicon Graphics and Fujitsu.
     23 //
     24 // THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
     25 // EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
     26 // WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
     27 //
     28 // IN NO EVENT SHALL SILICON GRAPHICS OR FUJITSU BE LIABLE FOR
     29 // ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
     30 // OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     31 // WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
     32 // LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     33 // OF THIS SOFTWARE.
     34 //
     35 
     36 //
     37 // Base object, type, Environment, Exception support.
     38 //
     39 
     40 //
     41 // Protect includes so that this file can be used with a different set
     42 // of include files.
     43 //
     44 
     45 #include <orb/invo/common.h>
     46 #include <orb/object/schema.h>
     47 #include <orb/invo/invocation.h>
     48 #include <orb/handler/handler.h>
     49 #include <sys/os.h>
     50 #include <sys/mc_probe.h>
     51 #include <orb/fault/fault_injection.h>
     52 
     53 #include <h/version.h>
     54 
     55 #ifdef	_KERNEL_ORB
     56 #include <orb/xdoor/rxdoor.h>
     57 #include <orb/member/members.h>
     58 #include <orb/msg/orb_msg.h>
     59 #include <orb/infrastructure/orb_conf.h>
     60 #endif
     61 
     62 //	Predefined object type ids
     63 // Keep 0 free to catch/avoid uninitialized ids
     64 //
     65 // The CORBA object id must be defined prior to _CORBA_Object_type_index
     66 //
     67 uint32_t _Ix__tid(CORBA_Object_0)[4] = { 0, 0, 0, 1 };
     68 
     69 //
     70 // class CORBA::Object methods
     71 //
     72 
     73 CORBA::Object::Object()
     74 {
     75 }
     76 
     77 CORBA::Object::~Object()
     78 {
     79 }
     80 
     81 //
     82 // CORBA::Object is a special case object.
     83 // The IDL compiler internally defines a CORBA::Object interface
     84 // so we can't redefine CORBA::Object using the IDL compiler directly.
     85 // We do want to provide certain methods on CORBA::Object though for
     86 // internal use so we have a corba.idl file to generate the code and
     87 // then we need to copy it here and fix up the names slightly.
     88 //
     89 // Define stub code.
     90 // Note that we depend on version.idl being compiled
     91 // and linked with the ORB for the inf_descriptor marshal functions.
     92 //
     93 extern MarshalInfo_complex _inf_typeid_ArgMarshalFuncs;
     94 extern MarshalInfo_complex _inf_descriptor_ArgMarshalFuncs;
     95 
     96 static arg_desc _CORBA_Object__get_dynamic_descriptor_pdesc[2] = {
     97 	0x2, 0x5
     98 };
     99 static arg_sizes _CORBA_Object__get_dynamic_descriptor_argsizes = {
    100 	2, 4, 0, 0, 0, 2, 0, 0
    101 };
    102 static ArgMarshalFuncs _CORBA_Object__get_dynamic_descriptor_pfunc[2] = {
    103 	ArgMarshalFuncs(&_inf_typeid_ArgMarshalFuncs),		//lint !e708
    104 	ArgMarshalFuncs(&_inf_descriptor_ArgMarshalFuncs)	//lint !e708
    105 };
    106 static arg_info _CORBA_Object__get_dynamic_descriptor_pinfo(
    107 	_Ix__tid(CORBA_Object_0),
    108 	0,
    109 	_CORBA_Object__get_dynamic_descriptor_pdesc,
    110 	_CORBA_Object__get_dynamic_descriptor_pfunc,
    111 	&_CORBA_Object__get_dynamic_descriptor_argsizes,
    112 	invocation_mode::NONE);
    113 
    114 //
    115 // Stub routine.
    116 //
    117 inf_descriptor *
    118 CORBA::Object_stub::_get_dynamic_descriptor(const inf_typeid tid,
    119     Environment &_environment)
    120 {
    121 	MC_PROBE_0(CORBA_Object__get_dynamic_descriptor_start,
    122 		" CORBA_Object clustering", "");
    123 	handler *_handlerp = _handler();
    124 	ExceptionStatus _status;
    125 	CORBA::Object_ptr this_obj;
    126 	inf_descriptor *_result = NULL;
    127 
    128 	do {
    129 		this_obj = (CORBA::Object_ptr)
    130 		    _handlerp->local_invoke(_Ix__tid(CORBA_Object_0),
    131 			_deep_type(), _environment);
    132 		if (CORBA::is_nil(this_obj)) {
    133 			ArgValue _arg[2];
    134 			_arg[0].t_addr = &_result;
    135 			_arg[1].t_addr = tid;
    136 			_status = _handlerp->invoke(
    137 			    _CORBA_Object__get_dynamic_descriptor_pinfo,
    138 			    _arg, _deep_type(), _environment);
    139 		} else if (_environment.exception() != NULL) {
    140 			_status = CORBA::LOCAL_EXCEPTION;
    141 			break;
    142 		} else {
    143 			InterfaceDescriptor *infp =
    144 			    OxSchema::schema()->descriptor(
    145 				(const CORBA::TypeId)tid, NULL);
    146 			if (infp != NULL)
    147 				_result = infp->get_inf_descriptor();
    148 			_status = _handlerp->local_invoke_done(_environment);
    149 		}
    150 	} while (_status == CORBA::RETRY_EXCEPTION);
    151 
    152 	MC_PROBE_0(CORBA_Object__get_dynamic_descriptor_end,
    153 		" CORBA_Object clustering", "");
    154 	return (_result);
    155 }
    156 
    157 //
    158 // Marshal time support functions for CORBA::octet_seq_t
    159 //
    160 
    161 void
    162 _CORBA_octet_seq_t_put(service &_b, void *voidp)
    163 {
    164 	CORBA::octet_seq_t *sequencep = (CORBA::octet_seq_t *)voidp;
    165 	_b.put_seq(sequencep, (unsigned)sizeof (uint8_t));
    166 }
    167 
    168 void
    169 _CORBA_octet_seq_t_get(service &_b, void *voidp)
    170 {
    171 	CORBA::octet_seq_t *sequencep = (CORBA::octet_seq_t *)voidp;
    172 	_b.get_seq(sequencep, (unsigned)sizeof (uint8_t));
    173 }
    174 
    175 void *
    176 _CORBA_octet_seq_t_makef()
    177 {
    178 	return (new CORBA::octet_seq_t);
    179 }
    180 
    181 void
    182 _CORBA_octet_seq_t_freef(void *voidp)
    183 {
    184 	CORBA::octet_seq_t *sequencep = (CORBA::octet_seq_t *)voidp;
    185 	delete sequencep;
    186 }
    187 
    188 void
    189 _CORBA_octet_seq_t_release(void *voidp)
    190 {
    191 	CORBA::octet_seq_t *sequencep = (CORBA::octet_seq_t *)voidp;
    192 	sequencep->load(0, 0, NULL, false);
    193 }
    194 
    195 uint_t
    196 _CORBA_octet_seq_t_marshal_size(void *voidp)
    197 {
    198 	CORBA::octet_seq_t *sequencep = (CORBA::octet_seq_t *)voidp;
    199 	return (sequencep->_marshal_size() +
    200 		(sequencep->length() * (unsigned)sizeof (uint8_t)));
    201 }
    202 
    203 MarshalInfo_complex _CORBA_octet_seq_t_ArgMarshalFuncs = {
    204 	&_CORBA_octet_seq_t_put,
    205 	&_CORBA_octet_seq_t_get,
    206 	&_CORBA_octet_seq_t_makef,
    207 	&_CORBA_octet_seq_t_freef,
    208 	&_CORBA_octet_seq_t_release,
    209 	NULL,
    210 	&_CORBA_octet_seq_t_marshal_size
    211 };
    212 
    213 extern MarshalInfo_object _CORBA_Object_ArgMarshalFuncs;
    214 
    215 //
    216 // Marshal time support functions for CORBA::object_seq_t
    217 //
    218 
    219 void
    220 _CORBA_object_seq_t_put(service &_b, void *voidp)
    221 {
    222 	CORBA::object_seq_t *sequencep = (CORBA::object_seq_t *)voidp;
    223 	sequencep->_put(_b);
    224 }
    225 
    226 void
    227 _CORBA_object_seq_t_get(service &_b, void *voidp)
    228 {
    229 	CORBA::object_seq_t *sequencep = (CORBA::object_seq_t *)voidp;
    230 	sequencep->_get(_b, &_CORBA_Object_ArgMarshalFuncs);
    231 }
    232 
    233 void *
    234 _CORBA_object_seq_t_makef()
    235 {
    236 	return (new CORBA::object_seq_t);
    237 }
    238 
    239 void
    240 _CORBA_object_seq_t_freef(void *voidp)
    241 {
    242 	CORBA::object_seq_t *sequencep = (CORBA::object_seq_t *)voidp;
    243 	delete sequencep;
    244 }
    245 
    246 void
    247 _CORBA_object_seq_t_release(void *voidp)
    248 {
    249 	CORBA::object_seq_t *sequencep = (CORBA::object_seq_t *)voidp;
    250 	sequencep->load(0, 0, NULL, false);
    251 }
    252 
    253 void
    254 _CORBA_object_seq_t_unput(void *voidp)
    255 {
    256 	CORBA::object_seq_t *sequencep = (CORBA::object_seq_t *)voidp;
    257 	sequencep->_unput();
    258 }
    259 
    260 uint_t
    261 _CORBA_object_seq_t_marshal_size(void *voidp)
    262 {
    263 	CORBA::object_seq_t *sequencep = (CORBA::object_seq_t *)voidp;
    264 	return (sequencep->_marshal_size() +
    265 		0);
    266 }
    267 
    268 MarshalInfo_complex _CORBA_object_seq_t_ArgMarshalFuncs = {
    269 	&_CORBA_object_seq_t_put,
    270 	&_CORBA_object_seq_t_get,
    271 	&_CORBA_object_seq_t_makef,
    272 	&_CORBA_object_seq_t_freef,
    273 	&_CORBA_object_seq_t_release,
    274 	&_CORBA_object_seq_t_unput,
    275 	&_CORBA_object_seq_t_marshal_size
    276 };
    277 
    278 static arg_desc _CORBA_Object__generic_method_pdesc[3] = {
    279 	0xc2, 0xb, 0xb
    280 };
    281 static arg_sizes _CORBA_Object__generic_method_argsizes = {
    282 	3, 0, 0, 0, 0, 2, 0, 2
    283 };
    284 ArgMarshalFuncs _CORBA_Object__generic_method_pfunc[3] = {
    285 	ArgMarshalFuncs(&_CORBA_octet_seq_t_ArgMarshalFuncs),	//lint !e708
    286 	ArgMarshalFuncs(&_CORBA_object_seq_t_ArgMarshalFuncs),	//lint !e708
    287 	ArgMarshalFuncs()					//lint !e708
    288 };
    289 arg_info _CORBA_Object__generic_method_pinfo(
    290 	_Ix__tid(CORBA_Object_0),
    291 	1,
    292 	_CORBA_Object__generic_method_pdesc,
    293 	_CORBA_Object__generic_method_pfunc,
    294 	&_CORBA_Object__generic_method_argsizes,
    295 	invocation_mode::NONE);
    296 
    297 //
    298 // Stub routine.
    299 //
    300 void
    301 CORBA::Object_stub::_generic_method(octet_seq_t &data, object_seq_t &objs,
    302     Environment &_environment)
    303 {
    304 	MC_PROBE_0(CORBA_Object__generic_method_start,
    305 		" CORBA_Object clustering", "");
    306 	handler *_handlerp = _handler();
    307 	CORBA::Object_ptr this_obj;
    308 	ExceptionStatus _status;
    309 
    310 	do {
    311 		this_obj = (CORBA::Object_ptr)
    312 		    _handlerp->local_invoke(_Ix__tid(CORBA_Object_0),
    313 			_deep_type(), _environment);
    314 		if (CORBA::is_nil(this_obj)) {
    315 			ArgValue _arg[3];
    316 			_arg[1].t_addr = &data;
    317 			_arg[2].t_addr = &objs;
    318 			_status = _handlerp->invoke(
    319 			    _CORBA_Object__generic_method_pinfo,
    320 			    _arg, _deep_type(), _environment);
    321 		} else if (_environment.exception() != NULL) {
    322 			_status = CORBA::LOCAL_EXCEPTION;
    323 			break;
    324 		} else {
    325 			this_obj->_generic_method(data, objs, _environment);
    326 			_status = _handlerp->local_invoke_done(_environment);
    327 		}
    328 	} while (_status == CORBA::RETRY_EXCEPTION);
    329 
    330 	MC_PROBE_0(CORBA_Object__generic_method_end,
    331 		" CORBA_Object clustering", "");
    332 }
    333 
    334 static InterfaceDescriptor::VersionTable _Ix_type_index(CORBA_Object)[] = {
    335 	{ NULL, 0 },
    336 	{ NULL, 0 }
    337 };
    338 
    339 void *
    340 _Ix_CreateProxy(CORBA_Object)(handler *handlerp, InterfaceDescriptor *infp)
    341 {
    342 	return (new proxy<CORBA::Object_stub>(handlerp, infp));
    343 }
    344 
    345 //
    346 // Provide a structure containing all of the information needed to
    347 // support marshal time operations on the CORBA::Object.
    348 //
    349 MarshalInfo_object	_CORBA_Object_ArgMarshalFuncs = {
    350 	&_Ix_CreateProxy(CORBA_Object),
    351 	_Ix__tid(CORBA_Object_0)
    352 };
    353 
    354 //
    355 // Skel code for _get_dynamic_descriptor() method.
    356 // Note that this code is basically the same as
    357 // idlversion::_get_dynamic_descriptor() except we are operating on
    358 // the object of interest rather than an idlversion object.
    359 // See OxSchema::descriptor() for details.
    360 //
    361 static void
    362 _CORBA_Object__get_dynamic_descriptor_receive(void *objectp, service &_stream)
    363 {
    364 	MC_PROBE_0(CORBA_Object__get_dynamic_descriptor_skel_start,
    365 		" CORBA::Object clustering", "");
    366 	CORBA::Object_ptr _this = (CORBA::Object_ptr)objectp;
    367 	ArgValue _arg[2];
    368 	inf_descriptor *_result = NULL;
    369 	inf_typeid tid;
    370 	_arg[1].t_addr = tid;
    371 	_stream.unmarshal_receive(_CORBA_Object__get_dynamic_descriptor_pinfo,
    372 	    _arg);
    373 	FAULTPT_ORPHAN(FAULTNUM_ORB_GET_DESCRIPTOR, FaultFunctions::generic);
    374 	InterfaceDescriptor *infp = OxSchema::schema()->descriptor(
    375 	    (const CORBA::TypeId)tid, NULL);
    376 	if (infp != NULL)
    377 		_result = infp->get_inf_descriptor();
    378 	_arg[0].t_addr = &_result;
    379 	_stream.send_reply(_this, _CORBA_Object__get_dynamic_descriptor_pinfo,
    380 	    _arg);
    381 	MC_PROBE_0(CORBA_Object__get_dynamic_descriptor_skel_end,
    382 		" CORBA::Object clustering", "");
    383 }
    384 
    385 static void
    386 _CORBA_Object__generic_method_receive(void *objectp, service &_stream)
    387 {
    388 	MC_PROBE_0(CORBA_Object__generic_method_skel_start,
    389 		" CORBA_Object clustering", "");
    390 	CORBA::Object_ptr _this = (CORBA::Object_ptr)objectp;
    391 	Environment &_environment = *(_stream.get_env());
    392 	ArgValue _arg[3];
    393 	CORBA::octet_seq_t data;
    394 	_arg[1].t_addr = &data;
    395 	CORBA::object_seq_t objs;
    396 	_arg[2].t_addr = &objs;
    397 	_stream.unmarshal_receive(_CORBA_Object__generic_method_pinfo, _arg);
    398 	_this->_generic_method(data, objs, _environment);
    399 	_stream.send_reply(_this, _CORBA_Object__generic_method_pinfo, _arg);
    400 	MC_PROBE_0(CORBA_Object__generic_method_skel_end,
    401 		" CORBA_Object clustering", "");
    402 }
    403 
    404 static InterfaceDescriptor::ReceiverFunc _CORBA_Object_receive_table[2] = {
    405 	_CORBA_Object__get_dynamic_descriptor_receive,
    406 	_CORBA_Object__generic_method_receive
    407 };
    408 
    409 static InterfaceDescriptor::ReceiverTable _Ix_index_func(CORBA_Object)[] = {
    410 	{ 2, _CORBA_Object_receive_table },
    411 };
    412 
    413 InterfaceDescriptor _Ix__type(CORBA_Object)(
    414 	"CORBA::Object_0",
    415 	_Ix__tid(CORBA_Object_0),
    416 	_Ix__tid(CORBA_Object_0),
    417 	0,
    418 	NULL,
    419 	_Ix_type_index(CORBA_Object),
    420 	_Ix_index_func(CORBA_Object),
    421 	&_Ix_CreateProxy(CORBA_Object));
    422 
    423 //
    424 // Use the _ix_schema data structure to load info about the CORBA Object class
    425 // into the overall schema.
    426 //
    427 static InterfaceDescriptor *_ix_schema[] = {
    428 	&_CORBA_Object_type,
    429 	NULL
    430 };
    431 
    432 //
    433 // Lint complains about OxInitSchema not having any data members
    434 // See bugid 4244933
    435 //
    436 static OxInitSchema _ix_init_schema(_ix_schema);	//lint !e1502
    437 
    438 //
    439 // _duplicate - every object inherits from CORBA::Object.
    440 // Increment the object reference count.
    441 //
    442 CORBA::Object_ptr
    443 CORBA::Object::_duplicate(CORBA::Object_ptr object_p)
    444 {
    445 	return ((CORBA::Object_ptr)(is_nil(object_p) ? nil :
    446 	    object_p->_handler()->duplicate(object_p,
    447 		_Ix__tid(CORBA_Object_0))));
    448 }
    449 
    450 //
    451 // _ox_cast - Cast is assumed always to be called on a non-nil object reference
    452 // which has methods and with known type ids.
    453 // This is called by the stub method for local invocations.
    454 // NULL is returned if the object cannot be cast to the requested type.
    455 //
    456 void *
    457 _ox_cast(CORBA::Object_ptr object_p, CORBA::TypeId ancestor_tid)
    458 {
    459 	ASSERT(object_p != NULL);
    460 	//
    461 	// Note that we are using the interface descriptor that is
    462 	// known at the time the stub code for the object was compiled
    463 	// rather than the dynamic interface descriptor.
    464 	// However, we don't allow invocations if the server object
    465 	// doesn't support them (newer client with older server).
    466 	//
    467 	InterfaceDescriptor &idesc = *object_p->_interface_descriptor();
    468 	int inf_index = idesc.lookup_type_index(ancestor_tid, true);
    469 	if (inf_index < 0)
    470 		return (NULL);
    471 	InterfaceDescriptor *infp = object_p->_deep_type();
    472 	if (infp != &idesc && !infp->is_type_supported(ancestor_tid))
    473 		return (NULL);
    474 	return (idesc.cast(object_p->_this_ptr(), (uint_t)inf_index));
    475 }
    476 
    477 //
    478 // _ox_equal_tid - Compare two type ids. All tids use MD5 tids
    479 //
    480 bool
    481 _ox_equal_tid(CORBA::TypeId tid1, CORBA::TypeId tid2)
    482 {
    483 	ASSERT(tid1 != NULL);
    484 	ASSERT(tid2 != NULL);
    485 	//
    486 	// Optimization for the case the two tid ptrs are same
    487 	// This is common because we allocate tids statically
    488 	//
    489 	if (tid1 == tid2) {
    490 		return (true);
    491 	}
    492 	// A type id contains 4 words.
    493 	// The full check compares each word.
    494 	//
    495 	for (int i = 0; i < 4; i++, tid1++, tid2++) {
    496 		if (*tid1 != *tid2) {
    497 			return (false);
    498 		}
    499 	}
    500 	return (true);
    501 }
    502 
    503 //
    504 // _ox_put_tid - Put a type id into a marshal buffer.
    505 // All TypeId's are MD5 digests.
    506 //
    507 void
    508 _ox_put_tid(service &serv, CORBA::TypeId tid)
    509 {
    510 	serv.put_bytes(tid, (uint_t)sizeof (CORBA::MD5_Tid));
    511 }
    512 
    513 //
    514 // _ox_get_tid - Get a type id from the marshal buffer.
    515 // Use the given typeid buffer (all TypeId's are MD5 digests)
    516 //
    517 void
    518 _ox_get_tid(service &serv, CORBA::TypeId tid)
    519 {
    520 	serv.get_bytes(tid, (uint_t)sizeof (CORBA::MD5_Tid));
    521 }
    522 
    523 bool
    524 CORBA::Object::_equiv(Object_ptr ob2)
    525 {
    526 	return (_handler()->equiv(this, ob2));
    527 }
    528 
    529 uint_t
    530 CORBA::Object::_hash(uint_t sz)
    531 {
    532 	return (_handler()->hash(sz));
    533 }
    534 
    535 void *
    536 CORBA::Object::_this_ptr()
    537 {
    538 	return (this);
    539 }
    540 
    541 //
    542 // Return the compiled-in InterfaceDescriptor pointer for this class.
    543 //
    544 InterfaceDescriptor *
    545 CORBA::Object::_interface_descriptor()
    546 {
    547 	return (&_CORBA_Object_type);
    548 }
    549 
    550 //
    551 // Return the dynamic InterfaceDescriptor pointer for this class.
    552 //
    553 InterfaceDescriptor *
    554 CORBA::Object::_deep_type()
    555 {
    556 	return (_interface_descriptor());
    557 }
    558 
    559 //
    560 // Return the version number of the given object reference or 0 if nil.
    561 //
    562 int
    563 CORBA::Object::_version(CORBA::Object_ptr object_p)
    564 {
    565 	return (is_nil(object_p) ? -1 :
    566 	    object_p->_deep_type()->get_version(_Ix__tid(CORBA_Object_0)));
    567 }
    568 
    569 //
    570 // Return the type info for CORBA::Object.
    571 //
    572 CORBA::type_info_t *
    573 CORBA::Object::_get_type_info(int v)
    574 {
    575 	return (_Ix__type(CORBA_Object).get_type_info(v));
    576 }
    577 
    578 generic_proxy *
    579 CORBA::Object::_this_component_ptr()
    580 {
    581 	ASSERT(0);
    582 	return (NULL);
    583 }
    584 
    585 bool
    586 CORBA::Object::_is_local()
    587 {
    588 	return (_handler()->is_local());
    589 }
    590 
    591 bool
    592 CORBA::Object::_supports_type(type_info_t *tp)
    593 {
    594 	return (_deep_type()->is_type_supported(
    595 	    ((InterfaceDescriptor *)tp)->get_tid()));
    596 }
    597 
    598 //
    599 // Default implementation for generic method for those interfaces which
    600 // don't need it.
    601 //
    602 void
    603 CORBA::Object::_generic_method(octet_seq_t &, object_seq_t &, Environment &e)
    604 {
    605 	// Throw an unimplemented method exception.
    606 	e.system_exception(VERSION());
    607 }
    608 
    609 //
    610 // Release an object reference.  This operation is just forwarded on
    611 // to the exchange.  The this pointer is passed as a parameter so that
    612 // the exchange can decide to delete this object.
    613 //
    614 void
    615 CORBA::release(CORBA::Object_ptr obj)
    616 {
    617 	if (is_not_nil(obj)) {
    618 		obj->_handler()->release(obj);
    619 	}
    620 }
    621 
    622 //
    623 // Return a proxy object of the given type.
    624 //
    625 CORBA::Object_ptr
    626 CORBA::create_proxy_obj(type_info_t *tp, handler *hp)
    627 {
    628 	if (tp == NULL || hp == NULL) {
    629 		return (CORBA::Object::_nil());
    630 	}
    631 	CORBA::Object_ptr objp =
    632 	    ((InterfaceDescriptor *)tp)->create_proxy_obj(hp,
    633 		(InterfaceDescriptor *)tp);
    634 	if (is_not_nil(objp)) {
    635 		hp->new_reference();
    636 	}
    637 	return (objp);
    638 }
    639 
    640 //
    641 // exception_data macro - declares fixed data for exceptions,
    642 // and avoids error prone manual declarations.
    643 //
    644 // The id's rely on the large id name space to prevent collisions.
    645 // The convention is to use the major number of the system exception
    646 // in the type id. The exceptions are declared in corba.h
    647 // The IDL compiler generates the type ids for user exceptions.
    648 //
    649 #define	exception_data(except) {{except ## _major, 0, 0, 0}, #except}
    650 
    651 exception_major_data	major_translation[] = {
    652     exception_data(UserException),
    653     exception_data(SystemException),
    654     exception_data(BAD_PARAM),
    655     exception_data(COMM_FAILURE),
    656     exception_data(INV_OBJREF),
    657     exception_data(WOULDBLOCK),
    658     exception_data(RETRY_NEEDED),
    659     exception_data(PRIMARY_FROZEN),
    660     exception_data(VERSION_Exception),
    661     exception_data(CTX_EACCESS),
    662     exception_data(NS_EPERM)
    663 };
    664 
    665 //
    666 // class CORBA::Exception methods
    667 //
    668 
    669 //
    670 // Default Destructor - most exceptions do nothing in the destructor,
    671 // and those exceptions use this default destructor. However a small number
    672 // of UserException objects need to do something, and they provide their
    673 // own destructor.
    674 //
    675 // Lint complains about not zeroing some pointers in destructor
    676 //lint -e1540
    677 CORBA::Exception::~Exception()
    678 {
    679 }
    680 //lint +e1540
    681 
    682 //
    683 // class CORBA::SystemException
    684 //
    685 
    686 CORBA::SystemException::SystemException(uint_t major_, uint_t minor_,
    687     CompletionStatus compstat) :
    688 	Exception(major_, major_translation[major_].tid(),
    689 	    major_translation[major_].name),
    690 	_minor_(minor_),
    691 	_completed_(compstat)
    692 {
    693 }
    694 
    695 bool
    696 CORBA::SystemException::is_system_exception()
    697 {
    698 	return (true);
    699 }
    700 
    701 CORBA::SystemException *
    702 CORBA::SystemException::_exnarrow(Exception *exceptp)
    703 {
    704 	if (exceptp != NULL && exceptp->is_system_exception()) {
    705 		return ((CORBA::SystemException *)exceptp);
    706 	} else {
    707 		return (NULL);
    708 	}
    709 }
    710 
    711 static const char *
    712 completion_status_str(CORBA::CompletionStatus c)
    713 {
    714 	switch (c) {
    715 	case CORBA::COMPLETED_NO:
    716 		return ("NO");
    717 	case CORBA::COMPLETED_YES:
    718 		return ("YES");
    719 	case CORBA::COMPLETED_MAYBE:
    720 		return ("MAYBE");
    721 	default :
    722 		ASSERT(!"Invalid CompletionStatus");
    723 	}
    724 	return (NULL);
    725 }
    726 
    727 void
    728 CORBA::SystemException::print_exception(char *msg)
    729 {
    730 	void (*prf)(const char *, ...);
    731 	prf = os::printf;
    732 
    733 #ifdef _KERNEL
    734 	if (*msg == '!') {
    735 		prf = os::prom_printf;
    736 		msg++;
    737 	}
    738 #endif
    739 
    740 #ifndef _KERNEL
    741 	prf("%s SystemException: %s major %d minor %d %s completed %s\n",
    742 	    msg,  _name() ? _name() : "<Null Name>", _major(), _minor(),
    743 	    strerror((int)_minor()) ? strerror((int)_minor()) : "",
    744 	    completion_status_str(completed()));
    745 #else
    746 	    // XX WOuld be nice to have a kernel strerror
    747 	prf("%s SystemException: %s major %d minor %d completed %s\n",
    748 	    msg,  _name() ? _name() : "<Null Name>", _major(), _minor(),
    749 	    completion_status_str(completed()));
    750 #endif
    751 }
    752 
    753 void
    754 CORBA::SystemException::_put(service &_b) const
    755 {
    756 	_put(_b.se->get_MainBuf());
    757 }
    758 
    759 void
    760 CORBA::SystemException::_put(MarshalStream &_m) const
    761 {
    762 	_m.put_unsigned_long(CORBA::SYSTEM_EXCEPTION);
    763 	_m.put_unsigned_long(_major_);
    764 	_m.put_unsigned_long(_minor_);
    765 	_m.put_long((int32_t)_completed_);
    766 }
    767 
    768 //
    769 // class CORBA::UserException
    770 //
    771 
    772 bool
    773 CORBA::UserException::is_system_exception()
    774 {
    775 	return (false);
    776 }
    777 
    778 CORBA::UserException *
    779 CORBA::UserException::_exnarrow(Exception *exceptp)
    780 {
    781 	if (exceptp != NULL && !exceptp->is_system_exception()) {
    782 		return ((CORBA::UserException *)exceptp);
    783 	} else {
    784 		return (NULL);
    785 	}
    786 }
    787 
    788 void
    789 CORBA::UserException::_put(service &serv) const
    790 {
    791 	serv.put_unsigned_long(CORBA::USER_EXCEPTION);
    792 	_ox_put_tid(serv, tid);
    793 }
    794 
    795 void
    796 #ifdef DEBUG
    797 CORBA::UserException::print_exception(char *msg)
    798 #else
    799 CORBA::UserException::print_exception(char *)
    800 #endif
    801 {
    802 #ifdef DEBUG
    803 	void (*prf)(const char *, ...);
    804 	prf = os::printf;
    805 
    806 #ifdef _KERNEL
    807 	if (*msg == '!') {
    808 		prf = os::prom_printf;
    809 		msg++;
    810 	}
    811 #endif
    812 
    813 	prf("%s UserException: %s major %d\n",
    814 	    msg, _name() ? _name() : "<Null Name>", _major());
    815 #endif
    816 }
    817 
    818 //
    819 // An ancestor class has a virtual destructor.
    820 // Avoid multiple copies by defining this function.
    821 //
    822 CORBA::BAD_PARAM::~BAD_PARAM()
    823 {
    824 }
    825 
    826 //
    827 // An ancestor class has a virtual destructor.
    828 // Avoid multiple copies by defining this function.
    829 //
    830 CORBA::COMM_FAILURE::~COMM_FAILURE()
    831 {
    832 }
    833 
    834 //
    835 // An ancestor class has a virtual destructor.
    836 // Avoid multiple copies by defining this function.
    837 //
    838 CORBA::INV_OBJREF::~INV_OBJREF()
    839 {
    840 }
    841 
    842 //
    843 // An ancestor class has a virtual destructor.
    844 // Avoid multiple copies by defining this function.
    845 //
    846 CORBA::WOULDBLOCK::~WOULDBLOCK()
    847 {
    848 }
    849 
    850 //
    851 // An ancestor class has a virtual destructor.
    852 // Avoid multiple copies by defining this function.
    853 //
    854 CORBA::RETRY_NEEDED::~RETRY_NEEDED()
    855 {
    856 }
    857 
    858 //
    859 // An ancestor class has a virtual destructor.
    860 // Avoid multiple copies by defining this function.
    861 //
    862 CORBA::PRIMARY_FROZEN::~PRIMARY_FROZEN()
    863 {
    864 }
    865 
    866 CORBA::VERSION::~VERSION()
    867 {
    868 }
    869 
    870 //
    871 // An ancestor class has a virtual destructor.
    872 // Avoid multiple copies by defining this function.
    873 //
    874 CORBA::CTX_EACCESS::~CTX_EACCESS()
    875 {
    876 }
    877 
    878 //
    879 // An ancestor class has a virtual destructor.
    880 // Avoid multiple copies by defining this function.
    881 //
    882 CORBA::NS_EPERM::~NS_EPERM()
    883 {
    884 }
    885 
    886 //
    887 // Environment constructor - used for a request on the client node.
    888 //
    889 Environment::Environment() :
    890 	trans_ctxp(NULL),		// No transaction
    891 #ifdef DEBUG
    892 	needs_checking(false),
    893 #endif
    894 	nonblocking(false),		// Blocking allowed
    895 	service_freezing(false),
    896 	freeze_retry(false),
    897 #ifdef _KERNEL_ORB
    898 	source_node(orb_conf::current_id_node()),
    899 #endif
    900 	_ptr(NULL),			// No exception
    901 #if (SOL_VERSION >= __s10) && !defined(UNODE)
    902 	zone_id(GLOBAL_ZONEID),
    903 #ifdef _KERNEL
    904 	zone_uniqid(GLOBAL_ZONEUNIQID),
    905 #else
    906 	zone_uniqid(0),
    907 #endif	// _KERNEL
    908 	cluster_id(PHYSICAL_CLUSTER_ID),
    909 #endif	// (SOL_VERSION >= __s10) && !defined(UNODE)
    910 
    911 	sys_ex(SystemException_major, 0, COMPLETED_MAYBE)
    912 {
    913 }
    914 
    915 #ifdef	_KERNEL_ORB
    916 //
    917 // Environment constructor - used when a request from another node
    918 // arrives on the server node.
    919 //
    920 #if (SOL_VERSION >= __s10) && !defined(UNODE)
    921 Environment::Environment(
    922     ID_node &src_node, zoneid_t zoneid, uint32_t clid,
    923     uint64_t zone_uniq_id) :
    924 #else
    925 Environment::Environment(ID_node &src_node) :
    926 #endif
    927 	trans_ctxp(NULL),		// No transaction
    928 #ifdef DEBUG
    929 	needs_checking(false),
    930 #endif
    931 	nonblocking(false),		// Blocking allowed
    932 	service_freezing(false),
    933 	freeze_retry(false),
    934 	source_node(src_node),
    935 	_ptr(NULL),			// No exception
    936 #if (SOL_VERSION >= __s10) && !defined(UNODE)
    937 	zone_id(zoneid),
    938 	cluster_id(clid),
    939 	zone_uniqid(zone_uniq_id),
    940 #endif
    941 	sys_ex(SystemException_major, 0, COMPLETED_MAYBE)
    942 {
    943 }
    944 #endif	// _KERNEL_ORB
    945 
    946 Environment::~Environment()
    947 {
    948 	check_used("unchecked environment going out of scope");
    949 	ASSERT(trans_ctxp == NULL);	// Cleared by framework
    950 	ASSERT(!service_freezing);	// Cleared by framework
    951 	done();
    952 	ASSERT(_ptr == NULL);
    953 }
    954 
    955 //
    956 // release_exception - disconnect the Environment object from any exception.
    957 // When an exception is connected to an Environment object, the exception is
    958 // destroyed when the Environment destructor executes. This method permits
    959 // the exception to outlive the Environment object.
    960 //
    961 // Returns a pointer to any current exception and guarantees that the
    962 // exception is not stored in the Environment object.
    963 //
    964 CORBA::Exception *
    965 Environment::release_exception()
    966 {
    967 	Exception	*ep = _ptr;
    968 	if (ep == &sys_ex) {
    969 		//
    970 		// System exceptions are stored inside the Environment object.
    971 		// Create a system exception object outside the
    972 		// Environment object.
    973 		//
    974 		ep = new SystemException(sys_ex._major(), sys_ex._minor(),
    975 		    sys_ex.completed());
    976 	}
    977 	_ptr = NULL;
    978 	has_checked();
    979 	return (ep);
    980 }
    981 
    982 #ifdef _KERNEL_ORB
    983 //
    984 // is_orphan - returns true when the current invocation came from a client
    985 // node that is dead. Invocations from dead nodes are called
    986 // orphan requests.
    987 //
    988 // This test does not know anything about nested invocations.
    989 //
    990 // This test is only useful for the server side.
    991 // While this test can be executed on the client side,
    992 // a client side test will never find an orphan.
    993 //
    994 bool
    995 Environment::is_orphan()
    996 {
    997 	return (!(members::the().still_alive(source_node)));
    998 }
    999 
   1000 //
   1001 // is_local_client - returns true when the invocation originated
   1002 // on the same node.
   1003 //
   1004 // The use of this method eliminates "location transparency".
   1005 // Therefore this method should not be used outside the orb
   1006 // without consulting with those responsible for the orb.
   1007 // Justification is required for using this method.
   1008 //
   1009 bool
   1010 Environment::is_local_client()
   1011 {
   1012 	//
   1013 	// It is not necessary to check the node incarnation number,
   1014 	// because a node cannot receive an orphan message from a
   1015 	// prior incarnation of itself.
   1016 	//
   1017 	return (source_node.ndid == orb_conf::node_number());
   1018 }
   1019 #endif	// _KERNEL_ORB
   1020