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/SystemException.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           "$Id: UIOP_Connector.cpp 79388 2007-08-17 16:05:00Z wilsond $")
00023 
00024 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00025 
00026 TAO_UIOP_Connector::TAO_UIOP_Connector (void)
00027   : TAO_Connector (TAO_TAG_UIOP_PROFILE),
00028     connect_strategy_ (),
00029     base_connector_ ()
00030 {
00031 }
00032 
00033 TAO_UIOP_Connector::~TAO_UIOP_Connector (void)
00034 {
00035 }
00036 
00037 int
00038 TAO_UIOP_Connector::open (TAO_ORB_Core *orb_core)
00039 {
00040   this->orb_core (orb_core);
00041 
00042   // Create our connect strategy
00043   if (this->create_connect_strategy () == -1)
00044     return -1;
00045 
00046   // Our connect creation strategy
00047   TAO_UIOP_CONNECT_CREATION_STRATEGY *connect_creation_strategy = 0;
00048 
00049   ACE_NEW_RETURN (connect_creation_strategy,
00050                   TAO_UIOP_CONNECT_CREATION_STRATEGY
00051                       (orb_core->thr_mgr (),
00052                        orb_core),
00053                   -1);
00054 
00055   /// Our activation strategy
00056   TAO_UIOP_CONNECT_CONCURRENCY_STRATEGY *concurrency_strategy = 0;
00057 
00058   ACE_NEW_RETURN (concurrency_strategy,
00059                   TAO_UIOP_CONNECT_CONCURRENCY_STRATEGY (orb_core),
00060                   -1);
00061 
00062   return this->base_connector_.open (this->orb_core ()->reactor (),
00063                                      connect_creation_strategy,
00064                                      &this->connect_strategy_,
00065                                      concurrency_strategy);
00066 }
00067 
00068 int
00069 TAO_UIOP_Connector::close (void)
00070 {
00071   // Zap the creation strategy that we created earlier.
00072   delete this->base_connector_.creation_strategy ();
00073   delete this->base_connector_.concurrency_strategy ();
00074 
00075   return this->base_connector_.close ();
00076 }
00077 
00078 TAO_Profile *
00079 TAO_UIOP_Connector::corbaloc_scan (const char *str, size_t &len
00080                                    )
00081 {
00082   if (this->check_prefix (str) != 0)
00083     return 0;
00084 
00085   const char *separator = ACE_OS::strchr (str,'|');
00086   if (separator == 0)
00087     {
00088       if (TAO_debug_level)
00089         ACE_DEBUG ((LM_DEBUG,
00090                     "(%P|%t) TAO_UIOP_CONNECTOR::corbaloc_scan error: "
00091                     "explicit terminating charactor '|' is missing from <%s>",
00092                     str));
00093       return 0;
00094     }
00095   len = (separator - str) + 1;
00096   return this->make_profile ();
00097 }
00098 
00099 
00100 int
00101 TAO_UIOP_Connector::set_validate_endpoint (TAO_Endpoint *endpoint)
00102 {
00103   TAO_UIOP_Endpoint *uiop_endpoint = this->remote_endpoint (endpoint);
00104 
00105   if (uiop_endpoint == 0)
00106     return -1;
00107 
00108    const ACE_UNIX_Addr &remote_address = uiop_endpoint->object_addr ();
00109 
00110    // @@ Note, POSIX.1g renames AF_UNIX to AF_LOCAL.
00111    // Verify that the remote ACE_UNIX_Addr was initialized properly.
00112    // Failure can occur if hostname lookup failed when initializing the
00113    // remote ACE_INET_Addr.
00114    if (remote_address.get_type () != AF_UNIX)
00115      {
00116        if (TAO_debug_level > 0)
00117          {
00118            ACE_DEBUG ((LM_DEBUG,
00119                        ACE_TEXT ("TAO (%P|%t) UIOP failure.\n")
00120                        ACE_TEXT ("TAO (%P|%t) This is most likely ")
00121                        ACE_TEXT ("due to a hostname lookup ")
00122                        ACE_TEXT ("failure.\n")));
00123          }
00124 
00125        return -1;
00126      }
00127 
00128    return 0;
00129 }
00130 
00131 TAO_Transport *
00132 TAO_UIOP_Connector::make_connection (TAO::Profile_Transport_Resolver *r,
00133                                      TAO_Transport_Descriptor_Interface &desc,
00134                                      ACE_Time_Value *max_wait_time)
00135 {
00136   if (TAO_debug_level > 0)
00137     ACE_DEBUG ((LM_DEBUG,
00138                 ACE_TEXT ("TAO (%P|%t) UIUP_Connector::make_connection, ")
00139                 ACE_TEXT ("looking for UIOP connection.\n")));
00140 
00141   TAO_UIOP_Endpoint *uiop_endpoint =
00142     this->remote_endpoint (desc.endpoint ());
00143 
00144   if (uiop_endpoint == 0)
00145     return 0;
00146 
00147   const ACE_UNIX_Addr &remote_address =
00148     uiop_endpoint->object_addr ();
00149 
00150   if (TAO_debug_level > 2)
00151     ACE_DEBUG ((LM_DEBUG,
00152                 ACE_TEXT ("TAO (%P|%t) UIUP_Connector::make_connection, ")
00153                 ACE_TEXT ("making a new connection \n")));
00154 
00155   // Get the right synch options
00156   ACE_Synch_Options synch_options;
00157 
00158   this->active_connect_strategy_->synch_options (max_wait_time,
00159                                                  synch_options);
00160 
00161   // The code used to set the timeout to zero, with the intent of
00162   // polling the reactor for connection completion. However, the side-effect
00163   // was to cause the connection to timeout immediately.
00164 
00165   TAO_UIOP_Connection_Handler *svc_handler = 0;
00166 
00167   // Connect.
00168   int result =
00169     this->base_connector_.connect (svc_handler,
00170                                    remote_address,
00171                                    synch_options);
00172 
00173   // This call creates the service handler and bumps the #REFCOUNT# up
00174   // one extra.  There are three possibilities: (a) connection
00175   // succeeds immediately - in this case, the #REFCOUNT# on the
00176   // handler is two; (b) connection completion is pending - in this
00177   // case, the #REFCOUNT# on the handler is also two; (c) connection
00178   // fails immediately - in this case, the #REFCOUNT# on the handler
00179   // is one since close() gets called on the handler.
00180   //
00181   // The extra reference count in
00182   // TAO_Connect_Creation_Strategy::make_svc_handler() is needed in
00183   // the case when connection completion is pending and we are going
00184   // to wait on a variable in the handler to changes, signifying
00185   // success or failure.  Note, that this increment cannot be done
00186   // once the connect() returns since this might be too late if
00187   // another thread pick up the completion and potentially deletes the
00188   // handler before we get a chance to increment the reference count.
00189 
00190   // Make sure that we always do a remove_reference
00191   ACE_Event_Handler_var svc_handler_auto_ptr (svc_handler);
00192 
00193   TAO_Transport *transport =
00194     svc_handler->transport ();
00195 
00196   if (result == -1)
00197     {
00198       // No immediate result, wait for completion
00199       if (errno == EWOULDBLOCK)
00200         {
00201           // Try to wait until connection completion. Incase we block, then we
00202           // get a connected transport or not. In case of non block we get
00203           // a connected or not connected transport
00204           if (!this->wait_for_connection_completion (r,
00205                                                      transport,
00206                                                      max_wait_time))
00207             {
00208               if (TAO_debug_level > 2)
00209                 ACE_ERROR ((LM_ERROR, "TAO (%P|%t) - UIOP_Connector::"
00210                                       "make_connection, "
00211                                       "wait for completion failed\n"));
00212             }
00213         }
00214       else
00215         {
00216           // Transport is not usable
00217           transport = 0;
00218         }
00219     }
00220 
00221   // In case of errors transport is zero
00222   if (transport == 0)
00223     {
00224       // Give users a clue to the problem.
00225       if (TAO_debug_level > 3)
00226           ACE_ERROR ((LM_ERROR,
00227                       "TAO (%P|%t) - UIOP_Connector::make_connection, "
00228                       "connection to <%s> failed (%p)\n",
00229                       uiop_endpoint->rendezvous_point (),
00230                       ACE_TEXT("errno")));
00231 
00232       return 0;
00233     }
00234 
00235   if (svc_handler->keep_waiting ())
00236     {
00237       svc_handler->connection_pending ();
00238     }
00239 
00240   if (svc_handler->error_detected ())
00241     {
00242       svc_handler->cancel_pending_connection ();
00243     }
00244 
00245   // At this point, the connection has be successfully created
00246   // connected or not connected, but we have a connection.
00247   if (TAO_debug_level > 2)
00248     ACE_DEBUG ((LM_DEBUG,
00249                 "TAO (%P|%t) - UIOP_Connector::make_connection, "
00250                 "new %s connection to <%s> on Transport[%d]\n",
00251                 transport->is_connected() ? "connected" : "not connected",
00252                 uiop_endpoint->rendezvous_point (),
00253                 svc_handler->peer ().get_handle ()));
00254 
00255   // Add the handler to Cache
00256   int retval =
00257     this->orb_core ()->lane_resources ().transport_cache ().cache_transport (&desc,
00258                                                                              transport);
00259   // Failure in adding to cache.
00260   if (retval != 0)
00261     {
00262       // Close the handler.
00263       svc_handler->close ();
00264 
00265       if (TAO_debug_level > 0)
00266         {
00267           ACE_ERROR ((LM_ERROR,
00268                       ACE_TEXT ("TAO (%P|%t) UIOP_Connector::make_connection, ")
00269                       ACE_TEXT ("could not add the new connection to Cache \n")));
00270         }
00271 
00272       return 0;
00273     }
00274 
00275   if (svc_handler->error_detected ())
00276     {
00277       svc_handler->cancel_pending_connection ();
00278       transport->purge_entry();
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 (void)
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 
00339   return profile;
00340 }
00341 
00342 int
00343 TAO_UIOP_Connector::check_prefix (const char *endpoint)
00344 {
00345   // Check for a valid string
00346   if (!endpoint || !*endpoint)
00347     return -1;  // Failure
00348 
00349   static const char *protocol[] = { "uiop", "uioploc" };
00350 
00351   const size_t slot = ACE_OS::strchr (endpoint, ':') - endpoint;
00352 
00353   const size_t len0 = ACE_OS::strlen (protocol[0]);
00354   const size_t len1 = ACE_OS::strlen (protocol[1]);
00355 
00356   // Check for the proper prefix in the IOR.  If the proper prefix
00357   // isn't in the IOR then it is not an IOR we can use.
00358   if (slot == len0
00359       && ACE_OS::strncasecmp (endpoint,
00360                               protocol[0],
00361                               len0) == 0)
00362     return 0;
00363   else if (slot == len1
00364            && ACE_OS::strncasecmp (endpoint,
00365                                    protocol[1],
00366                                    len1) == 0)
00367     return 0;
00368 
00369   return -1;
00370   // Failure: not an UIOP IOR DO NOT throw an exception here.
00371 }
00372 
00373 char
00374 TAO_UIOP_Connector::object_key_delimiter (void) const
00375 {
00376   return TAO_UIOP_Profile::object_key_delimiter_;
00377 }
00378 
00379 TAO_UIOP_Endpoint *
00380 TAO_UIOP_Connector::remote_endpoint (TAO_Endpoint *endpoint)
00381 {
00382   if (endpoint->tag () != TAO_TAG_UIOP_PROFILE)
00383     return 0;
00384 
00385   TAO_UIOP_Endpoint *uiop_endpoint =
00386     dynamic_cast<TAO_UIOP_Endpoint *> (endpoint);
00387 
00388   if (uiop_endpoint == 0)
00389     return 0;
00390 
00391   return uiop_endpoint;
00392 }
00393 
00394 int
00395 TAO_UIOP_Connector::cancel_svc_handler (
00396   TAO_Connection_Handler * svc_handler)
00397 {
00398   TAO_UIOP_Connection_Handler* handler=
00399     dynamic_cast<TAO_UIOP_Connection_Handler*> (svc_handler);
00400 
00401   if (handler)
00402     // Cancel from the connector
00403     return this->base_connector_.cancel (handler);
00404 
00405   return -1;
00406 }
00407 
00408 TAO_END_VERSIONED_NAMESPACE_DECL
00409 
00410 #endif /* TAO_HAS_UIOP == 1 */

Generated on Tue Feb 2 17:47:18 2010 for TAO_Strategies by  doxygen 1.4.7