TAO::Synch_Twoway_Invocation Class Reference

All the action for a synchronous twoway invocation happen here. More...

#include <Synch_Invocation.h>

Inheritance diagram for TAO::Synch_Twoway_Invocation:

Inheritance graph
[legend]
Collaboration diagram for TAO::Synch_Twoway_Invocation:

Collaboration graph
[legend]
List of all members.

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)

Detailed Description

All the action for a synchronous twoway invocation happen here.

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 & Destructor Documentation

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.

Parameters:
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.

References CORBA::Object_ptr.

00046     : Remote_Invocation (otarget,
00047                          resolver,
00048                          detail,
00049                          response_expected)
00050   {
00051   }


Member Function Documentation

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

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.

Note:
A location forwarding loop may occur where a client is bounced from the original target to the forwarded target and back if the application is not equipped to handle retries of previously called targets. TAO may be able to help in this case but it ultimately ends up being an application issue.

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   }

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

Invocation_Status TAO::Synch_Twoway_Invocation::location_forward TAO_InputCDR cdr  )  [protected]
 

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   }

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(), 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   }

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


The documentation for this class was generated from the following files:
Generated on Sun Jan 27 13:18:43 2008 for TAO by doxygen 1.3.6