#include <Synch_Invocation.h>
Inheritance diagram for TAO::Synch_Twoway_Invocation:


Public Member Functions | |
| Synch_Twoway_Invocation (CORBA::Object_ptr otarget, Profile_Transport_Resolver &resolver, TAO_Operation_Details &detail, bool response_expected=true) | |
| Constructor used by TAO::Invocation_Adapter. | |
| Invocation_Status | remote_twoway (ACE_Time_Value *max_wait_time) |
Protected Member Functions | |
| virtual Invocation_Status | handle_user_exception (TAO_InputCDR &cdr) |
| Invocation_Status | location_forward (TAO_InputCDR &cdr) |
| Helper method used to handle location forwarded replies. | |
| Invocation_Status | handle_system_exception (TAO_InputCDR &cdr) |
| Invocation_Status | wait_for_reply (ACE_Time_Value *max_wait_time, TAO_Synch_Reply_Dispatcher &rd, TAO_Bind_Dispatcher_Guard &bd) |
| As the name suggests waits for a reply from the remote ORB. | |
Private Member Functions | |
| Invocation_Status | check_reply_status (TAO_Synch_Reply_Dispatcher &rd) |
An object of this type is created by TAO::Invocation_Adapter and invokes a method on this class. The method takes care of creating and sending a request, waiting for a reply and demarshalling the reply for the client.
Definition at line 52 of file Synch_Invocation.h.
|
||||||||||||||||||||
|
Constructor used by TAO::Invocation_Adapter.
Definition at line 41 of file Synch_Invocation.cpp. References CORBA::Object_ptr.
00046 : Remote_Invocation (otarget, 00047 resolver, 00048 detail, 00049 response_expected) 00050 { 00051 } |
|
|
This method returns an exception when there is an error. Definition at line 319 of file Synch_Invocation.cpp. References ACE_DEBUG, TAO_Transport::assign_translators(), TAO_Operation_Details::demarshal_args(), handle_system_exception(), handle_user_exception(), TAO_Pseudo_Var_T< T >::in(), TAO::Invocation_Status, TAO_ORB_Core::is_permanent_forward_condition(), LM_DEBUG, location_forward(), TAO::Invocation_Base::orb_core(), TAO::Profile_Transport_Resolver::profile(), ACE_InputCDR::read_short(), TAO_Synch_Reply_Dispatcher::reply_cdr(), TAO_Reply_Dispatcher::reply_status(), TAO::Invocation_Base::request_service_context(), TAO::Reply_Guard::set_status(), TAO_debug_level, TAO::TAO_INVOKE_FAILURE, TAO::TAO_INVOKE_RESTART, TAO::TAO_INVOKE_SUCCESS, TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD, TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD_PERM, TAO_PLUGGABLE_MESSAGE_NEEDS_ADDRESSING_MODE, TAO_PLUGGABLE_MESSAGE_NO_EXCEPTION, TAO_PLUGGABLE_MESSAGE_SYSTEM_EXCEPTION, TAO_PLUGGABLE_MESSAGE_USER_EXCEPTION, and TAO::Profile_Transport_Resolver::transport(). Referenced by remote_twoway().
00320 {
00321 /*
00322 * Precondition: We probably got a reply. <ACE_Thread::self> is
00323 * checking the status of the reply
00324 *
00325 * Postcondition: Any error while reading the reply is marked by
00326 * raising an exception. LOCATION_FORWARDED replies are marked by
00327 * returning a restart since that is what needed to be done by the
00328 * callee.
00329 */
00330 TAO_InputCDR &cdr = rd.reply_cdr ();
00331
00332 // Set the translators
00333 this->resolver_.transport ()->assign_translators (&cdr, 0);
00334
00335 // At this point it can be assumed that the GIOP/whatever protocol
00336 // header and the reply header are already handled. Further it
00337 // can be assumed that the reply body contains the details
00338 // required for further processing. All the other details should
00339 // have been handled in the reply dispatcher/protocol framework.
00340 switch (rd.reply_status ())
00341 {
00342 case TAO_PLUGGABLE_MESSAGE_NO_EXCEPTION:
00343 {
00344 Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00345 if (this->details_.demarshal_args (cdr) == false)
00346 {
00347 throw ::CORBA::MARSHAL ();
00348 }
00349
00350 mon.set_status (TAO_INVOKE_SUCCESS);
00351 }
00352 break;
00353 case TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD:
00354 return this->location_forward (cdr);
00355 case TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD_PERM:
00356 {
00357 // Unmarshal the location forward object and set the
00358 // variable this->forward_to_.
00359 Invocation_Status const s = this->location_forward (cdr);
00360 if (s != TAO_INVOKE_FAILURE)
00361 {
00362 // de-marshalling of permanent object reference was successfull
00363 CORBA::Boolean const permanent_forward_condition =
00364 this->orb_core ()->is_permanent_forward_condition
00365 (this->forwarded_to_.in (),
00366 this->request_service_context ());
00367
00368 if (!permanent_forward_condition)
00369 {
00370 // permanent condition not given
00371 if (TAO_debug_level > 3)
00372 ACE_DEBUG ((LM_DEBUG,
00373 "TAO (%P|%t) - Synch_Twoway_Invocation::"
00374 "check_reply_status: unexpected LOCATION_FORWARD_PERM reply\n"));
00375
00376 throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO);
00377 }
00378 }
00379
00380 return s;
00381 }
00382 case TAO_PLUGGABLE_MESSAGE_USER_EXCEPTION:
00383 return this->handle_user_exception (cdr);
00384 case TAO_PLUGGABLE_MESSAGE_SYSTEM_EXCEPTION:
00385 return this->handle_system_exception (cdr);
00386
00387 case TAO_PLUGGABLE_MESSAGE_NEEDS_ADDRESSING_MODE:
00388 {
00389 Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00390 // We have received a message with a request to change the
00391 // addressing mode. First let us read the mode that the
00392 // server/agent asks for.
00393 CORBA::Short addr_mode = 0;
00394
00395 if (cdr.read_short (addr_mode) == 0)
00396 {
00397 // Could not demarshal the addressing disposition, raise an local
00398 // CORBA::MARSHAL
00399 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE);
00400 }
00401
00402 // Now set this addressing mode in the profile, so that
00403 // the next invocation need not go through this.
00404 this->resolver_.profile ()->addressing_mode (addr_mode);
00405
00406 mon.set_status (TAO_INVOKE_RESTART);
00407
00408 // Now restart the invocation
00409 return TAO_INVOKE_RESTART;
00410 }
00411 }
00412 return TAO_INVOKE_SUCCESS;
00413 }
|
|
|
Helper method used to handle system exceptions from the remote objects. There has been a unanimous view that this is not the right way to do things. But a need to be compliant is forcing us into this.
Definition at line 493 of file Synch_Invocation.cpp. References CORBA::SystemException::_raise(), ACE_DEBUG, ACE_NEW_RETURN, CORBA::SystemException::completed(), TAO::create_system_exception(), TAO::String_var< charT >::in(), TAO::String_var< charT >::inout(), TAO::Invocation_Status, LM_DEBUG, CORBA::SystemException::minor(), TAO_Stub::next_profile_retry(), TAO::Invocation_Base::orb_core(), TAO::Profile_Transport_Resolver::profile(), TAO_ORB_Core::service_raise_transient_failure(), TAO::Reply_Guard::set_status(), CORBA::String_var, TAO::Profile_Transport_Resolver::stub(), TAO_debug_level, TAO::TAO_INVOKE_FAILURE, TAO::TAO_INVOKE_RESTART, and TAO::TAO_INVOKE_SYSTEM_EXCEPTION. Referenced by check_reply_status().
00494 {
00495 Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00496
00497 if (TAO_debug_level > 3)
00498 ACE_DEBUG ((LM_DEBUG,
00499 "TAO (%P|%t) - Synch_Twoway_Invocation::"
00500 "handle_system_exception \n"));
00501
00502 CORBA::String_var type_id;
00503
00504 if ((cdr >> type_id.inout ()) == 0)
00505 {
00506 // Could not demarshal the exception id, raise an local
00507 // CORBA::MARSHAL
00508 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE);
00509 }
00510
00511 CORBA::ULong minor = 0;
00512 CORBA::ULong completion = 0;
00513
00514 if ((cdr >> minor) == 0 || (cdr >> completion) == 0)
00515 {
00516 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE);
00517 }
00518
00519 // Special handling for non-fatal system exceptions.
00520 //
00521 // Note that we are careful to retain "at most once" semantics.
00522 if ((ACE_OS_String::strcmp (type_id.in (),
00523 "IDL:omg.org/CORBA/TRANSIENT:1.0") == 0 ||
00524 ACE_OS_String::strcmp (type_id.in (),
00525 "IDL:omg.org/CORBA/OBJ_ADAPTER:1.0") == 0 ||
00526 ACE_OS_String::strcmp (type_id.in (),
00527 "IDL:omg.org/CORBA/NO_RESPONSE:1.0") == 0 ||
00528 ACE_OS_String::strcmp (type_id.in (),
00529 "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0) &&
00530 (CORBA::CompletionStatus) completion != CORBA::COMPLETED_YES)
00531 {
00532 {
00533 // Start the special case for FTCORBA.
00534 /**
00535 * There has been a unanimous view that this is not the
00536 * right way to do things. But a need to be compliant is
00537 * forcing us into this.
00538 */
00539 Invocation_Status const s =
00540 this->orb_core ()->service_raise_transient_failure (
00541 this->details_.request_service_context ().service_info (),
00542 this->resolver_.profile ());
00543
00544 if (s == TAO_INVOKE_RESTART)
00545 return s;
00546 }
00547
00548 // Attempt profile retry.
00549 /**
00550 * @note A location forwarding loop may occur where a client
00551 * is bounced from the original target to the forwarded
00552 * target and back if the application is not equipped to
00553 * handle retries of previously called targets. TAO may
00554 * be able to help in this case but it ultimately ends
00555 * up being an application issue.
00556 */
00557 if (this->resolver_.stub ()->next_profile_retry ())
00558 {
00559 return TAO_INVOKE_RESTART;
00560 }
00561
00562 // Fall through and raise an exception.
00563 }
00564
00565 CORBA::SystemException *ex = TAO::create_system_exception (type_id.in ());
00566
00567 if (ex == 0)
00568 {
00569 // @@ We should raise a CORBA::NO_MEMORY, but we ran out
00570 // of memory already. We need a pre-allocated, TSS,
00571 // CORBA::NO_MEMORY instance
00572 ACE_NEW_RETURN (ex,
00573 CORBA::UNKNOWN,
00574 TAO_INVOKE_FAILURE);
00575 }
00576
00577 // Without this, the call to create_system_exception() above
00578 // causes a memory leak. On platforms without native exceptions,
00579 // the CORBA::Environment class manages the memory.
00580 auto_ptr<CORBA::SystemException> safety (ex);
00581
00582 ex->minor (minor);
00583 ex->completed (CORBA::CompletionStatus (completion));
00584
00585 if (TAO_debug_level > 4)
00586 ACE_DEBUG ((LM_DEBUG,
00587 "TAO (%P|%t) - Synch_Twoway_Invocation::"
00588 "handle_system_exception, about to raise\n"));
00589
00590 mon.set_status (TAO_INVOKE_SYSTEM_EXCEPTION);
00591
00592 // Raise the exception.
00593 ex->_raise ();
00594
00595 return TAO_INVOKE_SYSTEM_EXCEPTION;
00596 }
|
|
|
This method is selectively made virtual, so that inherited classes can overload the user exception handling type. For example the DII needs a totally different method of user exception exception handling Definition at line 446 of file Synch_Invocation.cpp. References CORBA::Exception::_raise(), CORBA::Exception::_tao_decode(), ACE_DEBUG, ACE_TEXT, ACE_TEXT_CHAR_TO_TCHAR, TAO_Operation_Details::corba_exception(), TAO::String_var< charT >::in(), TAO::String_var< charT >::inout(), LM_DEBUG, TAO::Reply_Guard::set_status(), CORBA::String_var, TAO_debug_level, TAO::TAO_INVOKE_FAILURE, and TAO::TAO_INVOKE_USER_EXCEPTION. Referenced by check_reply_status().
00447 {
00448 Reply_Guard mon (this,
00449 TAO_INVOKE_FAILURE);
00450
00451 if (TAO_debug_level > 3)
00452 ACE_DEBUG ((LM_DEBUG,
00453 "TAO (%P|%t) - Synch_Twoway_Invocation::"
00454 "handle_user_exception \n"));
00455
00456 // Pull the exception from the stream.
00457 CORBA::String_var buf;
00458
00459 if ((cdr >> buf.inout ()) == 0)
00460 {
00461 // Could not demarshal the exception id, raise an local
00462 // CORBA::MARSHAL
00463 throw ::CORBA::MARSHAL (0, CORBA::COMPLETED_MAYBE);
00464 }
00465
00466 CORBA::Exception *exception = this->details_.corba_exception (buf.in ());
00467
00468 exception->_tao_decode (cdr);
00469
00470 if (TAO_debug_level > 5)
00471 {
00472 ACE_DEBUG ((LM_DEBUG,
00473 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
00474 ACE_TEXT ("handle_user_exception - ")
00475 ACE_TEXT ("raising exception %s\n"),
00476 ACE_TEXT_CHAR_TO_TCHAR (buf.in ())));
00477 }
00478
00479 mon.set_status (TAO_INVOKE_USER_EXCEPTION);
00480
00481 // If we have native exceptions, we must manage the memory allocated
00482 // by the call above to alloc(). Otherwise the Environment class
00483 // manages the memory.
00484 auto_ptr<CORBA::Exception> safety (exception);
00485
00486 // Direct throw because we don't have the try_ENV.
00487 exception->_raise ();
00488
00489 return TAO_INVOKE_USER_EXCEPTION;
00490 }
|
|
|
Helper method used to handle location forwarded replies.
Definition at line 416 of file Synch_Invocation.cpp. References ACE_DEBUG, ACE_TEXT, TAO::Invocation_Base::forwarded_reference(), TAO_Pseudo_Var_T< T >::in(), LM_DEBUG, CORBA::Object_var, TAO::Reply_Guard::set_status(), TAO_debug_level, TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE, TAO::TAO_INVOKE_FAILURE, and TAO::TAO_INVOKE_RESTART. Referenced by TAO::LocateRequest_Invocation::check_reply(), and check_reply_status().
00417 {
00418 Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00419
00420 if (TAO_debug_level > 3)
00421 {
00422 ACE_DEBUG ((LM_DEBUG,
00423 ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::location_forward ")
00424 ACE_TEXT ("being handled \n")));
00425 }
00426
00427 CORBA::Object_var fwd;
00428
00429 if ((inp_stream >> fwd) == 0)
00430 {
00431 throw ::CORBA::MARSHAL (
00432 CORBA::SystemException::_tao_minor_code (
00433 TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00434 errno),
00435 CORBA::COMPLETED_NO);
00436 }
00437
00438 this->forwarded_reference (fwd.in ());
00439
00440 mon.set_status (TAO_INVOKE_RESTART);
00441
00442 return TAO_INVOKE_RESTART;
00443 }
|
|
|
There is a exception declaration in this method which ensures that the exceptions propogated by the remote objects are converted a CORBA exceptions for the clients. This method does a bunch of things necessary to create and send the invocation. This method is also nerve centre for the interceptor invocation points. Definition at line 54 of file Synch_Invocation.cpp. References check_reply_status(), TAO_Transport::close_connection(), TAO::Invocation_Base::handle_all_exception(), TAO::Invocation_Base::handle_any_exception(), TAO_Transport::idle_after_reply(), TAO_Transport::idle_after_send(), TAO::Remote_Invocation::init_target_spec(), TAO::Invocation_Status, TAO::Remote_Invocation::marshal_data(), TAO_OutputCDR::message_attributes(), TAO_Transport::out_stream(), TAO::Invocation_Base::receive_other_interception(), TAO::Invocation_Base::receive_reply_interception(), TAO_Operation_Details::reply_service_info(), PortableInterceptor::ReplyStatus, TAO::Remote_Invocation::send_message(), TAO::Invocation_Base::send_request_interception(), TAO_Bind_Dispatcher_Guard::status(), TAO::Profile_Transport_Resolver::stub(), TAO::TAO_INVOKE_FAILURE, TAO::TAO_INVOKE_RESTART, TAO::TAO_INVOKE_SUCCESS, TAO_Transport::tms(), TAO::Profile_Transport_Resolver::transport(), TAO::Profile_Transport_Resolver::transport_released(), ACE_Countdown_Time::update(), wait_for_reply(), and TAO::Remote_Invocation::write_header(). Referenced by TAO::Invocation_Adapter::invoke_twoway().
00055 {
00056 ACE_Countdown_Time countdown (max_wait_time);
00057
00058 TAO_Synch_Reply_Dispatcher rd (this->resolver_.stub ()->orb_core (),
00059 this->details_.reply_service_info ());
00060
00061 TAO_Target_Specification tspec;
00062 this->init_target_spec (tspec);
00063
00064 Invocation_Status s = TAO_INVOKE_FAILURE;
00065
00066 #if TAO_HAS_INTERCEPTORS == 1
00067 // Start the interception point here..
00068 s = this->send_request_interception ();
00069
00070 if (s != TAO_INVOKE_SUCCESS)
00071 return s;
00072
00073 // We have started the interception flow. We need to call the
00074 // ending interception flow if things go wrong. The purpose of the
00075 // try block is to do just this.
00076 try
00077 {
00078 #endif /*TAO_HAS_INTERCEPTORS */
00079
00080 TAO_OutputCDR &cdr = this->resolver_.transport ()->out_stream ();
00081
00082 cdr.message_attributes (this->details_.request_id (),
00083 this->resolver_.stub (),
00084 TAO_Transport::TAO_TWOWAY_REQUEST,
00085 max_wait_time);
00086
00087 this->write_header (tspec, cdr);
00088
00089 this->marshal_data (cdr);
00090
00091 // Register a reply dispatcher for this invocation. Use the
00092 // preallocated reply dispatcher.
00093 TAO_Bind_Dispatcher_Guard dispatch_guard (
00094 this->details_.request_id (),
00095 &rd,
00096 this->resolver_.transport ()->tms ());
00097
00098 if (dispatch_guard.status () != 0)
00099 {
00100 // @@ What is the right way to handle this error? Why should
00101 // we close the connection?
00102 this->resolver_.transport ()->close_connection ();
00103
00104 throw ::CORBA::INTERNAL (0, CORBA::COMPLETED_NO);
00105 }
00106
00107 countdown.update ();
00108
00109 s = this->send_message (cdr,
00110 TAO_Transport::TAO_TWOWAY_REQUEST,
00111 max_wait_time);
00112
00113 #if TAO_HAS_INTERCEPTORS == 1
00114 // @@NOTE: Too much code repetition.
00115 // If the above call returns a restart due to connection
00116 // failure then call the receive_other interception point
00117 // before we leave.
00118 if (s == TAO_INVOKE_RESTART)
00119 {
00120 Invocation_Status const tmp = this->receive_other_interception ();
00121
00122 if (tmp != TAO_INVOKE_SUCCESS)
00123 s = tmp;
00124 }
00125 #endif /* TAO_HAS_INTERCEPTORS */
00126
00127 if (s != TAO_INVOKE_SUCCESS)
00128 return s;
00129
00130 countdown.update ();
00131
00132 // For some strategies one may want to release the transport
00133 // back to cache. If the idling is successfull let the
00134 // resolver about that.
00135 if (this->resolver_.transport ()->idle_after_send ())
00136 this->resolver_.transport_released ();
00137
00138 // @@ In all MT environments, there's a cancellation point lurking
00139 // here; need to investigate. Client threads would frequently be
00140 // canceled sometime during recv_request ... the correct action to
00141 // take on being canceled is to issue a CancelRequest message to the
00142 // server and then imediately let other client-side cancellation
00143 // handlers do their jobs.
00144 //
00145 // In C++, that basically means to unwind the stack using almost
00146 // normal procedures: all destructors should fire, and some "catch"
00147 // blocks should probably be able to handle things like releasing
00148 // pointers. (Without unwinding the C++ stack, resources that must
00149 // be freed by thread cancellation won't be freed, and the process
00150 // won't continue to function correctly.) The tricky part is that
00151 // according to POSIX, all C stack frames must also have their
00152 // (explicitly coded) handlers called. We assume a POSIX.1c/C/C++
00153 // environment.
00154
00155 s = this->wait_for_reply (max_wait_time, rd, dispatch_guard);
00156
00157 #if TAO_HAS_INTERCEPTORS == 1
00158 if (s == TAO_INVOKE_RESTART)
00159 {
00160 Invocation_Status const tmp = this->receive_other_interception ();
00161
00162 // Push the latest values for the return..
00163 if (tmp != TAO_INVOKE_SUCCESS)
00164 s = tmp;
00165 }
00166 #endif /* TAO_HAS_INTERCEPTORS */
00167
00168 if (s != TAO_INVOKE_SUCCESS)
00169 return s;
00170
00171 // What happens when the above call returns an error through
00172 // the return value? That would be bogus as per the contract
00173 // in the interface. The call violated the contract
00174 s = this->check_reply_status (rd);
00175
00176 // For some strategies one may want to release the transport
00177 // back to cache after receiving the reply.
00178 if (this->resolver_.transport ()->idle_after_reply ())
00179 this->resolver_.transport_released ();
00180
00181 #if TAO_HAS_INTERCEPTORS == 1
00182 Invocation_Status tmp = TAO_INVOKE_FAILURE;
00183 if (s == TAO_INVOKE_RESTART)
00184 {
00185 tmp = this->receive_other_interception ();
00186 }
00187 else if (s == TAO_INVOKE_SUCCESS)
00188 {
00189 tmp = this->receive_reply_interception ();
00190 }
00191 if (tmp != TAO_INVOKE_SUCCESS)
00192 s = tmp;
00193 }
00194 catch ( ::CORBA::Exception& ex)
00195 {
00196 PortableInterceptor::ReplyStatus const status =
00197 this->handle_any_exception (&ex);
00198
00199 if (status == PortableInterceptor::LOCATION_FORWARD ||
00200 status == PortableInterceptor::TRANSPORT_RETRY)
00201 s = TAO_INVOKE_RESTART;
00202 else if (status == PortableInterceptor::SYSTEM_EXCEPTION
00203 || status == PortableInterceptor::USER_EXCEPTION)
00204 throw;
00205 }
00206 catch (...)
00207 {
00208 // Notify interceptors of non-CORBA exception, and propagate
00209 // that exception to the caller.
00210
00211 PortableInterceptor::ReplyStatus const st =
00212 this->handle_all_exception ();
00213
00214 if (st == PortableInterceptor::LOCATION_FORWARD ||
00215 st == PortableInterceptor::TRANSPORT_RETRY)
00216 s = TAO_INVOKE_RESTART;
00217 else
00218 throw;
00219 }
00220 #endif /* TAO_HAS_INTERCEPTORS */
00221
00222 return s;
00223 }
|
|
||||||||||||||||
|
As the name suggests waits for a reply from the remote ORB. This method returns an exception when there is an error. Definition at line 226 of file Synch_Invocation.cpp. References ACE_DEBUG, TAO_Transport::close_connection(), ETIME, LM_DEBUG, ACE_Time_Value::msec(), TAO::Invocation_Base::orb_core(), TAO::Profile_Transport_Resolver::profile(), TAO_Stub::reset_profiles(), TAO_ORB_Core::service_raise_comm_failure(), TAO::Profile_Transport_Resolver::stub(), TAO_debug_level, TAO::TAO_INVOKE_SUCCESS, TAO_TIMEOUT_RECV_MINOR_CODE, TAO::Profile_Transport_Resolver::transport(), TAO_Bind_Dispatcher_Guard::unbind_dispatcher(), TAO_Wait_Strategy::wait(), and TAO_Transport::wait_strategy(). Referenced by TAO::LocateRequest_Invocation::invoke(), and remote_twoway().
00229 {
00230 /*
00231 * Precondition: The call went to the remote
00232 * peer. <ACE_Thread::self> is waiting for the reply.
00233 *
00234 * Postcondition: Any error during a wait is marked by raising an
00235 * exception. Success alone is returned through the return value.
00236 */
00237
00238 int const reply_error =
00239 this->resolver_.transport ()->wait_strategy ()->wait (max_wait_time, rd);
00240
00241 if (TAO_debug_level > 0 && max_wait_time != 0)
00242 {
00243 CORBA::ULong const msecs = max_wait_time->msec ();
00244
00245 ACE_DEBUG ((LM_DEBUG,
00246 "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, "
00247 "timeout after recv is <%u> status <%d>\n",
00248 msecs,
00249 reply_error));
00250 }
00251
00252 // Check the reply error.
00253 if (reply_error == -1)
00254 {
00255 // Unbind the dispatcher, since its of no use at this point of
00256 // time
00257 if (TAO_debug_level > 3)
00258 {
00259 ACE_DEBUG ((LM_DEBUG,
00260 "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, "
00261 "recovering after an error \n"));
00262 }
00263
00264 // You the smarty, don't try to moving the unbind_dispatcher
00265 // () call since it looks like it is repeated twice. That
00266 // could land you in trouble. If you don't believe this
00267 // warning go ahead and try. Try running tests to see what is
00268 // going on ;)
00269 if (errno == ETIME)
00270 {
00271 // If the unbind succeeds then thrown an exception to the
00272 // application, else just collect the reply and dispatch
00273 // that to the application.
00274 //
00275 // NOTE: A fragile synchronization is provided when using
00276 // the Muxed Transport strategy. We could infact be a
00277 // follower thread getting timedout in the LF whereas the
00278 // dispatching thread could be on the reply_dispatcher
00279 // that we created. This would lead bad crashes. To get
00280 // around that, the call to unbind_dispatcher () will wait
00281 // on the lock on the Muxed_Transport_Strategy if
00282 // dispatching has started. This is fragile.
00283 if (bd.unbind_dispatcher () == 0)
00284 {
00285 // Just a timeout with completed_maybe, don't close
00286 // the connection or anything
00287 throw ::CORBA::TIMEOUT (
00288 CORBA::SystemException::_tao_minor_code (
00289 TAO_TIMEOUT_RECV_MINOR_CODE,
00290 errno),
00291 CORBA::COMPLETED_MAYBE);
00292 }
00293 }
00294 else
00295 {
00296 (void) bd.unbind_dispatcher ();
00297 this->resolver_.transport ()->close_connection ();
00298
00299 try
00300 {
00301 return
00302 this->orb_core ()->service_raise_comm_failure (
00303 this->details_.request_service_context ().service_info (),
00304 this->resolver_.profile ());
00305
00306 }
00307 catch (const ::CORBA::Exception&)
00308 {
00309 this->resolver_.stub ()->reset_profiles ();
00310 throw;
00311 }
00312 }
00313 }
00314
00315 return TAO_INVOKE_SUCCESS;
00316 }
|
1.3.6