Synch_Invocation.cpp

Go to the documentation of this file.
00001 // Synch_Invocation.cpp,v 1.36 2006/04/20 12:37:17 jwillemsen Exp
00002 
00003 #include "tao/Synch_Invocation.h"
00004 #include "tao/Profile_Transport_Resolver.h"
00005 #include "tao/Profile.h"
00006 #include "tao/Synch_Reply_Dispatcher.h"
00007 #include "tao/Transport.h"
00008 #include "tao/Stub.h"
00009 #include "tao/Bind_Dispatcher_Guard.h"
00010 #include "tao/operation_details.h"
00011 #include "tao/Wait_Strategy.h"
00012 #include "tao/debug.h"
00013 #include "tao/ORB_Constants.h"
00014 #include "tao/Messaging_SyncScopeC.h"
00015 #include "tao/ORB_Core.h"
00016 #include "tao/Service_Context.h"
00017 
00018 #if TAO_HAS_INTERCEPTORS == 1
00019 # include "tao/PortableInterceptorC.h"
00020 #endif /*TAO_HAS_INTERCEPTORS */
00021 
00022 #include "ace/Auto_Ptr.h"
00023 #include "ace/OS_NS_string.h"
00024 #include "ace/Countdown_Time.h"
00025 
00026 #if !defined (__ACE_INLINE__)
00027 # include "tao/Synch_Invocation.inl"
00028 #endif /* __ACE_INLINE__ */
00029 
00030 
00031 ACE_RCSID (tao,
00032            Synch_Invocation,
00033            "Synch_Invocation.cpp,v 1.36 2006/04/20 12:37:17 jwillemsen Exp")
00034 
00035 
00036 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00037 
00038 namespace TAO
00039 {
00040   Synch_Twoway_Invocation::Synch_Twoway_Invocation (
00041     CORBA::Object_ptr otarget,
00042     Profile_Transport_Resolver &resolver,
00043     TAO_Operation_Details &detail,
00044     bool response_expected)
00045     : Remote_Invocation (otarget,
00046                          resolver,
00047                          detail,
00048                          response_expected)
00049   {
00050   }
00051 
00052   Invocation_Status
00053   Synch_Twoway_Invocation::remote_twoway (ACE_Time_Value *max_wait_time
00054                                           ACE_ENV_ARG_DECL)
00055     ACE_THROW_SPEC ((CORBA::Exception))
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   }
00267 
00268   Invocation_Status
00269   Synch_Twoway_Invocation::wait_for_reply (ACE_Time_Value *max_wait_time,
00270                                            TAO_Synch_Reply_Dispatcher &rd,
00271                                            TAO_Bind_Dispatcher_Guard &bd
00272                                            ACE_ENV_ARG_DECL)
00273     ACE_THROW_SPEC ((CORBA::SystemException))
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   }
00366 
00367   Invocation_Status
00368   Synch_Twoway_Invocation::check_reply_status (TAO_Synch_Reply_Dispatcher &rd
00369                                                ACE_ENV_ARG_DECL)
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   }
00478 
00479   Invocation_Status
00480   Synch_Twoway_Invocation::location_forward (TAO_InputCDR &inp_stream
00481                                              ACE_ENV_ARG_DECL)
00482     ACE_THROW_SPEC ((CORBA::SystemException))
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   }
00512 
00513   Invocation_Status
00514   Synch_Twoway_Invocation::handle_user_exception (TAO_InputCDR &cdr
00515                                                   ACE_ENV_ARG_DECL)
00516     ACE_THROW_SPEC ((CORBA::Exception))
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   }
00573 
00574   Invocation_Status
00575   Synch_Twoway_Invocation::handle_system_exception (TAO_InputCDR &cdr
00576                                                     ACE_ENV_ARG_DECL)
00577     ACE_THROW_SPEC ((CORBA::SystemException))
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   }
00691 
00692   // =========================================================================
00693 
00694   Synch_Oneway_Invocation::Synch_Oneway_Invocation (
00695     CORBA::Object_ptr otarget,
00696     Profile_Transport_Resolver &r,
00697     TAO_Operation_Details &d)
00698     : Synch_Twoway_Invocation (otarget, r, d, false)
00699   {
00700   }
00701 
00702   Invocation_Status
00703   Synch_Oneway_Invocation::remote_oneway (ACE_Time_Value *max_wait_time
00704                                           ACE_ENV_ARG_DECL)
00705     ACE_THROW_SPEC ((CORBA::Exception))
00706   {
00707     ACE_Countdown_Time countdown (max_wait_time);
00708 
00709     const CORBA::Octet response_flags =
00710        this->details_.response_flags ();
00711 
00712     Invocation_Status s = TAO_INVOKE_FAILURE;
00713 
00714     if (response_flags == CORBA::Octet (Messaging::SYNC_WITH_SERVER) ||
00715         response_flags == CORBA::Octet (Messaging::SYNC_WITH_TARGET))
00716       {
00717         s = Synch_Twoway_Invocation::remote_twoway (max_wait_time
00718                                                     ACE_ENV_ARG_PARAMETER);
00719         ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00720 
00721         return s;
00722       }
00723 
00724     TAO_Target_Specification tspec;
00725     this->init_target_spec (tspec ACE_ENV_ARG_PARAMETER);
00726     ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00727 
00728 #if TAO_HAS_INTERCEPTORS == 1
00729     s = this->send_request_interception (ACE_ENV_SINGLE_ARG_PARAMETER);
00730     ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00731 
00732     if (s != TAO_INVOKE_SUCCESS)
00733       return s;
00734 #endif /*TAO_HAS_INTERCEPTORS */
00735 
00736     TAO_Transport* transport =
00737       this->resolver_.transport ();
00738 
00739     TAO_OutputCDR &cdr = transport->out_stream ();
00740 
00741     ACE_TRY
00742       {
00743         cdr.message_attributes (this->details_.request_id (),
00744                                 this->resolver_.stub (),
00745                                 TAO_Transport::TAO_ONEWAY_REQUEST,
00746                                 max_wait_time);
00747 
00748         this->write_header (tspec,
00749                             cdr
00750                             ACE_ENV_ARG_PARAMETER);
00751         ACE_TRY_CHECK;
00752 
00753         this->marshal_data (cdr
00754                             ACE_ENV_ARG_PARAMETER);
00755         ACE_TRY_CHECK;
00756 
00757         countdown.update ();
00758 
00759         if (transport->is_connected())
00760           {
00761             // We have a connected transport so we can send the message
00762             s = this->send_message (cdr,
00763                                     TAO_Transport::TAO_ONEWAY_REQUEST,
00764                                     max_wait_time
00765                                     ACE_ENV_ARG_PARAMETER);
00766             ACE_TRY_CHECK;
00767           }
00768         else
00769           {
00770             if (TAO_debug_level > 4)
00771               ACE_DEBUG ((LM_DEBUG,
00772                           "TAO (%P|%t) - Synch_Oneway_Invocation::"
00773                           "remote_oneway, queueing message\n"));
00774 
00775             if (transport->format_queue_message (cdr) != 0)
00776               s = TAO_INVOKE_FAILURE;
00777           }
00778 
00779 #if TAO_HAS_INTERCEPTORS == 1
00780         s =
00781           this->receive_other_interception (ACE_ENV_SINGLE_ARG_PARAMETER);
00782         ACE_TRY_CHECK;
00783 #endif /*TAO_HAS_INTERCEPTORS */
00784       }
00785     ACE_CATCHANY
00786       {
00787 #if TAO_HAS_INTERCEPTORS == 1
00788         PortableInterceptor::ReplyStatus status =
00789           this->handle_any_exception (&ACE_ANY_EXCEPTION
00790                                       ACE_ENV_ARG_PARAMETER);
00791         ACE_TRY_CHECK;
00792 
00793         if (status == PortableInterceptor::LOCATION_FORWARD ||
00794             status == PortableInterceptor::TRANSPORT_RETRY)
00795           s = TAO_INVOKE_RESTART;
00796         else if (status == PortableInterceptor::SYSTEM_EXCEPTION
00797             || status == PortableInterceptor::USER_EXCEPTION)
00798 #endif /*TAO_HAS_INTERCEPTORS*/
00799           ACE_RE_THROW;
00800       }
00801 # if defined (ACE_HAS_EXCEPTIONS) \
00802      && defined (ACE_HAS_BROKEN_UNEXPECTED_EXCEPTIONS)
00803     ACE_CATCHALL
00804       {
00805 #if TAO_HAS_INTERCEPTORS == 1
00806         PortableInterceptor::ReplyStatus st =
00807           this->handle_all_exception (ACE_ENV_SINGLE_ARG_PARAMETER);
00808         ACE_TRY_CHECK;
00809 
00810         if (st == PortableInterceptor::LOCATION_FORWARD ||
00811             st == PortableInterceptor::TRANSPORT_RETRY)
00812           s = TAO_INVOKE_RESTART;
00813         else
00814 #endif /*TAO_HAS_INTERCEPTORS == 1*/
00815           ACE_RE_THROW;
00816       }
00817 # endif  /* ACE_HAS_EXCEPTIONS &&
00818             ACE_HAS_BROKEN_UNEXPECTED_EXCEPTION*/
00819     ACE_ENDTRY;
00820     ACE_CHECK_RETURN (TAO_INVOKE_FAILURE);
00821 
00822     return s;
00823   }
00824 }
00825 
00826 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 11:54:22 2006 for TAO by doxygen 1.3.6