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.

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

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


The documentation for this class was generated from the following files:
Generated on Tue Feb 2 17:39:19 2010 for TAO by  doxygen 1.4.7