Synch_Invocation.cpp File Reference

#include "tao/Synch_Invocation.h"
#include "tao/Profile_Transport_Resolver.h"
#include "tao/Profile.h"
#include "tao/Synch_Reply_Dispatcher.h"
#include "tao/Transport.h"
#include "tao/Stub.h"
#include "tao/Bind_Dispatcher_Guard.h"
#include "tao/operation_details.h"
#include "tao/Wait_Strategy.h"
#include "tao/debug.h"
#include "tao/ORB_Constants.h"
#include "tao/Messaging_SyncScopeC.h"
#include "tao/ORB_Core.h"
#include "tao/Service_Context.h"
#include "tao/SystemException.h"
#include "ace/Intrusive_Auto_Ptr.h"
#include "tao/PortableInterceptorC.h"
#include "ace/Auto_Ptr.h"
#include "ace/OS_NS_string.h"
#include "ace/Countdown_Time.h"
Include dependency graph for Synch_Invocation.cpp:

Go to the source code of this file.

Functions

 ACE_RCSID (tao, Synch_Invocation,"$Id: Synch_Invocation.cpp 86232 2009-07-24 21:52:20Z dai_y $") 1 namespace TAO

Function Documentation

ACE_RCSID ( tao  ,
Synch_Invocation  ,
"$Id: Synch_Invocation.cpp 86232 2009-07-24 21:52:20Z dai_y $"   
)

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

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

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Sat Nov 21 23:27:47 2009 for TAO by  doxygen 1.6.1