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