Synch_Invocation.cpp

Go to the documentation of this file.
00001 // $Id: Synch_Invocation.cpp 81632 2008-05-07 09:19:05Z vzykov $
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 81632 2008-05-07 09:19:05Z vzykov $")
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     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   }
00230 
00231   Invocation_Status
00232   Synch_Twoway_Invocation::wait_for_reply (ACE_Time_Value *max_wait_time,
00233                                            TAO_Synch_Reply_Dispatcher &rd,
00234                                            TAO_Bind_Dispatcher_Guard &bd)
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   }
00323 
00324   Invocation_Status
00325   Synch_Twoway_Invocation::check_reply_status (TAO_Synch_Reply_Dispatcher &rd)
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   }
00423 
00424   Invocation_Status
00425   Synch_Twoway_Invocation::location_forward (TAO_InputCDR &inp_stream)
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   }
00453 
00454   Invocation_Status
00455   Synch_Twoway_Invocation::handle_user_exception (TAO_InputCDR &cdr)
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   }
00500 
00501   Invocation_Status
00502   Synch_Twoway_Invocation::handle_system_exception (TAO_InputCDR &cdr)
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   }
00607 
00608   // =========================================================================
00609 
00610   Synch_Oneway_Invocation::Synch_Oneway_Invocation (
00611     CORBA::Object_ptr otarget,
00612     Profile_Transport_Resolver &r,
00613     TAO_Operation_Details &d)
00614     : Synch_Twoway_Invocation (otarget, r, d, false)
00615   {
00616   }
00617 
00618   Invocation_Status
00619   Synch_Oneway_Invocation::remote_oneway (ACE_Time_Value *max_wait_time)
00620   {
00621     ACE_Countdown_Time countdown (max_wait_time);
00622 
00623     CORBA::Octet const response_flags = this->details_.response_flags ();
00624 
00625     Invocation_Status s = TAO_INVOKE_FAILURE;
00626 
00627     if (response_flags == CORBA::Octet (Messaging::SYNC_WITH_SERVER) ||
00628         response_flags == CORBA::Octet (Messaging::SYNC_WITH_TARGET))
00629       {
00630         s = Synch_Twoway_Invocation::remote_twoway (max_wait_time);
00631 
00632         return s;
00633       }
00634 
00635 #if TAO_HAS_INTERCEPTORS == 1
00636     s = this->send_request_interception ();
00637 
00638     if (s != TAO_INVOKE_SUCCESS)
00639       return s;
00640 
00641     try
00642       {
00643 #endif /*TAO_HAS_INTERCEPTORS */
00644         TAO_Transport* const transport = this->resolver_.transport ();
00645 
00646         if (!transport)
00647           {
00648             // Way back, we failed to find a profile we could connect to.
00649             // We've come this far only so we reach the interception points
00650             // in case they can fix things. Time to bail....
00651             throw CORBA::TRANSIENT (CORBA::OMGVMCID | 2, CORBA::COMPLETED_NO);
00652           }
00653 
00654         TAO_OutputCDR &cdr = transport->out_stream ();
00655 
00656         cdr.message_attributes (this->details_.request_id (),
00657                                 this->resolver_.stub (),
00658                                 TAO_Transport::TAO_ONEWAY_REQUEST,
00659                                 max_wait_time);
00660 
00661         this->write_header (cdr);
00662 
00663         this->marshal_data (cdr);
00664 
00665         countdown.update ();
00666 
00667         if (transport->is_connected ())
00668           {
00669             // We have a connected transport so we can send the message
00670             s = this->send_message (cdr,
00671                                     TAO_Transport::TAO_ONEWAY_REQUEST,
00672                                     max_wait_time);
00673           }
00674         else
00675           {
00676             if (TAO_debug_level > 4)
00677               ACE_DEBUG ((LM_DEBUG,
00678                           "TAO (%P|%t) - Synch_Oneway_Invocation::"
00679                           "remote_oneway, queueing message\n"));
00680 
00681             if (transport->format_queue_message (cdr, max_wait_time) != 0)
00682               s = TAO_INVOKE_FAILURE;
00683           }
00684 
00685 #if TAO_HAS_INTERCEPTORS == 1
00686         s = this->receive_other_interception ();
00687       }
00688     catch ( ::CORBA::Exception& ex)
00689       {
00690         PortableInterceptor::ReplyStatus const status =
00691           this->handle_any_exception (&ex);
00692 
00693         if (status == PortableInterceptor::LOCATION_FORWARD ||
00694             status == PortableInterceptor::TRANSPORT_RETRY)
00695           s = TAO_INVOKE_RESTART;
00696         else if (status == PortableInterceptor::SYSTEM_EXCEPTION
00697             || status == PortableInterceptor::USER_EXCEPTION)
00698           throw;
00699       }
00700     catch (...)
00701       {
00702         // Notify interceptors of non-CORBA exception, and propagate
00703         // that exception to the caller.
00704 
00705          PortableInterceptor::ReplyStatus const st =
00706            this->handle_all_exception ();
00707 
00708          if (st == PortableInterceptor::LOCATION_FORWARD ||
00709              st == PortableInterceptor::TRANSPORT_RETRY)
00710            s = TAO_INVOKE_RESTART;
00711          else
00712            throw;
00713       }
00714 #endif /* TAO_HAS_INTERCEPTORS */
00715 
00716     return s;
00717   }
00718 }
00719 
00720 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:37:52 2010 for TAO by  doxygen 1.4.7