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) throw (CORBA::Exception)

Protected Member Functions

virtual Invocation_Status handle_user_exception (TAO_InputCDR &cdr) throw (CORBA::Exception)
Invocation_Status location_forward (TAO_InputCDR &cdr) throw (CORBA::SystemException)
 Helper method used to handle location forwarded replies.

Invocation_Status handle_system_exception (TAO_InputCDR &cdr) throw (CORBA::SystemException)
Invocation_Status wait_for_reply (ACE_Time_Value *max_wait_time, TAO_Synch_Reply_Dispatcher &rd, TAO_Bind_Dispatcher_Guard &bd) throw (CORBA::SystemException)
 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 40 of file Synch_Invocation.cpp.

References CORBA::Object_ptr.

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


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 368 of file Synch_Invocation.cpp.

References ACE_CHECK_RETURN, ACE_DEBUG, ACE_ENV_ARG_PARAMETER, ACE_THROW_RETURN, 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::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().

00370   {
00371     /*
00372      * Precondition: We probably got a reply. <ACE_Thread::self> is
00373      * checking the status of the reply
00374      *
00375      * Postcondition: Any error while reading the reply is marked by
00376      * raising an exception. LOCATION_FORWARDED replies are marked by
00377      * returning a restart since that is what needed to be done by the
00378      * callee.
00379      */
00380     TAO_InputCDR &cdr =
00381       rd.reply_cdr ();
00382 
00383     // Set the translators
00384     this->resolver_.transport ()->assign_translators (&cdr, 0);
00385 
00386     // At this point it can be assumed that the GIOP/whatever protocol
00387     // header and the reply header are already handled.  Further it
00388     // can be assumed that the reply body contains the details
00389     // required for further processing. All the other details should
00390     // have been handled in the reply dispatcher/protocol framework.
00391     switch (rd.reply_status ())
00392       {
00393       case TAO_PLUGGABLE_MESSAGE_NO_EXCEPTION:
00394         {
00395           Reply_Guard mon (this,
00396                            TAO_INVOKE_FAILURE);
00397           if (this->details_.demarshal_args (cdr) == false)
00398             {
00399               ACE_THROW_RETURN (CORBA::MARSHAL (),
00400                                 TAO_INVOKE_FAILURE);
00401             }
00402 
00403           mon.set_status (TAO_INVOKE_SUCCESS);
00404         }
00405         break;
00406       case TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD:
00407         return this->location_forward (cdr
00408                                        ACE_ENV_ARG_PARAMETER);
00409       case TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD_PERM:
00410         {
00411           // Unmarshal the location forward object and set the
00412           // variable this->forward_to_.
00413           const Invocation_Status s
00414             = this->location_forward (cdr
00415                                       ACE_ENV_ARG_PARAMETER);
00416           if (s != TAO_INVOKE_FAILURE)
00417             {
00418               // de-marshalling of permanent object reference was successfull
00419               const CORBA::Boolean permanent_forward_condition =
00420                 this->orb_core ()->is_permanent_forward_condition
00421                   (this->forwarded_to_.in (),
00422                    this->request_service_context ());
00423 
00424               if (!permanent_forward_condition)
00425                 {
00426                    // permanent condition not given
00427                     if (TAO_debug_level > 3)
00428                         ACE_DEBUG ((LM_DEBUG,
00429                                "TAO (%P|%t) - Synch_Twoway_Invocation::"
00430                                 "check_reply_status: unexpected LOCATION_FORWARD_PERM reply\n"));
00431 
00432                    ACE_THROW_RETURN (CORBA::INTERNAL (0, CORBA::COMPLETED_NO),
00433                                      TAO_INVOKE_FAILURE);
00434                 }
00435             }
00436 
00437           return s;
00438         }
00439       case TAO_PLUGGABLE_MESSAGE_USER_EXCEPTION:
00440         return this->handle_user_exception (cdr
00441                                             ACE_ENV_ARG_PARAMETER);
00442       case TAO_PLUGGABLE_MESSAGE_SYSTEM_EXCEPTION:
00443         return this->handle_system_exception (cdr
00444                                               ACE_ENV_ARG_PARAMETER);
00445 
00446       case TAO_PLUGGABLE_MESSAGE_NEEDS_ADDRESSING_MODE:
00447         {
00448           Reply_Guard mon (this,
00449                            TAO_INVOKE_FAILURE);
00450           // We have received a message with a request to change the
00451           // addressing mode. First let us read the mode that the
00452           // server/agent asks for.
00453           CORBA::Short addr_mode = 0;
00454 
00455           if (cdr.read_short (addr_mode) == 0)
00456             {
00457               // Could not demarshal the addressing disposition, raise an local
00458               // CORBA::MARSHAL
00459             ACE_THROW_RETURN (CORBA::MARSHAL (0,
00460                                               CORBA::COMPLETED_MAYBE),
00461                               TAO_INVOKE_FAILURE);
00462             }
00463 
00464           // Now set this addressing mode in the profile, so that
00465           // the next invocation need not go through this.
00466           this->resolver_.profile ()->addressing_mode (addr_mode
00467                                                        ACE_ENV_ARG_PARAMETER);
00468           ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00469 
00470           mon.set_status (TAO_INVOKE_RESTART);
00471 
00472           // Now restart the invocation
00473           return TAO_INVOKE_RESTART;
00474         }
00475     }
00476     return TAO_INVOKE_SUCCESS;
00477   }

