1 // -*- Mode: C++; -*-
2 // Package : omniORB
3 // callDescriptor.h Created on: 12/1998
4 // Author : David Riddoch (djr)
5 // Author : Duncan Grisby (dgrisby)
6 //
7 // Copyright (C) 2003-2012 Apasphere Ltd
8 // Copyright (C) 1996-1999 AT&T Research Cambridge
9 //
10 // This file is part of the omniORB library.
11 //
12 // The omniORB library is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation; either
15 // version 2.1 of the License, or (at your option) any later version.
16 //
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 // Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library. If not, see http://www.gnu.org/licenses/
24 //
25 //
26 // Object that encapsulates a call to be performed
27 //
28
29 #ifndef __OMNIORB_CALLDESCRIPTOR_H__
30 #define __OMNIORB_CALLDESCRIPTOR_H__
31
32 #ifdef _core_attr
33 # error "A local CPP macro _core_attr has already been defined."
34 #endif
35
36 #if defined(_OMNIORB_LIBRARY)
37 # define _core_attr
38 #else
39 # define _core_attr _OMNIORB_NTDLL_IMPORT
40 #endif
41
42
43 class omniObjRef;
44 class omniServant;
45 class omniCurrent;
46
47 OMNI_NAMESPACE_BEGIN(omni)
48 class omniOrbPOA;
49 class giopAddress;
OMNI_NAMESPACE_END(omni)50 OMNI_NAMESPACE_END(omni)
51
52 //////////////////////////////////////////////////////////////////////
53 ///////////////////////// omniCallDescriptor /////////////////////////
54 //////////////////////////////////////////////////////////////////////
55
56 class omniCallDescriptor {
57 public:
58 typedef void (*LocalCallFn)(omniCallDescriptor*, omniServant*);
59
60 struct InterceptorFn {
61 LocalCallFn fn;
62 InterceptorFn* next;
63 };
64
65 // Call descriptor constructor.
66 //
67 // lcfn -- function used to perform a local call on a servant
68 // op -- operation name. Null represents a LocateRequest
69 // rather than a normal call
70 // op_len -- length of operation name
71 // oneway -- true if a oneway call
72 // user_excns -- set of valid user exceptions or null if not known
73 // n_user_excns -- number of user exceptions
74 // is_upcall -- true if this is an upcall to a servant
75
76 inline omniCallDescriptor(LocalCallFn lcfn,
77 const char* op_,
78 size_t op_len_,
79 _CORBA_Boolean oneway,
80 const char*const* user_excns_,
81 int n_user_excns_,
82 _CORBA_Boolean is_upcall_)
83 : pd_do_call(sd_interceptor_call ? sd_interceptor_call : lcfn),
84 pd_local_call(lcfn),
85 pd_op(op_), pd_oplen(op_len_),
86 pd_user_excns(user_excns_),
87 pd_n_user_excns(n_user_excns_),
88 pd_is_oneway(oneway),
89 pd_is_upcall(is_upcall_),
90 pd_contains_values(0),
91 pd_first_address_used(0),
92 pd_current_address(0),
93 pd_objref(0),
94 pd_poa(0),
95 pd_localId(0)
96 {}
97
98 virtual ~omniCallDescriptor() {}
99
100 //////////////////////////////////////////////////
101 // Methods to implement call on the client side //
102 //////////////////////////////////////////////////
103
104 virtual void initialiseCall(cdrStream&);
105
106 virtual void marshalArguments(cdrStream&);
107 // Defaults to no arguments.
108
109 virtual void unmarshalReturnedValues(cdrStream&);
110 // Defaults to no arguments and returns void.
111
112 virtual void userException(cdrStream& stream, _OMNI_NS(IOP_C)* iop_client,
113 const char*);
114 // Called on the client side to handle a user exception.
115 // Defaults to no user exceptions, and thus throws CORBA::UNKNOWN.
116 // Most versions of this throw either a user exception or
117 // CORBA::UNKNOWN, but it is permitted to return successfully. This
118 // is done by DII, for example.
119 // If iop_client is non-zero, must call iop_client->RequestCompleted().
120
121 void validateUserException(const CORBA::UserException& ex);
122 // Called to validate a user exception in a local call. If the call
123 // descriptor knows the exception is not valid for the call, throws
124 // CORBA::UNKNOWN. If the exception is valid, or the call descriptor
125 // does not know, returns.
126
127 //////////////////////////////////////////////////
128 // Methods to implement call on the server side //
129 //////////////////////////////////////////////////
130
131 virtual void unmarshalArguments(cdrStream&);
132 // Defaults to no arguments.
133
134 virtual void marshalReturnedValues(cdrStream&);
135 // Defaults to no arguments and returns void.
136
137 ////////////////
138 // Invocation //
139 ////////////////
140
141 // Called by stub code to perform a local call.
142 inline void doLocalCall(omniServant* servant) {
143 pd_do_call(this, servant);
144 }
145
146 // Interceptor functions *must* call this to continue the call.
147 inline void interceptedCall(omniServant* servant) {
148 LocalCallFn lcfn;
149 if (pd_interceptor_stack) {
150 lcfn = pd_interceptor_stack->fn;
151 pd_interceptor_stack = pd_interceptor_stack->next;
152 }
153 else
154 lcfn = pd_local_call;
155
156 lcfn(this, servant);
157 }
158
159 ///////////////
160 // Accessors //
161 ///////////////
162
163 inline const char* op() const { return pd_op; }
164 inline size_t op_len() const { return pd_oplen; }
165 inline _CORBA_Boolean is_oneway() const { return pd_is_oneway; }
166 inline void set_oneway(_CORBA_Boolean o) { pd_is_oneway = o; }
167 inline const char* const* user_excns() { return pd_user_excns; }
168 inline int n_user_excns() { return pd_n_user_excns; }
169 inline _CORBA_Boolean is_upcall() const { return pd_is_upcall; }
170
171 inline _CORBA_Boolean haslocalCallFn() const {
172 return (pd_local_call) ? 1 : 0;
173 }
174
175 inline const _OMNI_NS(giopAddress)* firstAddressUsed() {
176 return pd_first_address_used;
177 }
178
179 inline void firstAddressUsed(const _OMNI_NS(giopAddress)* a) {
180 pd_first_address_used = a;
181 }
182
183 inline const _OMNI_NS(giopAddress)* currentAddress() {
184 return pd_current_address;
185 }
186
187 inline void currentAddress(const _OMNI_NS(giopAddress)* a) {
188 pd_current_address = a;
189 }
190
191 inline const omni_time_t& getDeadline() const {
192 return pd_deadline;
193 }
194
195 inline void setDeadline(const omni_time_t& deadline) {
196 pd_deadline = deadline;
197 }
198
199 inline void containsValues(_CORBA_Boolean v) {
200 pd_contains_values = v;
201 }
202 inline _CORBA_Boolean containsValues() {
203 return pd_contains_values;
204 }
205 // If pd_contains_values is true, the arguments / return values
206 // contain valuetypes. The spec requires that values are always
207 // passed by value, so local calls must make copies. Since values
208 // can be shared by separate arguments, the whole argument list must
209 // be copied in a single operation. We do this by marshalling via a
210 // temprary memory buffer. This is slow, so it can be turned off by
211 // setting the copyValuesInLocalCalls parameter to false.
212
213
214 /////////////////////
215 // Current support //
216 /////////////////////
217
218 inline void objref(omniObjRef* o) { pd_objref = o; }
219 inline omniObjRef* objref() { return pd_objref; }
220 inline void poa(_OMNI_NS(omniOrbPOA*) poa_) { pd_poa = poa_; }
221 inline _OMNI_NS(omniOrbPOA*) poa() { return pd_poa; }
222 inline void localId(omniLocalIdentity* lid) { pd_localId = lid; }
223 inline omniLocalIdentity* localId() { return pd_localId; }
224
225
226 //////////////////////////////
227 // Interceptor registration //
228 //////////////////////////////
229
230 static void addInterceptor(LocalCallFn func);
231 static void removeInterceptor(LocalCallFn func);
232
233
234 private:
235 LocalCallFn pd_do_call;
236 LocalCallFn pd_local_call;
237 const char* pd_op;
238 size_t pd_oplen;
239 const char*const* pd_user_excns;
240 int pd_n_user_excns;
241 _CORBA_Boolean pd_is_oneway;
242 _CORBA_Boolean pd_is_upcall;
243 _CORBA_Boolean pd_contains_values;
244
245 const _OMNI_NS(giopAddress)* pd_first_address_used;
246 const _OMNI_NS(giopAddress)* pd_current_address;
247 // state holder for the giop transport in relation to this call. Not
248 // manipulated by this class other than the access functions.
249 // Initialised to 0 in ctor.
250
251 /////////////////////
252 // Current support //
253 /////////////////////
254
255 omniCurrent* pd_current;
256 omniCallDescriptor* pd_current_next;
257 // The omniCurrent object maintains a stack of call descriptors,
258 // representing nested colocated calls. These pointers are
259 // maintained by functions in omniCurrent.
260
261 omniObjRef* pd_objref;
262 // This is set on the client side to indicate the object reference
263 // invoked on. It is used for two things: 1. to check if a servant
264 // found by the in process identity can be used in a direct local
265 // call; 2. as the return value from PortableServer::Current::
266 // get_reference(). In the case of a remote upcall, this is zero,
267 // and an objref is constructed from information in the local id on
268 // request.
269
270 _OMNI_NS(omniOrbPOA*) pd_poa;
271 omniLocalIdentity* pd_localId;
272 // Both always set on the way through the POA during an upcall.
273
274 ////////////////////////////
275 // Deadline for this call //
276 ////////////////////////////
277
278 // This is a state holder for the call. Not manipulated by this class
279 // other than the access functions. Initialised to 0 in ctor.
280 omni_time_t pd_deadline;
281
282
283 ///////////////////////
284 // Call interceptors //
285 ///////////////////////
286
287 static _core_attr LocalCallFn sd_interceptor_call;
288 // Function used in place of the normal local call function if
289 // interceptors are registered. Initialises the interceptor stack
290 // and calls the first interceptor in the stack.
291
292 static void setupInterception(omniCallDescriptor* cd, omniServant* servant);
293 // Function assigned to sd_interceptor_call when interceptors are registered.
294
295 static _core_attr InterceptorFn* sd_interceptor_stack;
296 InterceptorFn* pd_interceptor_stack;
297 // Global interceptor stack and this call descriptor's pointer into it.
298
299
300 /////////////////////
301 // Not implemented //
302 /////////////////////
303
304 omniCallDescriptor(const omniCallDescriptor&);
305 omniCallDescriptor& operator = (const omniCallDescriptor&);
306 // Not implemented.
307 };
308
309
310 //////////////////////////////////////////////////////////////////////
311 ///////////////////////// omniAsyncCallDescriptor ////////////////////
312 //////////////////////////////////////////////////////////////////////
313
314 class omniAsyncCallDescriptor : public omniCallDescriptor
315 {
316 public:
317 // Constructor for normal synchronous calls. Created on the stack.
omniAsyncCallDescriptor(LocalCallFn lcfn,const char * op_,size_t op_len_,_CORBA_Boolean oneway,const char * const * user_excns_,int n_user_excns_,_CORBA_Boolean is_upcall_)318 inline omniAsyncCallDescriptor(LocalCallFn lcfn,
319 const char* op_,
320 size_t op_len_,
321 _CORBA_Boolean oneway,
322 const char*const* user_excns_,
323 int n_user_excns_,
324 _CORBA_Boolean is_upcall_)
325 : omniCallDescriptor(lcfn, op_, op_len_, oneway,
326 user_excns_, n_user_excns_,
327 is_upcall_),
328 pd_exception(0),
329 pd_cond(0),
330 pd_set_cond(0)
331 {}
332
333 // Constructor for asynchronous calls. Created on the heap.
334 //
335 // In callback AMI, completeCallback() makes the callback to the
336 // ReplyHandler, then deletes this; in polling AMI, the poller
337 // valuetype owns the call descriptor and deletes it when the poller
338 // is deleted.
omniAsyncCallDescriptor(LocalCallFn lcfn,const char * op_,size_t op_len_,_CORBA_Boolean oneway,const char * const * user_excns_,int n_user_excns_)339 inline omniAsyncCallDescriptor(LocalCallFn lcfn,
340 const char* op_,
341 size_t op_len_,
342 _CORBA_Boolean oneway,
343 const char*const* user_excns_,
344 int n_user_excns_)
345 : omniCallDescriptor(lcfn, op_, op_len_, oneway,
346 user_excns_, n_user_excns_, 0),
347 pd_exception(0),
348 pd_cond(0),
349 pd_set_cond(0),
350 pd_complete(0),
351 pd_do_callback(1)
352 {}
353
354 virtual ~omniAsyncCallDescriptor();
355
356 virtual void completeCallback();
357
358 // Handler set / get. Object reference is a Messaging::ReplyHandler
359 // subclass.
360 virtual void setHandler(omniObjRef* objref);
361 virtual omniObjRef* getHandler();
362
363
setComplete()364 inline void setComplete()
365 {
366 _CORBA_Boolean do_callback;
367 {
368 omni_tracedmutex_lock l(sd_lock);
369 do_callback = pd_do_callback;
370 pd_complete = 1;
371
372 if (pd_cond)
373 pd_cond->broadcast();
374
375 if (pd_set_cond)
376 pd_set_cond->signal();
377 }
378 if (do_callback)
379 completeCallback();
380 }
381
isComplete()382 inline _CORBA_Boolean isComplete()
383 {
384 omni_tracedmutex_lock l(sd_lock);
385 return pd_complete;
386 }
387
lockedIsComplete()388 inline _CORBA_Boolean lockedIsComplete()
389 {
390 ASSERT_OMNI_TRACEDMUTEX_HELD(sd_lock, 1);
391 return pd_complete;
392 }
393
wait()394 inline void wait()
395 {
396 omni_tracedmutex_lock l(sd_lock);
397
398 if (pd_complete)
399 return;
400
401 if (!pd_cond)
402 pd_cond = new omni_tracedcondition(&sd_lock,
403 "omniAsyncCallDescriptor::pd_cond");
404
405 while (!pd_complete)
406 pd_cond->wait();
407 }
408
wait(const omni_time_t & t)409 inline _CORBA_Boolean wait(const omni_time_t& t)
410 {
411 omni_tracedmutex_lock l(sd_lock);
412
413 if (pd_complete)
414 return 1;
415
416 if (!pd_cond)
417 pd_cond = new omni_tracedcondition(&sd_lock,
418 "omniAsyncCallDescriptor::pd_cond");
419
420 pd_cond->timedwait(t);
421 return pd_complete;
422 }
423
isReady(CORBA::ULong timeout)424 inline _CORBA_Boolean isReady(CORBA::ULong timeout)
425 {
426 if (timeout == 0)
427 return isComplete();
428
429 if (timeout == 0xffffffff) {
430 wait();
431 return 1;
432 }
433
434 omni_time_t timeout_tt(timeout / 1000, (timeout % 1000) * 1000000);
435 omni_time_t deadline;
436 omni_thread::get_time(deadline, timeout_tt);
437
438 return wait(deadline);
439 }
440
441
storeException(const CORBA::Exception & ex)442 inline void storeException(const CORBA::Exception& ex)
443 {
444 pd_exception = CORBA::Exception::_duplicate(&ex);
445 }
446
exceptionOccurred()447 inline _CORBA_Boolean exceptionOccurred()
448 {
449 return pd_exception ? 1 : 0;
450 }
451
raiseException()452 inline void raiseException()
453 {
454 if (pd_exception)
455 pd_exception->_raise();
456 }
457
getException()458 inline CORBA::Exception* getException()
459 {
460 CORBA::Exception* ex = pd_exception;
461 pd_exception = 0;
462 return ex;
463 }
464
addToSet(omni_tracedcondition * set_cond)465 inline _CORBA_Boolean addToSet(omni_tracedcondition* set_cond)
466 {
467 ASSERT_OMNI_TRACEDMUTEX_HELD(sd_lock, 1);
468
469 if (pd_set_cond)
470 return 0;
471
472 pd_set_cond = set_cond;
473 return 1;
474 }
475
remFromSet(omni_tracedcondition * set_cond)476 inline void remFromSet(omni_tracedcondition* set_cond)
477 {
478 ASSERT_OMNI_TRACEDMUTEX_HELD(sd_lock, 1);
479 OMNIORB_ASSERT(pd_set_cond == set_cond);
480
481 pd_set_cond = 0;
482 }
483
484 static _core_attr omni_tracedmutex sd_lock;
485
486 protected:
487 CORBA::Exception* pd_exception;
488 omni_tracedcondition* pd_cond;
489 omni_tracedcondition* pd_set_cond;
490 _CORBA_Boolean pd_complete;
491 _CORBA_Boolean pd_do_callback;
492
493 // Not implemented
494 omniAsyncCallDescriptor(const omniAsyncCallDescriptor&);
495 omniAsyncCallDescriptor& operator=(const omniAsyncCallDescriptor&);
496 };
497
498
499 //////////////////////////////////////////////////////////////////////
500 /////////////////////////// omniStdCallDesc //////////////////////////
501 //////////////////////////////////////////////////////////////////////
502
503 // This just provides a namespace for pre-defined call descriptors.
504
505 class omniStdCallDesc {
506 public:
507
508 // Mangled signature: void
509 typedef omniCallDescriptor void_call;
510
511 // Mangled signature: _cCORBA_mObject_i_cstring
512 class _cCORBA_mObject_i_cstring : public omniCallDescriptor {
513 public:
514 inline _cCORBA_mObject_i_cstring(LocalCallFn lcfn, const char* op_,
515 size_t oplen, const char* a_0,
516 _CORBA_Boolean upcall=0) :
517 omniCallDescriptor(lcfn, op_, oplen, 0, 0, 0, upcall),
518 arg_0( OMNI_CONST_CAST(char*, a_0) ) {}
519
~_cCORBA_mObject_i_cstring()520 inline ~_cCORBA_mObject_i_cstring() {
521 if (is_upcall()) {
522 _CORBA_String_helper::dealloc(arg_0);
523 }
524 }
525
526 void marshalArguments(cdrStream&);
527 void unmarshalReturnedValues(cdrStream&);
528 void unmarshalArguments(cdrStream&);
529 void marshalReturnedValues(cdrStream&);
530
result()531 inline CORBA::Object_ptr result() { return pd_result._retn(); }
532
533 char* arg_0;
534 CORBA::Object_var pd_result;
535 };
536
537 };
538
539
540 //////////////////////////////////////////////////////////////////////
541 ///////////////////// omniLocalOnlyCallDescriptor ////////////////////
542 //////////////////////////////////////////////////////////////////////
543
544 // This class is needed to support calls to objects which may only
545 // reside in the local address space. eg. ServantLocator,
546 // ServantActivator, AdapterActivator.
547
548 class omniLocalOnlyCallDescriptor : public omniCallDescriptor {
549 public:
550 omniLocalOnlyCallDescriptor(LocalCallFn lcfn, const char* op_,
551 size_t op_len_, _CORBA_Boolean is_oneway_ = 0)
552 : omniCallDescriptor(lcfn, op_, op_len_, is_oneway_, 0, 0, 0) {}
553
554 // Only useful as client side descriptor. No set up for server side upcall.
555
556 // We only need to override this one -- as it will throw an
557 // exception, so the other members won't get called.
558 void marshalArguments(cdrStream&);
559 };
560
561 #undef _core_attr
562
563 #endif // __OMNIORB_CALLDESCRIPTOR_H__
564