SCIOP_Connector.cpp

Go to the documentation of this file.
00001 #include "tao/Strategies/SCIOP_Connector.h"
00002 #include "tao/Strategies/SCIOP_Profile.h"
00003 
00004 #if TAO_HAS_SCIOP == 1
00005 
00006 #include "tao/debug.h"
00007 #include "tao/ORB_Core.h"
00008 #include "tao/Client_Strategy_Factory.h"
00009 #include "tao/Environment.h"
00010 #include "tao/Base_Transport_Property.h"
00011 #include "tao/Protocols_Hooks.h"
00012 #include "tao/Transport_Cache_Manager.h"
00013 #include "tao/Connect_Strategy.h"
00014 #include "tao/Thread_Lane_Resources.h"
00015 #include "tao/Transport.h"
00016 #include "tao/Wait_Strategy.h"
00017 #include "tao/Profile_Transport_Resolver.h"
00018 
00019 #include "ace/OS_NS_strings.h"
00020 #include "ace/Strategies_T.h"
00021 
00022 
00023 ACE_RCSID (TAO,
00024            SCIOP_Connector,
00025            "SCIOP_Connector.cpp,v 1.22 2006/03/10 07:19:18 jtc Exp")
00026 
00027 
00028 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00029 
00030 TAO_SCIOP_Connector::TAO_SCIOP_Connector (CORBA::Boolean flag)
00031   : TAO_Connector (TAO_TAG_SCIOP_PROFILE),
00032     lite_flag_ (flag),
00033     connect_strategy_ (),
00034     base_connector_ ()
00035 {
00036 }
00037 
00038 TAO_SCIOP_Connector::~TAO_SCIOP_Connector (void)
00039 {
00040 }
00041 
00042 int
00043 TAO_SCIOP_Connector::open (TAO_ORB_Core *orb_core)
00044 {
00045   // @@todo: The functionality of the following two statements could
00046   // be  done in the constructor, but that involves changing the
00047   // interface of the pluggable transport factory.
00048 
00049   // Set the ORB Core
00050   this->orb_core (orb_core);
00051 
00052   // Create our connect strategy
00053   if (this->create_connect_strategy () == -1)
00054     return -1;
00055 
00056   /// Our connect creation strategy
00057   TAO_SCIOP_CONNECT_CREATION_STRATEGY *connect_creation_strategy = 0;
00058 
00059   ACE_NEW_RETURN (connect_creation_strategy,
00060                   TAO_SCIOP_CONNECT_CREATION_STRATEGY
00061                       (orb_core->thr_mgr (),
00062                        orb_core,
00063                        this->lite_flag_),
00064                   -1);
00065 
00066   /// Our activation strategy
00067   TAO_SCIOP_CONNECT_CONCURRENCY_STRATEGY *concurrency_strategy = 0;
00068 
00069   ACE_NEW_RETURN (concurrency_strategy,
00070                   TAO_SCIOP_CONNECT_CONCURRENCY_STRATEGY (orb_core),
00071                   -1);
00072 
00073   return this->base_connector_.open (this->orb_core ()->reactor (),
00074                                      connect_creation_strategy,
00075                                      &this->connect_strategy_,
00076                                      concurrency_strategy);
00077 }
00078 
00079 int
00080 TAO_SCIOP_Connector::close (void)
00081 {
00082   delete this->base_connector_.concurrency_strategy ();
00083   delete this->base_connector_.creation_strategy ();
00084   return this->base_connector_.close ();
00085 }
00086 
00087 int
00088 TAO_SCIOP_Connector::set_validate_endpoint (TAO_Endpoint *endpoint)
00089 {
00090   TAO_SCIOP_Endpoint *sciop_endpoint =
00091     this->remote_endpoint (endpoint);
00092 
00093   if (sciop_endpoint == 0)
00094     return -1;
00095 
00096    const ACE_INET_Addr &remote_address =
00097      sciop_endpoint->object_addr ();
00098 
00099    // Verify that the remote ACE_INET_Addr was initialized properly.
00100    // Failure can occur if hostname lookup failed when initializing the
00101    // remote ACE_INET_Addr.
00102    if (remote_address.get_type () != AF_INET)
00103      {
00104        if (TAO_debug_level > 0)
00105          {
00106            ACE_DEBUG ((LM_DEBUG,
00107                        ACE_TEXT ("TAO (%P|%t) SCIOP connection failed.\n")
00108                        ACE_TEXT ("TAO (%P|%t) This is most likely ")
00109                        ACE_TEXT ("due to a hostname lookup ")
00110                        ACE_TEXT ("failure.\n")));
00111          }
00112 
00113        return -1;
00114      }
00115 
00116    return 0;
00117 }
00118 
00119 TAO_Transport *
00120 TAO_SCIOP_Connector::make_connection (TAO::Profile_Transport_Resolver *r,
00121                                       TAO_Transport_Descriptor_Interface &desc,
00122                                       ACE_Time_Value *timeout)
00123 {
00124   TAO_Endpoint *tao_endpoint = desc.endpoint ();
00125 
00126   TAO_Transport *transport = 0;
00127 
00128   // @@ ATL folks, is this while loop needed?
00129   // TAO_Default_Endpoint_Selector has this code already, i.e., the
00130   // loop.
00131   while (tao_endpoint != 0)
00132     {
00133       TAO_SCIOP_Endpoint *sciop_endpoint =
00134         this->remote_endpoint (tao_endpoint);
00135 
00136       if (sciop_endpoint != 0)
00137         {
00138           transport =
00139             this->make_connection_i (r, desc, timeout, sciop_endpoint);
00140           if (transport)
00141             {
00142               break;
00143             }
00144         }
00145       tao_endpoint = tao_endpoint->next();
00146     }
00147 
00148   return transport;
00149 }
00150 
00151 
00152 TAO_Transport *
00153 TAO_SCIOP_Connector::make_connection_i (TAO::Profile_Transport_Resolver *r,
00154                                         TAO_Transport_Descriptor_Interface &desc,
00155                                         ACE_Time_Value *timeout,
00156                                         TAO_SCIOP_Endpoint *sciop_endpoint)
00157 {
00158   const ACE_INET_Addr &remote_address =
00159     sciop_endpoint->object_addr ();
00160 
00161   if (TAO_debug_level > 2)
00162       ACE_DEBUG ((LM_DEBUG,
00163                   "TAO (%P|%t) - SCIOP_Connector::make_connection_i, "
00164                   "to <%s:%d> which should %s\n",
00165                   ACE_TEXT_CHAR_TO_TCHAR(sciop_endpoint->host()),
00166                   sciop_endpoint->port(),
00167                   r->blocked_connect () ? ACE_TEXT("block") : ACE_TEXT("nonblock")));
00168 
00169   // Get the right synch options
00170   ACE_Synch_Options synch_options;
00171 
00172   this->active_connect_strategy_->synch_options (timeout,
00173                                                  synch_options);
00174 
00175   // If we don't need to block for a transport just set the timeout to
00176   // be zero.
00177   ACE_Time_Value tmp_zero (ACE_Time_Value::zero);
00178   if (!r->blocked_connect())
00179     {
00180       synch_options.timeout (ACE_Time_Value::zero);
00181       timeout = &tmp_zero;
00182     }
00183 
00184   TAO_SCIOP_Connection_Handler *svc_handler = 0;
00185 
00186   // Connect.
00187   ACE_Multihomed_INET_Addr multihomed;
00188   if (multihomed.set(remote_address.get_port_number(),
00189                      remote_address.get_ip_address()))
00190     return 0;
00191 
00192   ACE_Multihomed_INET_Addr local_address;
00193 
00194   bool pn =
00195     sciop_endpoint->is_preferred_network ();
00196 
00197   if (pn)
00198     local_address.set ((u_short) 0,
00199                        sciop_endpoint->preferred_network ());
00200 
00201   int result =
00202     this->base_connector_.connect (svc_handler,
00203                                    multihomed,
00204                                    synch_options,
00205                                    local_address);
00206 
00207   // This call creates the service handler and bumps the #REFCOUNT# up
00208   // one extra.  There are three possibilities: (a) connection
00209   // succeeds immediately - in this case, the #REFCOUNT# on the
00210   // handler is two; (b) connection completion is pending - in this
00211   // case, the #REFCOUNT# on the handler is also two; (c) connection
00212   // fails immediately - in this case, the #REFCOUNT# on the handler
00213   // is one since close() gets called on the handler.
00214   //
00215   // The extra reference count in
00216   // TAO_Connect_Creation_Strategy::make_svc_handler() is needed in
00217   // the case when connection completion is pending and we are going
00218   // to wait on a variable in the handler to changes, signifying
00219   // success or failure.  Note, that this increment cannot be done
00220   // once the connect() returns since this might be too late if
00221   // another thread pick up the completion and potentially deletes the
00222   // handler before we get a chance to increment the reference count.
00223 
00224   // Make sure that we always do a remove_reference
00225   ACE_Event_Handler_var svc_handler_auto_ptr (svc_handler);
00226 
00227   TAO_Transport *transport =
00228     svc_handler->transport ();
00229 
00230   if (result == -1)
00231     {
00232       // No immediate result, wait for completion
00233       if (errno == EWOULDBLOCK)
00234         {
00235           // Try to wait until connection completion. Incase we block, then we
00236           // get a connected transport or not. In case of non block we get
00237           // a connected or not connected transport
00238           if (!this->wait_for_connection_completion (r,
00239                                                      transport,
00240                                                      timeout))
00241             {
00242               if (TAO_debug_level > 2)
00243                 ACE_ERROR ((LM_ERROR, "TAO (%P|%t) - SCIOP_Connector::"
00244                                       "make_connection_i, "
00245                                       "wait for completion failed\n"));
00246             }
00247          }
00248        else
00249          {
00250            // Transport is not usable
00251            transport = 0;
00252          }
00253     }
00254 
00255   // In case of errors transport is zero
00256   if (transport == 0)
00257     {
00258       // Give users a clue to the problem.
00259       if (TAO_debug_level)
00260         {
00261           ACE_DEBUG ((LM_ERROR,
00262                       "TAO (%P|%t) - SCIOP_Connector::make_connection_i, "
00263                       "connection to <%s:%d> failed (%p)\n",
00264                       sciop_endpoint->host (), sciop_endpoint->port (),
00265                       "errno"));
00266         }
00267 
00268       return 0;
00269     }
00270 
00271   // At this point, the connection has be successfully connected.
00272   // #REFCOUNT# is one.
00273   if (TAO_debug_level > 2)
00274     ACE_DEBUG ((LM_DEBUG,
00275                 "TAO (%P|%t) - SCIOP_Connector::make_connection_i, "
00276                 "new %s connection to <%s:%d> on Transport[%d]\n",
00277                 transport->is_connected() ? "connected" : "not connected",
00278                 sciop_endpoint->host (), sciop_endpoint->port (),
00279                 svc_handler->peer ().get_handle ()));
00280 
00281   // Add the handler to Cache
00282   int retval =
00283     this->orb_core ()->lane_resources ().transport_cache ().cache_transport (&desc,
00284                                                                              transport);
00285 
00286   // Failure in adding to cache.
00287   if (retval != 0)
00288     {
00289       // Close the handler.
00290       svc_handler->close ();
00291 
00292       if (TAO_debug_level > 0)
00293         {
00294           ACE_ERROR ((LM_ERROR,
00295                       "TAO (%P|%t) - SCIOP_Connector::make_connection_i, "
00296                       "could not add the new connection to cache\n"));
00297         }
00298 
00299       return 0;
00300     }
00301 
00302   if (transport->is_connected () &&
00303       transport->wait_strategy ()->register_handler () != 0)
00304     {
00305       // Registration failures.
00306 
00307       // Purge from the connection cache, if we are not in the cache, this
00308       // just does nothing.
00309       (void) transport->purge_entry ();
00310 
00311       // Close the handler.
00312       (void) transport->close_connection ();
00313 
00314       if (TAO_debug_level > 0)
00315         ACE_ERROR ((LM_ERROR,
00316                     "TAO (%P|%t) - SCIOP_Connector [%d]::make_connection_i, "
00317                     "could not register the transport "
00318                     "in the reactor.\n",
00319                     transport->id ()));
00320 
00321       return 0;
00322     }
00323 
00324   return transport;
00325 }
00326 
00327 TAO_Profile *
00328 TAO_SCIOP_Connector::create_profile (TAO_InputCDR& cdr)
00329 {
00330   TAO_Profile *pfile;
00331   ACE_NEW_RETURN (pfile,
00332                   TAO_SCIOP_Profile (this->orb_core ()),
00333                   0);
00334 
00335   int r = pfile->decode (cdr);
00336   if (r == -1)
00337     {
00338       pfile->_decr_refcnt ();
00339       pfile = 0;
00340     }
00341 
00342   return pfile;
00343 }
00344 
00345 TAO_Profile *
00346 TAO_SCIOP_Connector::make_profile (ACE_ENV_SINGLE_ARG_DECL)
00347 {
00348   // The endpoint should be of the form:
00349   //    N.n@host:port/object_key
00350   // or:
00351   //    host:port/object_key
00352 
00353   TAO_Profile *profile = 0;
00354   ACE_NEW_THROW_EX (profile,
00355                     TAO_SCIOP_Profile (this->orb_core ()),
00356                     CORBA::NO_MEMORY (
00357                       CORBA::SystemException::_tao_minor_code (
00358                         TAO::VMCID,
00359                         ENOMEM),
00360                       CORBA::COMPLETED_NO));
00361   ACE_CHECK_RETURN (0);
00362 
00363   return profile;
00364 }
00365 
00366 int
00367 TAO_SCIOP_Connector::check_prefix (const char *endpoint)
00368 {
00369   // Check for a valid string
00370   if (!endpoint || !*endpoint)
00371     return -1;  // Failure
00372 
00373   const char *protocol[] = { "sciop", "scioploc" };
00374 
00375   size_t slot = ACE_OS::strchr (endpoint, ':') - endpoint;
00376 
00377   size_t len0 = ACE_OS::strlen (protocol[0]);
00378   size_t len1 = ACE_OS::strlen (protocol[1]);
00379 
00380   // Check for the proper prefix in the IOR.  If the proper prefix
00381   // isn't in the IOR then it is not an IOR we can use.
00382   if (slot == len0
00383       && ACE_OS::strncasecmp (endpoint, protocol[0], len0) == 0)
00384     return 0;
00385   else if (slot == len1
00386            && ACE_OS::strncasecmp (endpoint, protocol[1], len1) == 0)
00387     return 0;
00388 
00389   return -1;
00390   // Failure: not an SCIOP IOR
00391   // DO NOT throw an exception here.
00392 }
00393 
00394 char
00395 TAO_SCIOP_Connector::object_key_delimiter (void) const
00396 {
00397   return TAO_SCIOP_Profile::object_key_delimiter_;
00398 }
00399 
00400 TAO_SCIOP_Endpoint *
00401 TAO_SCIOP_Connector::remote_endpoint (TAO_Endpoint *endpoint)
00402 {
00403   if (endpoint->tag () != TAO_TAG_SCIOP_PROFILE)
00404     return 0;
00405 
00406   TAO_SCIOP_Endpoint *sciop_endpoint =
00407     dynamic_cast<TAO_SCIOP_Endpoint *> (endpoint );
00408   if (sciop_endpoint == 0)
00409     return 0;
00410 
00411   return sciop_endpoint;
00412 }
00413 
00414 int
00415 TAO_SCIOP_Connector::cancel_svc_handler (
00416   TAO_Connection_Handler * svc_handler)
00417 {
00418   TAO_SCIOP_Connection_Handler* handler=
00419     dynamic_cast<TAO_SCIOP_Connection_Handler*>(svc_handler);
00420 
00421   if (handler)
00422     // Cancel from the connector
00423     return this->base_connector_.cancel (handler);
00424 
00425   return -1;
00426 }
00427 
00428 TAO_END_VERSIONED_NAMESPACE_DECL
00429 
00430 #endif /* TAO_HAS_SCIOP == 1 */

Generated on Thu Nov 9 13:39:29 2006 for TAO_Strategies by doxygen 1.3.6