UIOP_Connector.cpp

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

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