Synch_Invocation.cpp

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

Generated on Sun Jan 27 13:07:36 2008 for TAO by doxygen 1.3.6