Invocation_Status TAO::Synch_Twoway_Invocation::handle_system_exception TAO_InputCDR cdr  )  throw (CORBA::SystemException) [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 575 of file Synch_Invocation.cpp.

References ACE_CHECK_RETURN, ACE_DEBUG, ACE_ENV_ARG_PARAMETER, ACE_ENV_RAISE, ACE_NEW_RETURN, ACE_THROW_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::Reply_Guard::set_status(), CORBA::String_var, TAO_debug_level, TAO::TAO_INVOKE_FAILURE, TAO::TAO_INVOKE_RESTART, and TAO::TAO_INVOKE_SYSTEM_EXCEPTION.

Referenced by check_reply_status().

00578   {
00579     Reply_Guard mon (this, TAO_INVOKE_FAILURE);
00580 
00581     if (TAO_debug_level > 3)
00582       ACE_DEBUG ((LM_DEBUG,
00583                   "TAO (%P|%t) - Synch_Twoway_Invocation::"
00584                   "handle_system_exception \n"));
00585 
00586     CORBA::String_var type_id;
00587 
00588     if ((cdr >> type_id.inout ()) == 0)
00589       {
00590         // Could not demarshal the exception id, raise an local
00591         // CORBA::MARSHAL
00592         ACE_THROW_RETURN (CORBA::MARSHAL (0,
00593                                           CORBA::COMPLETED_MAYBE),
00594                           TAO_INVOKE_FAILURE);
00595       }
00596 
00597     CORBA::ULong minor = 0;
00598     CORBA::ULong completion = 0;
00599 
00600     if ((cdr >> minor) == 0
00601         || (cdr >> completion) == 0)
00602       {
00603         ACE_THROW_RETURN (CORBA::MARSHAL (0,
00604                                           CORBA::COMPLETED_MAYBE),
00605                           TAO_INVOKE_FAILURE);
00606       }
00607 
00608     // Special handling for non-fatal system exceptions.
00609     //
00610     // Note that we are careful to retain "at most once" semantics.
00611     if ((ACE_OS_String::strcmp (type_id.in (),
00612                                 "IDL:omg.org/CORBA/TRANSIENT:1.0")   == 0 ||
00613          ACE_OS_String::strcmp (type_id.in (),
00614                                 "IDL:omg.org/CORBA/OBJ_ADAPTER:1.0") == 0 ||
00615          ACE_OS_String::strcmp (type_id.in (),
00616                                 "IDL:omg.org/CORBA/NO_RESPONSE:1.0") == 0 ||
00617          ACE_OS_String::strcmp (type_id.in (),
00618                                 "IDL:omg.org/CORBA/COMM_FAILURE:1.0") == 0) &&
00619         (CORBA::CompletionStatus) completion != CORBA::COMPLETED_YES)
00620       {
00621         {
00622           // Start the special case for FTCORBA.
00623           /**
00624            * There has been a unanimous view that this is not the
00625            * right way to do things. But a need to be compliant is
00626            * forcing us into this.
00627            */
00628           const Invocation_Status s =
00629             this->orb_core ()->service_raise_transient_failure (
00630               this->details_.request_service_context ().service_info (),
00631               this->resolver_.profile ()
00632               ACE_ENV_ARG_PARAMETER);
00633           ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00634 
00635           if (s == TAO_INVOKE_RESTART)
00636             return s;
00637         }
00638 
00639         // Attempt profile retry.
00640         /**
00641          * @note A location forwarding loop may occur where a client
00642          *       is bounced from the original target to the forwarded
00643          *       target and back if the application is not equipped to
00644          *       handle retries of previously called targets.  TAO may
00645          *       be able to help in this case but it ultimately ends
00646          *       up being an application issue.
00647          */
00648         if (this->resolver_.stub ()->next_profile_retry ())
00649           {
00650             return TAO_INVOKE_RESTART;
00651           }
00652 
00653         // Fall through and raise an exception.
00654       }
00655 
00656     CORBA::SystemException *ex =
00657       TAO::create_system_exception (type_id.in ());
00658 
00659     if (ex == 0)
00660       {
00661         // @@ We should raise a CORBA::NO_MEMORY, but we ran out
00662         //    of memory already. We need a pre-allocated, TSS,
00663         //    CORBA::NO_MEMORY instance
00664         ACE_NEW_RETURN (ex,
00665                         CORBA::UNKNOWN,
00666                         TAO_INVOKE_FAILURE);
00667       }
00668 
00669 #if defined (TAO_HAS_EXCEPTIONS)
00670     // Without this, the call to create_system_exception() above
00671     // causes a memory leak. On platforms without native exceptions,
00672     // the CORBA::Environment class manages the memory.
00673     auto_ptr<CORBA::SystemException> safety (ex);
00674 #endif
00675 
00676     ex->minor (minor);
00677     ex->completed (CORBA::CompletionStatus (completion));
00678 
00679     if (TAO_debug_level > 4)
00680       ACE_DEBUG ((LM_DEBUG,
00681                   "TAO (%P|%t) - Synch_Twoway_Invocation::"
00682                   "handle_system_exception, about to raise\n"));
00683 
00684     mon.set_status (TAO_INVOKE_SYSTEM_EXCEPTION);
00685 
00686     // Raise the exception.
00687     ACE_ENV_RAISE (ex);
00688 
00689     return TAO_INVOKE_SYSTEM_EXCEPTION;
00690   }

Invocation_Status TAO::Synch_Twoway_Invocation::handle_user_exception TAO_InputCDR cdr  )  throw (CORBA::Exception) [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 514 of file Synch_Invocation.cpp.

References CORBA::Exception::_raise(), CORBA::Exception::_tao_decode(), ACE_CHECK_RETURN, ACE_DEBUG, ACE_ENV_ARG_PARAMETER, ACE_TEXT, ACE_TEXT_CHAR_TO_TCHAR, ACE_THROW_RETURN, ACE_TRY_ENV, 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().

00517   {
00518     Reply_Guard mon (this,
00519                      TAO_INVOKE_FAILURE);
00520 
00521     if (TAO_debug_level > 3)
00522       ACE_DEBUG ((LM_DEBUG,
00523                   "TAO (%P|%t) - Synch_Twoway_Invocation::"
00524                   "handle_user_exception \n"));
00525 
00526     // Pull the exception from the stream.
00527     CORBA::String_var buf;
00528 
00529     if ((cdr >> buf.inout ()) == 0)
00530       {
00531         // Could not demarshal the exception id, raise an local
00532         // CORBA::MARSHAL
00533         ACE_THROW_RETURN (CORBA::MARSHAL (0,
00534                                           CORBA::COMPLETED_MAYBE),
00535                           TAO_INVOKE_FAILURE);
00536       }
00537 
00538     CORBA::Exception *exception =
00539       this->details_.corba_exception (buf.in ()
00540                                       ACE_ENV_ARG_PARAMETER);
00541     ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00542 
00543     exception->_tao_decode (cdr
00544                             ACE_ENV_ARG_PARAMETER);
00545     ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00546 
00547     if (TAO_debug_level > 5)
00548       {
00549         ACE_DEBUG ((LM_DEBUG,
00550                     ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::")
00551                     ACE_TEXT ("handle_user_exception - ")
00552                     ACE_TEXT ("raising exception %s\n"),
00553                     ACE_TEXT_CHAR_TO_TCHAR (buf.in ())));
00554       }
00555 
00556     mon.set_status (TAO_INVOKE_USER_EXCEPTION);
00557 
00558 #if defined (TAO_HAS_EXCEPTIONS)
00559     // If we have native exceptions, we must manage the memory allocated
00560     // by the call above to alloc(). Otherwise the Environment class
00561     // manages the memory.
00562     auto_ptr<CORBA::Exception> safety (exception);
00563 
00564     // Direct throw because we don't have the ACE_TRY_ENV.
00565     exception->_raise ();
00566 #else
00567     // We can not use ACE_THROW here.
00568     ACE_TRY_ENV.exception (exception);
00569 #endif
00570 
00571     return TAO_INVOKE_USER_EXCEPTION;
00572   }

Invocation_Status TAO::Synch_Twoway_Invocation::location_forward TAO_InputCDR cdr  )  throw (CORBA::SystemException) [protected]
 

