Invocation_Adapter.cpp

Go to the documentation of this file.
00001 //$Id: Invocation_Adapter.cpp 79237 2007-08-07 09:48:21Z johnnyw $
00002 
00003 #include "tao/Invocation_Adapter.h"
00004 #include "tao/Profile_Transport_Resolver.h"
00005 #include "tao/operation_details.h"
00006 #include "tao/Stub.h"
00007 #include "tao/ORB_Core.h"
00008 #include "tao/Synch_Invocation.h"
00009 #include "tao/debug.h"
00010 #include "tao/Collocated_Invocation.h"
00011 #include "tao/Transport.h"
00012 #include "tao/Transport_Mux_Strategy.h"
00013 #include "tao/Collocation_Proxy_Broker.h"
00014 #include "tao/GIOP_Utils.h"
00015 #include "tao/TAOC.h"
00016 #include "tao/SystemException.h"
00017 #include "ace/Service_Config.h"
00018 
00019 #if !defined (__ACE_INLINE__)
00020 # include "tao/Invocation_Adapter.inl"
00021 #endif /* __ACE_INLINE__ */
00022 
00023 
00024 ACE_RCSID (tao,
00025            Invocation_Adapter,
00026            "$Id: Invocation_Adapter.cpp 79237 2007-08-07 09:48:21Z johnnyw $")
00027 
00028 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00029 
00030 namespace TAO
00031 {
00032   Invocation_Adapter::~Invocation_Adapter (void)
00033   {
00034   }
00035 
00036   void
00037   Invocation_Adapter::invoke (TAO::Exception_Data *ex_data,
00038                               unsigned long ex_count)
00039   {
00040     // Should stub object be refcounted here?
00041     TAO_Stub *stub = this->get_stub ();
00042 
00043     TAO_Operation_Details op_details (this->operation_,
00044                                       this->op_len_,
00045                                       this->args_,
00046                                       this->number_args_,
00047                                       ex_data,
00048                                       ex_count);
00049 
00050     this->invoke_i (stub, op_details);
00051   }
00052 
00053   void
00054   Invocation_Adapter::invoke_i (TAO_Stub *stub, TAO_Operation_Details &details)
00055   {
00056     // The invocation has got to be within the context of the
00057     // corresponding ORB's configuration. Otherwise things like
00058     // timeout hooks, etc may not work as expected. Especially if
00059     // there are multiple ORB instances in the process, each with its
00060     // own, local configuration.
00061     ACE_Service_Config_Guard scg (stub->orb_core ()->configuration ());
00062 
00063     // Cache the target to a local variable.
00064     CORBA::Object_var effective_target =
00065       CORBA::Object::_duplicate (this->target_);
00066 
00067     // Initial state
00068     TAO::Invocation_Status status = TAO_INVOKE_START;
00069 
00070     while (status == TAO_INVOKE_START ||
00071            status == TAO_INVOKE_RESTART)
00072       {
00073         // Default we go to remote
00074         Collocation_Strategy strat = TAO_CS_REMOTE_STRATEGY;
00075 
00076         // If we have a collocated proxy broker we look if we maybe
00077         // can use a collocated invocation.  Similarly, if the
00078         // target object reference contains a pointer to a servant,
00079         // the object reference also refers to a collocated object.
00080         if (cpb_ != 0 || effective_target->_servant () != 0)
00081           {
00082             strat = TAO_ORB_Core::collocation_strategy (effective_target.in ());
00083           }
00084 
00085         if (strat == TAO_CS_REMOTE_STRATEGY || strat == TAO_CS_LAST)
00086           {
00087             ACE_Time_Value *max_wait_time = 0;
00088             status =
00089               this->invoke_remote_i (stub,
00090                                      details,
00091                                      effective_target,
00092                                      max_wait_time);
00093           }
00094         else
00095           {
00096             if (strat == TAO_CS_THRU_POA_STRATEGY)
00097               {
00098                 (void) this->set_response_flags (stub, details);
00099               }
00100 
00101             status =
00102               this->invoke_collocated_i (stub,
00103                                          details,
00104                                          effective_target,
00105                                          strat);
00106           }
00107 
00108         if (status == TAO_INVOKE_RESTART)
00109           {
00110             details.reset_request_service_info ();
00111             details.reset_reply_service_info ();
00112 
00113             if (TAO_debug_level > 2)
00114               {
00115                 ACE_DEBUG ((LM_DEBUG,
00116                   "TAO (%P|%t) - Invocation_Adapter::invoke_i, "
00117                   "handling forwarded locations \n"));
00118               }
00119           }
00120       }
00121   }
00122 
00123   bool
00124   Invocation_Adapter::get_timeout (TAO_Stub *stub, ACE_Time_Value &timeout)
00125   {
00126     bool has_timeout = false;
00127     this->target_->orb_core ()->call_timeout_hook (stub, has_timeout, timeout);
00128 
00129     return has_timeout;
00130   }
00131 
00132   TAO_Stub *
00133   Invocation_Adapter::get_stub (void) const
00134   {
00135     TAO_Stub * const stub = this->target_->_stubobj ();
00136 
00137     if (stub == 0)
00138       throw ::CORBA::INTERNAL (
00139         CORBA::SystemException::_tao_minor_code (
00140           TAO::VMCID,
00141           EINVAL),
00142         CORBA::COMPLETED_NO);
00143 
00144     return stub;
00145   }
00146 
00147   Invocation_Status
00148   Invocation_Adapter::invoke_collocated_i (TAO_Stub *stub,
00149                                            TAO_Operation_Details &details,
00150                                            CORBA::Object_var &effective_target,
00151                                            Collocation_Strategy strat)
00152   {
00153     // To make a collocated call we must have a collocated proxy broker, the
00154     // invoke_i() will make sure that we only come here when we have one
00155     ACE_ASSERT (cpb_ != 0
00156                 || (strat == TAO_CS_THRU_POA_STRATEGY
00157                     && effective_target->_servant () != 0));
00158 
00159     // Initial state
00160     TAO::Invocation_Status status = TAO_INVOKE_START;
00161 
00162     Collocated_Invocation coll_inv (this->target_,
00163                                     effective_target.in (),
00164                                     stub,
00165                                     details,
00166                                     this->type_ == TAO_TWOWAY_INVOCATION);
00167 
00168     status = coll_inv.invoke (this->cpb_, strat);
00169 
00170     if (status == TAO_INVOKE_RESTART && coll_inv.is_forwarded ())
00171       {
00172         effective_target = coll_inv.steal_forwarded_reference ();
00173 
00174 #if TAO_HAS_INTERCEPTORS == 1
00175         CORBA::Boolean const is_permanent_forward =
00176             (coll_inv.reply_status() == TAO_GIOP_LOCATION_FORWARD_PERM);
00177 #else
00178         CORBA::Boolean const is_permanent_forward = false;
00179 #endif
00180 
00181         this->object_forwarded (effective_target, stub, is_permanent_forward);
00182       }
00183 
00184     return status;
00185   }
00186 
00187   void
00188   Invocation_Adapter::set_response_flags (
00189     TAO_Stub *stub,
00190     TAO_Operation_Details &details)
00191   {
00192     switch (this->type_)
00193       {
00194       case TAO_ONEWAY_INVOCATION:
00195         {
00196           // Grab the syncscope policy from the ORB.
00197           Messaging::SyncScope sync_scope;
00198 
00199           bool has_synchronization = false;
00200 
00201           stub->orb_core ()->call_sync_scope_hook (stub,
00202                                                    has_synchronization,
00203                                                    sync_scope);
00204           if (has_synchronization)
00205             details.response_flags (CORBA::Octet (sync_scope));
00206           else
00207             details.response_flags (
00208               CORBA::Octet (Messaging::SYNC_WITH_TRANSPORT));
00209           break;
00210         }
00211       case TAO_TWOWAY_INVOCATION:
00212         {
00213           // @@note: Need to change this to something better. Too many
00214           // hash defines meaning the same things.
00215           details.response_flags (TAO_TWOWAY_RESPONSE_FLAG);
00216           break;
00217         }
00218       }
00219   }
00220 
00221   Invocation_Status
00222   Invocation_Adapter::invoke_remote_i (TAO_Stub *stub,
00223                                        TAO_Operation_Details &details,
00224                                        CORBA::Object_var &effective_target,
00225                                        ACE_Time_Value *&max_wait_time)
00226   {
00227     ACE_Time_Value tmp_wait_time;
00228     bool const is_timeout = this->get_timeout (stub, tmp_wait_time);
00229 
00230     if (is_timeout)
00231       max_wait_time = &tmp_wait_time;
00232 
00233     (void) this->set_response_flags (stub, details);
00234 
00235     CORBA::Octet rflags = details.response_flags ();
00236     bool block_connect =
00237       rflags != static_cast<CORBA::Octet> (Messaging::SYNC_NONE)
00238       && rflags != static_cast<CORBA::Octet> (TAO::SYNC_DELAYED_BUFFERING);
00239 
00240     // Create the resolver which will pick (or create) for us a
00241     // transport and a profile from the effective_target.
00242     Profile_Transport_Resolver resolver (
00243       effective_target.in (),
00244       stub,
00245       block_connect);
00246 
00247     resolver.resolve (max_wait_time);
00248 
00249     if (TAO_debug_level)
00250       {
00251         if (is_timeout && *max_wait_time == ACE_Time_Value::zero)
00252           ACE_DEBUG ((LM_DEBUG,
00253                       ACE_TEXT ("(%P|%t)Invocation_Adapter::invoke_remote_i: ")
00254                       ACE_TEXT ("max wait time consumed during transport resolution\n")));
00255       }
00256 
00257 
00258     // Update the request id now that we have a transport
00259     details.request_id (resolver.transport ()->tms ()->request_id ());
00260 
00261     if (this->type_ == TAO_ONEWAY_INVOCATION)
00262       {
00263         return this->invoke_oneway (details,
00264                                     effective_target,
00265                                     resolver,
00266                                     max_wait_time);
00267       }
00268     else if (this->type_ == TAO_TWOWAY_INVOCATION)
00269       {
00270         return this->invoke_twoway (details,
00271                                     effective_target,
00272                                     resolver,
00273                                     max_wait_time);
00274       }
00275 
00276     return TAO_INVOKE_FAILURE;
00277   }
00278 
00279   Invocation_Status
00280   Invocation_Adapter::invoke_twoway (TAO_Operation_Details &details,
00281                                      CORBA::Object_var &effective_target,
00282                                      Profile_Transport_Resolver &r,
00283                                      ACE_Time_Value *&max_wait_time)
00284   {
00285     // Simple sanity check
00286     if (this->mode_ != TAO_SYNCHRONOUS_INVOCATION ||
00287         this->type_ != TAO_TWOWAY_INVOCATION)
00288       {
00289         throw ::CORBA::INTERNAL (
00290           CORBA::SystemException::_tao_minor_code (
00291             TAO::VMCID,
00292             EINVAL),
00293           CORBA::COMPLETED_NO);
00294       }
00295 
00296     TAO::Synch_Twoway_Invocation synch (this->target_,  r, details);
00297 
00298     Invocation_Status const status = synch.remote_twoway (max_wait_time);
00299 
00300     if (status == TAO_INVOKE_RESTART &&
00301         synch.is_forwarded ())
00302       {
00303         effective_target = synch.steal_forwarded_reference ();
00304 
00305 #if TAO_HAS_INTERCEPTORS == 1
00306         CORBA::Boolean const is_permanent_forward =
00307             (synch.reply_status() == TAO_GIOP_LOCATION_FORWARD_PERM);
00308 #else
00309         CORBA::Boolean const is_permanent_forward = false;
00310 #endif
00311 
00312         this->object_forwarded (effective_target,
00313                                 r.stub (),
00314                                 is_permanent_forward);
00315       }
00316 
00317     return status;
00318   }
00319 
00320   Invocation_Status
00321   Invocation_Adapter::invoke_oneway (TAO_Operation_Details &details,
00322                                      CORBA::Object_var &effective_target,
00323                                      Profile_Transport_Resolver &r,
00324                                      ACE_Time_Value *&max_wait_time)
00325   {
00326     TAO::Synch_Oneway_Invocation synch (this->target_, r, details);
00327 
00328     Invocation_Status const s = synch.remote_oneway (max_wait_time);
00329 
00330     if (s == TAO_INVOKE_RESTART && synch.is_forwarded ())
00331       {
00332         effective_target = synch.steal_forwarded_reference ();
00333 
00334 #if TAO_HAS_INTERCEPTORS == 1
00335         CORBA::Boolean const is_permanent_forward =
00336             (synch.reply_status() == TAO_GIOP_LOCATION_FORWARD_PERM);
00337 #else
00338         CORBA::Boolean const is_permanent_forward = false;
00339 #endif
00340         this->object_forwarded (effective_target,
00341                                 r.stub (),
00342                                 is_permanent_forward);
00343       }
00344 
00345     return s;
00346   }
00347 
00348   void
00349   Invocation_Adapter::object_forwarded (CORBA::Object_var &effective_target,
00350                                         TAO_Stub *stub,
00351                                         CORBA::Boolean permanent_forward)
00352   {
00353     // The object pointer has to be changed to a TAO_Stub pointer
00354     // in order to obtain the profiles.
00355     TAO_Stub *stubobj = effective_target->_stubobj ();
00356 
00357     if (stubobj == 0)
00358       throw ::CORBA::INTERNAL (
00359         CORBA::SystemException::_tao_minor_code (
00360           TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00361           errno),
00362         CORBA::COMPLETED_NO);
00363 
00364     // Reset the profile in the stubs
00365     stub->add_forward_profiles (stubobj->base_profiles (), permanent_forward);
00366 
00367     if (stub->next_profile () == 0)
00368       throw ::CORBA::TRANSIENT (
00369         CORBA::SystemException::_tao_minor_code (
00370           TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00371           errno),
00372         CORBA::COMPLETED_NO);
00373 
00374     return;
00375   }
00376 } // End namespace TAO
00377 
00378 TAO_END_VERSIONED_NAMESPACE_DECL

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