Invocation_Adapter.cpp

Go to the documentation of this file.
00001 //$Id: Invocation_Adapter.cpp 81632 2008-05-07 09:19:05Z vzykov $
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 81632 2008-05-07 09:19:05Z vzykov $")
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 || status == TAO_INVOKE_RESTART)
00071       {
00072         // Default we go to remote
00073         Collocation_Strategy strat = TAO_CS_REMOTE_STRATEGY;
00074 
00075         // If we have a collocated proxy broker we look if we maybe
00076         // can use a collocated invocation.  Similarly, if the
00077         // target object reference contains a pointer to a servant,
00078         // the object reference also refers to a collocated object.
00079         if (cpb_ != 0 || effective_target->_servant () != 0)
00080           {
00081             strat = TAO_ORB_Core::collocation_strategy (effective_target.in ());
00082           }
00083 
00084         if (strat == TAO_CS_REMOTE_STRATEGY || strat == TAO_CS_LAST)
00085           {
00086             ACE_Time_Value *max_wait_time = 0;
00087             status =
00088               this->invoke_remote_i (stub,
00089                                      details,
00090                                      effective_target,
00091                                      max_wait_time);
00092           }
00093         else
00094           {
00095             if (strat == TAO_CS_THRU_POA_STRATEGY)
00096               {
00097                 (void) this->set_response_flags (stub, details);
00098               }
00099 
00100             status =
00101               this->invoke_collocated_i (stub,
00102                                          details,
00103                                          effective_target,
00104                                          strat);
00105           }
00106 
00107         if (status == TAO_INVOKE_RESTART)
00108           {
00109             details.reset_request_service_info ();
00110             details.reset_reply_service_info ();
00111 
00112             if (TAO_debug_level > 2)
00113               {
00114                 ACE_DEBUG ((LM_DEBUG,
00115                   "TAO (%P|%t) - Invocation_Adapter::invoke_i, "
00116                   "handling forwarded locations \n"));
00117               }
00118           }
00119       }
00120   }
00121 
00122   bool
00123   Invocation_Adapter::get_timeout (TAO_Stub *stub, ACE_Time_Value &timeout)
00124   {
00125     bool has_timeout = false;
00126     this->target_->orb_core ()->call_timeout_hook (stub, has_timeout, timeout);
00127 
00128     return has_timeout;
00129   }
00130 
00131   TAO_Stub *
00132   Invocation_Adapter::get_stub (void) const
00133   {
00134     TAO_Stub * const stub = this->target_->_stubobj ();
00135 
00136     if (stub == 0)
00137       throw ::CORBA::INTERNAL (
00138         CORBA::SystemException::_tao_minor_code (
00139           TAO::VMCID,
00140           EINVAL),
00141         CORBA::COMPLETED_NO);
00142 
00143     return stub;
00144   }
00145 
00146   Invocation_Status
00147   Invocation_Adapter::invoke_collocated_i (TAO_Stub *stub,
00148                                            TAO_Operation_Details &details,
00149                                            CORBA::Object_var &effective_target,
00150                                            Collocation_Strategy strat)
00151   {
00152     // To make a collocated call we must have a collocated proxy broker, the
00153     // invoke_i() will make sure that we only come here when we have one
00154     ACE_ASSERT (cpb_ != 0
00155                 || (strat == TAO_CS_THRU_POA_STRATEGY
00156                     && effective_target->_servant () != 0));
00157 
00158     // Initial state
00159     TAO::Invocation_Status status = TAO_INVOKE_START;
00160 
00161     Collocated_Invocation coll_inv (this->target_,
00162                                     effective_target.in (),
00163                                     stub,
00164                                     details,
00165                                     this->type_ == TAO_TWOWAY_INVOCATION);
00166 
00167     status = coll_inv.invoke (this->cpb_, strat);
00168 
00169     if (status == TAO_INVOKE_RESTART &&
00170         (coll_inv.reply_status () == GIOP::LOCATION_FORWARD ||
00171          coll_inv.reply_status () == GIOP::LOCATION_FORWARD_PERM))
00172       {
00173         CORBA::Boolean const is_permanent_forward =
00174           (coll_inv.reply_status () == GIOP::LOCATION_FORWARD_PERM);
00175 
00176         effective_target = coll_inv.steal_forwarded_reference ();
00177 
00178         this->object_forwarded (effective_target, stub, is_permanent_forward);
00179       }
00180 
00181     return status;
00182   }
00183 
00184   void
00185   Invocation_Adapter::set_response_flags (
00186     TAO_Stub *stub,
00187     TAO_Operation_Details &details)
00188   {
00189     switch (this->type_)
00190       {
00191       case TAO_ONEWAY_INVOCATION:
00192         {
00193           // Grab the syncscope policy from the ORB.
00194           Messaging::SyncScope sync_scope;
00195 
00196           bool has_synchronization = false;
00197 
00198           stub->orb_core ()->call_sync_scope_hook (stub,
00199                                                    has_synchronization,
00200                                                    sync_scope);
00201           if (has_synchronization)
00202             details.response_flags (CORBA::Octet (sync_scope));
00203           else
00204             details.response_flags (
00205               CORBA::Octet (Messaging::SYNC_WITH_TRANSPORT));
00206           break;
00207         }
00208       case TAO_TWOWAY_INVOCATION:
00209         {
00210           // @@note: Need to change this to something better. Too many
00211           // hash defines meaning the same things.
00212           details.response_flags (TAO_TWOWAY_RESPONSE_FLAG);
00213           break;
00214         }
00215       }
00216   }
00217 
00218   Invocation_Status
00219   Invocation_Adapter::invoke_remote_i (TAO_Stub *stub,
00220                                        TAO_Operation_Details &details,
00221                                        CORBA::Object_var &effective_target,
00222                                        ACE_Time_Value *&max_wait_time)
00223   {
00224     ACE_Time_Value tmp_wait_time;
00225     bool const is_timeout = this->get_timeout (stub, tmp_wait_time);
00226 
00227     if (is_timeout)
00228       max_wait_time = &tmp_wait_time;
00229 
00230     (void) this->set_response_flags (stub, details);
00231 
00232     CORBA::Octet const rflags = details.response_flags ();
00233     bool const block_connect =
00234       rflags != static_cast<CORBA::Octet> (Messaging::SYNC_NONE)
00235       && rflags != static_cast<CORBA::Octet> (TAO::SYNC_DELAYED_BUFFERING);
00236 
00237     // Create the resolver which will pick (or create) for us a
00238     // transport and a profile from the effective_target.
00239     Profile_Transport_Resolver resolver (
00240       effective_target.in (),
00241       stub,
00242       block_connect);
00243 
00244     resolver.resolve (max_wait_time);
00245 
00246     if (TAO_debug_level)
00247       {
00248         if (is_timeout && *max_wait_time == ACE_Time_Value::zero)
00249           ACE_DEBUG ((LM_DEBUG,
00250                       ACE_TEXT ("(%P|%t)Invocation_Adapter::invoke_remote_i: ")
00251                       ACE_TEXT ("max wait time consumed during transport resolution\n")));
00252       }
00253 
00254     // Update the request id now that we have a transport
00255     if (resolver.transport ())
00256       {
00257         details.request_id (resolver.transport ()->tms ()->request_id ());
00258       }
00259 
00260     switch (this->type_)
00261       {
00262         case TAO_ONEWAY_INVOCATION:
00263           {
00264             return this->invoke_oneway (details,
00265                                         effective_target,
00266                                         resolver,
00267                                         max_wait_time);
00268           }
00269         case TAO_TWOWAY_INVOCATION:
00270           {
00271             return this->invoke_twoway (details,
00272                                         effective_target,
00273                                         resolver,
00274                                         max_wait_time);
00275 
00276           }
00277       }
00278     return TAO_INVOKE_FAILURE;
00279   }
00280 
00281   Invocation_Status
00282   Invocation_Adapter::invoke_twoway (TAO_Operation_Details &details,
00283                                      CORBA::Object_var &effective_target,
00284                                      Profile_Transport_Resolver &r,
00285                                      ACE_Time_Value *&max_wait_time)
00286   {
00287     // Simple sanity check
00288     if (this->mode_ != TAO_SYNCHRONOUS_INVOCATION ||
00289         this->type_ != TAO_TWOWAY_INVOCATION)
00290       {
00291         throw ::CORBA::INTERNAL (
00292           CORBA::SystemException::_tao_minor_code (
00293             TAO::VMCID,
00294             EINVAL),
00295           CORBA::COMPLETED_NO);
00296       }
00297 
00298     TAO::Synch_Twoway_Invocation synch (this->target_,  r, details);
00299 
00300     Invocation_Status const status = synch.remote_twoway (max_wait_time);
00301 
00302     if (status == TAO_INVOKE_RESTART &&
00303         (synch.reply_status () == GIOP::LOCATION_FORWARD ||
00304          synch.reply_status () == GIOP::LOCATION_FORWARD_PERM))
00305       {
00306         CORBA::Boolean const is_permanent_forward =
00307           (synch.reply_status () == GIOP::LOCATION_FORWARD_PERM);
00308 
00309         effective_target = synch.steal_forwarded_reference ();
00310 
00311         this->object_forwarded (effective_target,
00312                                 r.stub (),
00313                                 is_permanent_forward);
00314       }
00315 
00316     return status;
00317   }
00318 
00319   Invocation_Status
00320   Invocation_Adapter::invoke_oneway (TAO_Operation_Details &details,
00321                                      CORBA::Object_var &effective_target,
00322                                      Profile_Transport_Resolver &r,
00323                                      ACE_Time_Value *&max_wait_time)
00324   {
00325     TAO::Synch_Oneway_Invocation synch (this->target_, r, details);
00326 
00327     Invocation_Status const s = synch.remote_oneway (max_wait_time);
00328 
00329     if (s == TAO_INVOKE_RESTART &&
00330         (synch.reply_status () == GIOP::LOCATION_FORWARD ||
00331          synch.reply_status () == GIOP::LOCATION_FORWARD_PERM))
00332       {
00333         CORBA::Boolean const is_permanent_forward =
00334           (synch.reply_status () == GIOP::LOCATION_FORWARD_PERM);
00335 
00336         effective_target = synch.steal_forwarded_reference ();
00337 
00338         this->object_forwarded (effective_target,
00339                                 r.stub (),
00340                                 is_permanent_forward);
00341       }
00342 
00343     return s;
00344   }
00345 
00346   void
00347   Invocation_Adapter::object_forwarded (CORBA::Object_var &effective_target,
00348                                         TAO_Stub *stub,
00349                                         CORBA::Boolean permanent_forward)
00350   {
00351     // The object pointer has to be changed to a TAO_Stub pointer
00352     // in order to obtain the profiles.
00353     TAO_Stub *stubobj = 0;
00354 
00355     bool nil_forward_ref = false;
00356     if (CORBA::is_nil (effective_target.in ()))
00357       nil_forward_ref = true;
00358     else
00359       {
00360         stubobj =
00361           effective_target->_stubobj ();
00362 
00363         if (stubobj && stubobj->base_profiles ().size () == 0)
00364           nil_forward_ref = true;
00365       }
00366 
00367     if (nil_forward_ref)
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     if (stubobj == 0)
00375       throw ::CORBA::INTERNAL (
00376         CORBA::SystemException::_tao_minor_code (
00377           TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00378           errno),
00379         CORBA::COMPLETED_NO);
00380 
00381     // Reset the profile in the stubs
00382     stub->add_forward_profiles (stubobj->base_profiles (), permanent_forward);
00383 
00384     if (stub->next_profile () == 0)
00385       throw ::CORBA::TRANSIENT (
00386         CORBA::SystemException::_tao_minor_code (
00387           TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00388           errno),
00389         CORBA::COMPLETED_NO);
00390   }
00391 } // End namespace TAO
00392 
00393 TAO_END_VERSIONED_NAMESPACE_DECL

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