Helper method used to handle location forwarded replies.

Definition at line 480 of file Synch_Invocation.cpp.

References ACE_DEBUG, ACE_TEXT, ACE_THROW_RETURN, 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().

00483   {
00484     Reply_Guard mon (this,
00485                      TAO_INVOKE_FAILURE);
00486 
00487     if (TAO_debug_level > 3)
00488       {
00489         ACE_DEBUG ((LM_DEBUG,
00490                     ACE_TEXT ("TAO (%P|%t) - Synch_Twoway_Invocation::location_forward ")
00491                     ACE_TEXT ("being handled \n")));
00492       }
00493 
00494     CORBA::Object_var fwd;
00495 
00496     if ((inp_stream >> fwd) == 0)
00497       {
00498         ACE_THROW_RETURN (CORBA::MARSHAL (
00499             CORBA::SystemException::_tao_minor_code (
00500               TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00501               errno),
00502             CORBA::COMPLETED_NO),
00503                           TAO_INVOKE_FAILURE);
00504       }
00505 
00506     this->forwarded_reference (fwd.in ());
00507 
00508     mon.set_status (TAO_INVOKE_RESTART);
00509 
00510     return TAO_INVOKE_RESTART;
00511   }

Invocation_Status TAO::Synch_Twoway_Invocation::remote_twoway ACE_Time_Value max_wait_time  )  throw (CORBA::Exception)
 

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 53 of file Synch_Invocation.cpp.

