00001 
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 
00022 
00023 
00024 ACE_RCSID (tao,
00025            Invocation_Adapter,
00026            "$Id: Invocation_Adapter.cpp 85951 2009-07-09 13:11:43Z sma $")
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     
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     
00057     
00058     
00059     
00060     
00061     ACE_Service_Config_Guard scg (stub->orb_core ()->configuration ());
00062 
00063     
00064     CORBA::Object_var effective_target =
00065       CORBA::Object::_duplicate (this->target_);
00066 
00067     
00068     TAO::Invocation_Status status = TAO_INVOKE_START;
00069     ACE_Time_Value *max_wait_time = 0;
00070     ACE_Time_Value tmp_wait_time = ACE_Time_Value::zero;
00071     if (this->get_timeout (stub, tmp_wait_time))
00072       {
00073         max_wait_time= &tmp_wait_time;
00074       }
00075 
00076     while (status == TAO_INVOKE_START || status == TAO_INVOKE_RESTART)
00077       {
00078         
00079         Collocation_Strategy strat = TAO_CS_REMOTE_STRATEGY;
00080 
00081         
00082         
00083         
00084         
00085         if (cpb_ != 0 || effective_target->_servant () != 0)
00086           {
00087             strat = TAO_ORB_Core::collocation_strategy (effective_target.in ());
00088           }
00089 
00090         if (strat == TAO_CS_REMOTE_STRATEGY || strat == TAO_CS_LAST)
00091           {
00092             status =
00093               this->invoke_remote_i (stub,
00094                                      details,
00095                                      effective_target,
00096                                      max_wait_time);
00097           }
00098         else
00099           {
00100             if (strat == TAO_CS_THRU_POA_STRATEGY)
00101               {
00102                 (void) this->set_response_flags (stub, details);
00103               }
00104 
00105             status =
00106               this->invoke_collocated_i (stub,
00107                                          details,
00108                                          effective_target,
00109                                          strat);
00110           }
00111 
00112         if (status == TAO_INVOKE_RESTART)
00113           {
00114             details.reset_request_service_info ();
00115             details.reset_reply_service_info ();
00116 
00117             if (TAO_debug_level > 2)
00118               {
00119                 ACE_DEBUG ((LM_DEBUG,
00120                   ACE_TEXT("TAO (%P|%t) - Invocation_Adapter::invoke_i, ")
00121                   ACE_TEXT("handling forwarded locations\n")));
00122               }
00123           }
00124       }
00125   }
00126 
00127   bool
00128   Invocation_Adapter::get_timeout (TAO_Stub *stub, ACE_Time_Value &timeout)
00129   {
00130     bool has_timeout = false;
00131     this->target_->orb_core ()->call_timeout_hook (stub, has_timeout, timeout);
00132 
00133     return has_timeout;
00134   }
00135 
00136   TAO_Stub *
00137   Invocation_Adapter::get_stub (void) const
00138   {
00139     TAO_Stub * const stub = this->target_->_stubobj ();
00140 
00141     if (stub == 0)
00142       throw ::CORBA::INTERNAL (
00143         CORBA::SystemException::_tao_minor_code (
00144           TAO::VMCID,
00145           EINVAL),
00146         CORBA::COMPLETED_NO);
00147 
00148     return stub;
00149   }
00150 
00151   Invocation_Status
00152   Invocation_Adapter::invoke_collocated_i (TAO_Stub *stub,
00153                                            TAO_Operation_Details &details,
00154                                            CORBA::Object_var &effective_target,
00155                                            Collocation_Strategy strat)
00156   {
00157     
00158     
00159     ACE_ASSERT (cpb_ != 0
00160                 || (strat == TAO_CS_THRU_POA_STRATEGY
00161                     && effective_target->_servant () != 0));
00162 
00163     
00164     TAO::Invocation_Status status = TAO_INVOKE_START;
00165 
00166     Collocated_Invocation coll_inv (this->target_,
00167                                     effective_target.in (),
00168                                     stub,
00169                                     details,
00170                                     this->type_ == TAO_TWOWAY_INVOCATION);
00171 
00172     status = coll_inv.invoke (this->cpb_, strat);
00173 
00174     if (status == TAO_INVOKE_RESTART &&
00175         (coll_inv.reply_status () == GIOP::LOCATION_FORWARD ||
00176          coll_inv.reply_status () == GIOP::LOCATION_FORWARD_PERM))
00177       {
00178         CORBA::Boolean const is_permanent_forward =
00179           (coll_inv.reply_status () == GIOP::LOCATION_FORWARD_PERM);
00180 
00181         effective_target = coll_inv.steal_forwarded_reference ();
00182 
00183         this->object_forwarded (effective_target, stub, is_permanent_forward);
00184       }
00185 
00186     return status;
00187   }
00188 
00189   void
00190   Invocation_Adapter::set_response_flags (
00191     TAO_Stub *stub,
00192     TAO_Operation_Details &details)
00193   {
00194     switch (this->type_)
00195       {
00196       case TAO_ONEWAY_INVOCATION:
00197         {
00198           
00199           Messaging::SyncScope sync_scope;
00200 
00201           bool has_synchronization = false;
00202 
00203           stub->orb_core ()->call_sync_scope_hook (stub,
00204                                                    has_synchronization,
00205                                                    sync_scope);
00206           if (has_synchronization)
00207             details.response_flags (CORBA::Octet (sync_scope));
00208           else
00209             details.response_flags (
00210               CORBA::Octet (Messaging::SYNC_WITH_TRANSPORT));
00211           break;
00212         }
00213       case TAO_TWOWAY_INVOCATION:
00214         {
00215           
00216           
00217           details.response_flags (TAO_TWOWAY_RESPONSE_FLAG);
00218           break;
00219         }
00220       }
00221   }
00222 
00223   Invocation_Status
00224   Invocation_Adapter::invoke_remote_i (TAO_Stub *stub,
00225                                        TAO_Operation_Details &details,
00226                                        CORBA::Object_var &effective_target,
00227                                        ACE_Time_Value *&max_wait_time)
00228   {
00229     (void) this->set_response_flags (stub, details);
00230 
00231     CORBA::Octet const rflags = details.response_flags ();
00232     bool const block_connect =
00233       rflags != static_cast<CORBA::Octet> (Messaging::SYNC_NONE)
00234       && rflags != static_cast<CORBA::Octet> (TAO::SYNC_DELAYED_BUFFERING);
00235 
00236     
00237     
00238     Profile_Transport_Resolver resolver (
00239       effective_target.in (),
00240       stub,
00241       block_connect);
00242 
00243     resolver.resolve (max_wait_time);
00244 
00245     if (TAO_debug_level)
00246       {
00247         if (max_wait_time && *max_wait_time == ACE_Time_Value::zero)
00248           ACE_DEBUG ((LM_DEBUG,
00249                       ACE_TEXT ("TAO (%P|%t) - Invocation_Adapter::invoke_remote_i, ")
00250                       ACE_TEXT ("max wait time consumed during transport resolution\n")));
00251       }
00252 
00253     
00254     if (resolver.transport ())
00255       {
00256         details.request_id (resolver.transport ()->tms ()->request_id ());
00257       }
00258 
00259     switch (this->type_)
00260       {
00261         case TAO_ONEWAY_INVOCATION:
00262           {
00263             return this->invoke_oneway (details,
00264                                         effective_target,
00265                                         resolver,
00266                                         max_wait_time);
00267           }
00268         case TAO_TWOWAY_INVOCATION:
00269           {
00270             return this->invoke_twoway (details,
00271                                         effective_target,
00272                                         resolver,
00273                                         max_wait_time);
00274 
00275           }
00276       }
00277     return TAO_INVOKE_FAILURE;
00278   }
00279 
00280   Invocation_Status
00281   Invocation_Adapter::invoke_twoway (TAO_Operation_Details &details,
00282                                      CORBA::Object_var &effective_target,
00283                                      Profile_Transport_Resolver &r,
00284                                      ACE_Time_Value *&max_wait_time)
00285   {
00286     
00287     if (this->mode_ != TAO_SYNCHRONOUS_INVOCATION ||
00288         this->type_ != TAO_TWOWAY_INVOCATION)
00289       {
00290         throw ::CORBA::INTERNAL (
00291           CORBA::SystemException::_tao_minor_code (
00292             TAO::VMCID,
00293             EINVAL),
00294           CORBA::COMPLETED_NO);
00295       }
00296 
00297     TAO::Synch_Twoway_Invocation synch (this->target_,  r, details);
00298 
00299     Invocation_Status const status = synch.remote_twoway (max_wait_time);
00300 
00301     if (status == TAO_INVOKE_RESTART &&
00302         (synch.reply_status () == GIOP::LOCATION_FORWARD ||
00303          synch.reply_status () == GIOP::LOCATION_FORWARD_PERM))
00304       {
00305         CORBA::Boolean const is_permanent_forward =
00306           (synch.reply_status () == GIOP::LOCATION_FORWARD_PERM);
00307 
00308         effective_target = synch.steal_forwarded_reference ();
00309 
00310         this->object_forwarded (effective_target,
00311                                 r.stub (),
00312                                 is_permanent_forward);
00313       }
00314 
00315     return status;
00316   }
00317 
00318   Invocation_Status
00319   Invocation_Adapter::invoke_oneway (TAO_Operation_Details &details,
00320                                      CORBA::Object_var &effective_target,
00321                                      Profile_Transport_Resolver &r,
00322                                      ACE_Time_Value *&max_wait_time)
00323   {
00324     TAO::Synch_Oneway_Invocation synch (this->target_, r, details);
00325 
00326     Invocation_Status const s = synch.remote_oneway (max_wait_time);
00327 
00328     if (s == TAO_INVOKE_RESTART &&
00329         (synch.reply_status () == GIOP::LOCATION_FORWARD ||
00330          synch.reply_status () == GIOP::LOCATION_FORWARD_PERM))
00331       {
00332         CORBA::Boolean const is_permanent_forward =
00333           (synch.reply_status () == GIOP::LOCATION_FORWARD_PERM);
00334 
00335         effective_target = synch.steal_forwarded_reference ();
00336 
00337         this->object_forwarded (effective_target,
00338                                 r.stub (),
00339                                 is_permanent_forward);
00340       }
00341 
00342     return s;
00343   }
00344 
00345   void
00346   Invocation_Adapter::object_forwarded (CORBA::Object_var &effective_target,
00347                                         TAO_Stub *stub,
00348                                         CORBA::Boolean permanent_forward)
00349   {
00350     
00351     
00352     TAO_Stub *stubobj = 0;
00353 
00354     bool nil_forward_ref = false;
00355     if (CORBA::is_nil (effective_target.in ()))
00356       nil_forward_ref = true;
00357     else
00358       {
00359         stubobj =
00360           effective_target->_stubobj ();
00361 
00362         if (stubobj && stubobj->base_profiles ().size () == 0)
00363           nil_forward_ref = true;
00364       }
00365 
00366     if (nil_forward_ref)
00367       throw ::CORBA::TRANSIENT (
00368         CORBA::SystemException::_tao_minor_code (
00369           TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00370           errno),
00371         CORBA::COMPLETED_NO);
00372 
00373     if (stubobj == 0)
00374       throw ::CORBA::INTERNAL (
00375         CORBA::SystemException::_tao_minor_code (
00376           TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00377           errno),
00378         CORBA::COMPLETED_NO);
00379 
00380     
00381     stub->add_forward_profiles (stubobj->base_profiles (), permanent_forward);
00382 
00383     if (stub->next_profile () == 0)
00384       throw ::CORBA::TRANSIENT (
00385         CORBA::SystemException::_tao_minor_code (
00386           TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
00387           errno),
00388         CORBA::COMPLETED_NO);
00389   }
00390 } 
00391 
00392 TAO_END_VERSIONED_NAMESPACE_DECL