#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 } |