References ACE_ANY_EXCEPTION, ACE_CATCHALL, ACE_CATCHANY, ACE_CHECK_RETURN, ACE_ENDTRY, ACE_ENV_ARG_PARAMETER, ACE_ENV_SINGLE_ARG_PARAMETER, ACE_RE_THROW, ACE_THROW_RETURN, ACE_TRY, ACE_TRY_CHECK, TAO::Invocation_Status, TAO_OutputCDR::message_attributes(), PortableInterceptor::ReplyStatus, TAO_Bind_Dispatcher_Guard::status(), TAO::TAO_INVOKE_FAILURE, TAO::TAO_INVOKE_RESTART, TAO::TAO_INVOKE_SUCCESS, and ACE_Countdown_Time::update().

Referenced by TAO::Invocation_Adapter::invoke_twoway().

00056   {
00057     ACE_Countdown_Time countdown (max_wait_time);
00058 
00059     TAO_Synch_Reply_Dispatcher rd (this->resolver_.stub ()->orb_core (),
00060                                    this->details_.reply_service_info ());
00061 
00062     TAO_Target_Specification tspec;
00063     this->init_target_spec (tspec ACE_ENV_ARG_PARAMETER);
00064     ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00065 
00066     Invocation_Status s = TAO_INVOKE_FAILURE;
00067 
00068 #if TAO_HAS_INTERCEPTORS == 1
00069     // Start the interception point here..
00070     s =
00071       this->send_request_interception (ACE_ENV_SINGLE_ARG_PARAMETER);
00072     ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00073 
00074     if (s != TAO_INVOKE_SUCCESS)
00075       return s;
00076 #endif /*TAO_HAS_INTERCEPTORS */
00077 
00078     // We have started the interception flow. We need to call the
00079     // ending interception flow if things go wrong. The purpose of the
00080     // try block is to do just this.
00081     ACE_TRY
00082       {
00083         TAO_OutputCDR &cdr = this->resolver_.transport ()->out_stream ();
00084 
00085         cdr.message_attributes (this->details_.request_id (),
00086                                 this->resolver_.stub (),
00087                                 TAO_Transport::TAO_TWOWAY_REQUEST,
00088                                 max_wait_time);
00089 
00090         this->write_header (tspec,
00091                             cdr
00092                             ACE_ENV_ARG_PARAMETER);
00093         ACE_TRY_CHECK;
00094 
00095         this->marshal_data (cdr
00096                             ACE_ENV_ARG_PARAMETER);
00097         ACE_TRY_CHECK;
00098 
00099         // Register a reply dispatcher for this invocation. Use the
00100         // preallocated reply dispatcher.
00101         TAO_Bind_Dispatcher_Guard dispatch_guard (
00102           this->details_.request_id (),
00103           &rd,
00104           this->resolver_.transport ()->tms ());
00105 
00106         if (dispatch_guard.status () != 0)
00107           {
00108             // @@ What is the right way to handle this error? Why should
00109             // we close the connection?
00110             this->resolver_.transport ()->close_connection ();
00111 
00112             ACE_THROW_RETURN (
00113               CORBA::INTERNAL (
00114                                0,
00115                                CORBA::COMPLETED_NO),
00116               s);
00117           }
00118 
00119         countdown.update ();
00120 
00121         s = this->send_message (cdr,
00122                                 TAO_Transport::TAO_TWOWAY_REQUEST,
00123                                 max_wait_time
00124                                 ACE_ENV_ARG_PARAMETER);
00125         ACE_TRY_CHECK;
00126 
00127 #if TAO_HAS_INTERCEPTORS == 1
00128         // @@NOTE: Too much code repetition.
00129         // If the above call returns a restart due to connection
00130         // failure then call the receive_other interception point
00131         // before we leave.
00132         if (s == TAO_INVOKE_RESTART)
00133           {
00134             const Invocation_Status tmp =
00135               this->receive_other_interception (ACE_ENV_SINGLE_ARG_PARAMETER);
00136             ACE_TRY_CHECK;
00137 
00138             if (tmp != TAO_INVOKE_SUCCESS)
00139               s = tmp;
00140           }
00141 #endif /*TAO_HAS_INTERCEPTORS */
00142 
00143         if (s != TAO_INVOKE_SUCCESS)
00144           return s;
00145 
00146         countdown.update ();
00147 
00148         // For some strategies one may want to release the transport
00149         // back to  cache. If the idling is successfull let the
00150         // resolver about that.
00151         if (this->resolver_.transport ()->idle_after_send ())
00152           this->resolver_.transport_released ();
00153 
00154         // @@ In all MT environments, there's a cancellation point lurking
00155         // here; need to investigate.  Client threads would frequently be
00156         // canceled sometime during recv_request ... the correct action to
00157         // take on being canceled is to issue a CancelRequest message to the
00158         // server and then imediately let other client-side cancellation
00159         // handlers do their jobs.
00160         //
00161         // In C++, that basically means to unwind the stack using almost
00162         // normal procedures: all destructors should fire, and some "catch"
00163         // blocks should probably be able to handle things like releasing
00164         // pointers. (Without unwinding the C++ stack, resources that must
00165         // be freed by thread cancellation won't be freed, and the process
00166         // won't continue to function correctly.)  The tricky part is that
00167         // according to POSIX, all C stack frames must also have their
00168         // (explicitly coded) handlers called.  We assume a POSIX.1c/C/C++
00169         // environment.
00170 
00171         s =
00172           this->wait_for_reply (max_wait_time,
00173                                 rd,
00174                                 dispatch_guard
00175                                 ACE_ENV_ARG_PARAMETER);
00176         ACE_TRY_CHECK;
00177 
00178 #if TAO_HAS_INTERCEPTORS == 1
00179         if (s == TAO_INVOKE_RESTART)
00180           {
00181             Invocation_Status tmp =
00182               this->receive_other_interception (ACE_ENV_SINGLE_ARG_PARAMETER);
00183             ACE_TRY_CHECK;
00184 
00185             // Push the latest values for the return..
00186             if (tmp != TAO_INVOKE_SUCCESS)
00187               s = tmp;
00188           }
00189 #endif /*TAO_HAS_INTERCEPTORS */
00190 
00191         if (s != TAO_INVOKE_SUCCESS)
00192           return s;
00193 
00194         // What happens when the above call returns an error through
00195         // the return value? That would be bogus as per the contract
00196         // in the interface. The call violated the contract
00197 
00198         s = this->check_reply_status (rd
00199                                       ACE_ENV_ARG_PARAMETER);
00200         ACE_TRY_CHECK;
00201 
00202         // For some strategies one may want to release the transport
00203         // back to  cache after receiving the reply.
00204         if (this->resolver_.transport ()->idle_after_reply ())
00205           this->resolver_.transport_released ();
00206 
00207 #if TAO_HAS_INTERCEPTORS == 1
00208         Invocation_Status tmp = TAO_INVOKE_FAILURE;
00209         if (s == TAO_INVOKE_RESTART)
00210           {
00211             tmp =
00212               this->receive_other_interception (ACE_ENV_SINGLE_ARG_PARAMETER);
00213             ACE_TRY_CHECK;
00214           }
00215         else if (s == TAO_INVOKE_SUCCESS)
00216           {
00217             tmp  =
00218               this->receive_reply_interception (ACE_ENV_SINGLE_ARG_PARAMETER);
00219             ACE_TRY_CHECK;
00220           }
00221         if (tmp != TAO_INVOKE_SUCCESS)
00222           s = tmp;
00223 #endif /*TAO_HAS_INTERCEPTORS */
00224 
00225         if (s != TAO_INVOKE_SUCCESS)
00226           return s;
00227       }
00228     ACE_CATCHANY
00229       {
00230 #if TAO_HAS_INTERCEPTORS == 1
00231         const PortableInterceptor::ReplyStatus status =
00232           this->handle_any_exception (&ACE_ANY_EXCEPTION
00233                                       ACE_ENV_ARG_PARAMETER);
00234         ACE_TRY_CHECK;
00235 
00236         if (status == PortableInterceptor::LOCATION_FORWARD ||
00237             status == PortableInterceptor::TRANSPORT_RETRY)
00238           s = TAO_INVOKE_RESTART;
00239         else if (status == PortableInterceptor::SYSTEM_EXCEPTION
00240                  || status == PortableInterceptor::USER_EXCEPTION)
00241 #endif /*TAO_HAS_INTERCEPTORS*/
00242           ACE_RE_THROW;
00243       }
00244 # if defined (ACE_HAS_EXCEPTIONS) \
00245      && defined (ACE_HAS_BROKEN_UNEXPECTED_EXCEPTIONS)
00246     ACE_CATCHALL
00247       {
00248 #if TAO_HAS_INTERCEPTORS == 1
00249         const PortableInterceptor::ReplyStatus st =
00250           this->handle_all_exception (ACE_ENV_SINGLE_ARG_PARAMETER);
00251         ACE_TRY_CHECK;
00252 
00253         if (st == PortableInterceptor::LOCATION_FORWARD ||
00254             st == PortableInterceptor::TRANSPORT_RETRY)
00255           s = TAO_INVOKE_RESTART;
00256         else
00257 #endif /*TAO_HAS_INTERCEPTORS == 1*/
00258           ACE_RE_THROW;
00259       }
00260 # endif  /* ACE_HAS_EXCEPTIONS &&
00261             ACE_HAS_BROKEN_UNEXPECTED_EXCEPTION*/
00262     ACE_ENDTRY;
00263     ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00264 
00265     return s;
00266   }

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
throw (CORBA::SystemException) [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 269 of file Synch_Invocation.cpp.

References ACE_CATCHANY, ACE_DEBUG, ACE_ENDTRY, ACE_ENV_ARG_PARAMETER, ACE_RE_THROW, ACE_THROW_RETURN, ACE_TRY, ACE_TRY_CHECK, ETIME, LM_DEBUG, TAO_debug_level, TAO::TAO_INVOKE_FAILURE, TAO::TAO_INVOKE_SUCCESS, and TAO_TIMEOUT_RECV_MINOR_CODE.

00274   {
00275     /*
00276      * Precondition: The call went to the remote
00277      * peer. <ACE_Thread::self> is waiting for the reply.
00278      *
00279      * Postcondition: Any error during a wait is marked by raising an
00280      * exception. Success alone is returned through the return value.
00281      */
00282 
00283     const int reply_error =
00284       this->resolver_.transport ()->wait_strategy ()->wait (max_wait_time,
00285                                                             rd);
00286     if (TAO_debug_level > 0 && max_wait_time != 0)
00287       {
00288         const CORBA::ULong msecs = max_wait_time->msec ();
00289 
00290         ACE_DEBUG ((LM_DEBUG,
00291                     "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, "
00292                     "timeout after recv is <%u> status <%d>\n",
00293                     msecs,
00294                     reply_error));
00295       }
00296 
00297     // Check the reply error.
00298     if (reply_error == -1)
00299       {
00300         // Unbind the dispatcher, since its of no use at this point of
00301         // time
00302         if (TAO_debug_level > 3)
00303           {
00304             ACE_DEBUG ((LM_DEBUG,
00305                         "TAO (%P|%t) - Synch_Twoway_Invocation::wait_for_reply, "
00306                         "recovering after an error \n"));
00307           }
00308 
00309         // You the smarty, don't try to moving the unbind_dispatcher
00310         // () call since it looks like it is repeated twice. That
00311         // could land you in trouble. If you don't believe this
00312         // warning go ahead and try. Try running tests to see what is
00313         // going on ;)
00314         if (errno == ETIME)
00315           {
00316             // If the unbind succeeds then thrown an exception to the
00317             // application, else just collect the reply and dispatch
00318             // that to the application.
00319             //
00320             // NOTE: A fragile synchronization is provided when using
00321             // the Muxed Transport strategy. We could infact be a
00322             // follower thread getting timedout in the LF whereas the
00323             // dispatching thread could be on the reply_dispatcher
00324             // that we created. This would lead bad crashes. To get
00325             // around that, the call to unbind_dispatcher () will wait
00326             // on the lock on the Muxed_Transport_Strategy if
00327             // dispatching has started. This is fragile.
00328             if (bd.unbind_dispatcher () == 0)
00329               {
00330                 // Just a timeout with completed_maybe, don't close
00331                 // the connection or  anything
00332                 ACE_THROW_RETURN (CORBA::TIMEOUT (
00333                                     CORBA::SystemException::_tao_minor_code (
00334                                       TAO_TIMEOUT_RECV_MINOR_CODE,
00335                                       errno),
00336                                     CORBA::COMPLETED_MAYBE),
00337                                   TAO_INVOKE_FAILURE);
00338               }
00339           }
00340         else
00341           {
00342             (void) bd.unbind_dispatcher ();
00343             this->resolver_.transport ()->close_connection ();
00344 
00345             ACE_TRY
00346               {
00347                 return
00348                   this->orb_core ()->service_raise_comm_failure (
00349                     this->details_.request_service_context ().service_info (),
00350                     this->resolver_.profile ()
00351                     ACE_ENV_ARG_PARAMETER);
00352                 ACE_TRY_CHECK;
00353 
00354               }
00355             ACE_CATCHANY
00356               {
00357                 this->resolver_.stub ()->reset_profiles ();
00358                 ACE_RE_THROW;
00359               }
00360             ACE_ENDTRY;
00361           }
00362       }
00363 
00364     return TAO_INVOKE_SUCCESS;
00365   }


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 12:27:00 2006 for TAO by doxygen 1.3.6