Transport_Connector.cpp

Go to the documentation of this file.
00001 #include "tao/Transport_Connector.h"
00002 #include "tao/Transport.h"
00003 #include "tao/ORB_Core.h"
00004 #include "tao/MProfile.h"
00005 #include "tao/Profile.h"
00006 #include "tao/Environment.h"
00007 #include "tao/Thread_Lane_Resources.h"
00008 #include "tao/debug.h"
00009 #include "tao/Connect_Strategy.h"
00010 #include "tao/LF_Multi_Event.h"
00011 #include "tao/Client_Strategy_Factory.h"
00012 #include "tao/Connection_Handler.h"
00013 #include "tao/Profile_Transport_Resolver.h"
00014 #include "tao/Wait_Strategy.h"
00015 #include "tao/SystemException.h"
00016 #include "tao/Endpoint.h"
00017 #include "tao/Base_Transport_Property.h"
00018 
00019 #include "ace/OS_NS_string.h"
00020 
00021 //@@ TAO_CONNECTOR_SPL_INCLUDE_ADD_HOOK
00022 
00023 #if !defined (__ACE_INLINE__)
00024 # include "tao/Transport_Connector.inl"
00025 #endif /* __ACE_INLINE__ */
00026 
00027 ACE_RCSID (tao,
00028            Connector,
00029            "Transport_Connector.cpp,v 1.34 2006/05/16 06:10:47 mesnier_p Exp")
00030 
00031 
00032 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00033 
00034 // Connector
00035 TAO_Connector::TAO_Connector (CORBA::ULong tag)
00036   : active_connect_strategy_ (0),
00037     tag_ (tag),
00038     orb_core_ (0)
00039 {
00040 }
00041 
00042 TAO_Connector::~TAO_Connector (void)
00043 {
00044   delete this->active_connect_strategy_;
00045 }
00046 
00047 TAO_Profile *
00048 TAO_Connector::corbaloc_scan (const char *str,
00049                               size_t &len
00050                               ACE_ENV_ARG_DECL)
00051 {
00052   if (this->check_prefix (str) != 0)
00053     return 0;
00054   const char *comma_pos = ACE_OS::strchr (str,',');
00055   const char *slash_pos = ACE_OS::strchr (str,'/');
00056   if (comma_pos == 0 && slash_pos == 0)
00057     {
00058       if (TAO_debug_level)
00059         ACE_DEBUG ((LM_DEBUG,
00060                     ACE_TEXT("(%P|%t) TAO_CONNECTOR::corbaloc_scan warning: ")
00061                     ACE_TEXT("supplied string contains no comma or slash: %s\n"),
00062                     str));
00063       len = ACE_OS::strlen (str);
00064     }
00065   else if (comma_pos == 0 || comma_pos > slash_pos)
00066     len = (slash_pos - str);
00067   else len = comma_pos - str;
00068   return this->make_profile(ACE_ENV_SINGLE_ARG_PARAMETER);
00069 }
00070 
00071 int
00072 TAO_Connector::make_mprofile (const char *string,
00073                               TAO_MProfile &mprofile
00074                               ACE_ENV_ARG_DECL)
00075 {
00076   // This method utilizes the "Template Method" design pattern to
00077   // parse the given URL style IOR for the protocol being used
00078   // and create an mprofile from it.
00079   //
00080   // The methods that must be defined by all Connector sub-classes are:
00081   //      make_profile
00082   //      check_prefix
00083 
00084   // Check for a valid string
00085   if (!string || !*string)
00086     {
00087       ACE_THROW_RETURN (CORBA::INV_OBJREF (
00088                           CORBA::SystemException::_tao_minor_code (
00089                             0,
00090                             EINVAL),
00091                           CORBA::COMPLETED_NO),
00092                         -1);
00093     }
00094 
00095   // Check for the proper prefix in the IOR.  If the proper prefix isn't
00096   // in the IOR then it is not an IOR we can use.
00097   if (this->check_prefix (string) != 0)
00098     {
00099       return 1;
00100       // Failure: not the correct IOR for this protocol.
00101       // DO NOT throw an exception here since the Connector_Registry
00102       // should be allowed the opportunity to continue looking for
00103       // an appropriate connector.
00104     }
00105 
00106   if (TAO_debug_level > 0)
00107     {
00108       ACE_DEBUG ((LM_DEBUG,
00109                   ACE_TEXT ("TAO (%P|%t) - TAO_Connector::make_mprofile ")
00110                   ACE_TEXT ("<%s>\n"),
00111                   ACE_TEXT_CHAR_TO_TCHAR (string)));
00112     }
00113 
00114   ACE_CString ior;
00115 
00116   ior.set (string, ACE_OS::strlen (string), 1);
00117 
00118   // Find out where the protocol ends
00119   ssize_t ior_index = ior.find ("://");
00120 
00121   if (ior_index == ACE_CString::npos)
00122     {
00123       ACE_THROW_RETURN (CORBA::INV_OBJREF (), -1);
00124       // No colon ':' in the IOR!
00125     }
00126   else
00127     {
00128       ior_index += 3;
00129       // Add the length of the colon and the two forward slashes `://'
00130       // to the IOR string index (i.e. 3)
00131     }
00132 
00133   // Find the object key
00134   const ssize_t objkey_index =
00135     ior.find (this->object_key_delimiter (), ior_index);
00136 
00137   if (objkey_index == 0 || objkey_index == ACE_CString::npos)
00138     {
00139       ACE_THROW_RETURN (CORBA::INV_OBJREF (), -1);
00140       // Failure: No endpoints specified or no object key specified.
00141     }
00142 
00143   const char endpoint_delimiter = ',';
00144   // The delimiter used to seperate inidividual addresses.
00145 
00146   // Count the number of endpoints in the IOR.  This will be the number
00147   // of entries in the MProfile.
00148 
00149   CORBA::ULong profile_count = 1;
00150   // Number of endpoints in the IOR  (initialized to 1).
00151 
00152   // Only check for endpoints after the protocol specification and
00153   // before the object key.
00154   for (ssize_t i = ior_index; i < objkey_index; ++i)
00155     {
00156       if (ior[i] == endpoint_delimiter)
00157         ++profile_count;
00158     }
00159 
00160   // Tell the MProfile object how many Profiles it should hold.
00161   // MProfile::set(size) returns the number profiles it can hold.
00162   if (mprofile.set (profile_count) != static_cast<int> (profile_count))
00163     {
00164       ACE_THROW_RETURN (CORBA::INV_OBJREF (
00165                           CORBA::SystemException::_tao_minor_code (
00166                             TAO_MPROFILE_CREATION_ERROR,
00167                             0),
00168                           CORBA::COMPLETED_NO),
00169                         -1);
00170       // Error while setting the MProfile size!
00171     }
00172 
00173   // The idea behind the following loop is to split the IOR into several
00174   // strings that can be parsed by each profile.
00175   // For example,
00176   //    `1.3@moo,shu,1.1@chicken/arf'
00177   // will be parsed into:
00178   //    `1.3@moo/arf'
00179   //    `shu/arf'
00180   //    `1.1@chicken/arf'
00181 
00182   ssize_t begin = 0;
00183   ssize_t end = ior_index - 1;
00184   // Initialize the end of the endpoint index
00185 
00186   for (CORBA::ULong j = 0; j < profile_count; ++j)
00187     {
00188       begin = end + 1;
00189 
00190       if (j < profile_count - 1)
00191         {
00192           end = ior.find (endpoint_delimiter, begin);
00193         }
00194       else
00195         {
00196           end = objkey_index;  // Handle last endpoint differently
00197         }
00198 
00199       if (end < static_cast<ssize_t> (ior.length ()) && end != ior.npos)
00200         {
00201           ACE_CString endpoint = ior.substring (begin, end - begin);
00202 
00203           // Add the object key to the string.
00204           endpoint += ior.substring (objkey_index);
00205 
00206           // The endpoint should now be of the form:
00207           //    `N.n@endpoint/object_key'
00208           // or
00209           //    `endpoint/object_key'
00210 
00211           TAO_Profile *profile =
00212             this->make_profile (ACE_ENV_SINGLE_ARG_PARAMETER);
00213           ACE_CHECK_RETURN (-1);
00214           // Failure:  Problem during profile creation
00215 
00216           // Initialize a Profile using the individual endpoint
00217           // string.
00218           // @@ Not exception safe!  We need a TAO_Profile_var!
00219           profile->parse_string (endpoint.c_str ()
00220                                  ACE_ENV_ARG_PARAMETER);
00221           ACE_CHECK_RETURN (-1);
00222 
00223           // Give up ownership of the profile.
00224           if (mprofile.give_profile (profile) == -1)
00225             {
00226               profile->_decr_refcnt ();
00227 
00228               ACE_THROW_RETURN (CORBA::INV_OBJREF (
00229                                   CORBA::SystemException::_tao_minor_code (
00230                                      TAO_MPROFILE_CREATION_ERROR,
00231                                      0),
00232                                   CORBA::COMPLETED_NO),
00233                                 -1);
00234               // Failure presumably only occurs when MProfile is full!
00235               // This should never happen.
00236             }
00237         }
00238       else
00239         {
00240           ACE_THROW_RETURN (CORBA::INV_OBJREF (), -1);
00241           // Unable to seperate endpoints
00242         }
00243     }
00244 
00245   return 0;  // Success
00246 }
00247 
00248 int
00249 TAO_Connector::supports_parallel_connects(void) const
00250 {
00251   return 0; // by default, we don't support parallel connection attempts;
00252 }
00253 
00254 TAO_Transport*
00255 TAO_Connector::make_parallel_connection (TAO::Profile_Transport_Resolver *,
00256                                          TAO_Transport_Descriptor_Interface &,
00257                                          ACE_Time_Value *)
00258 {
00259   return 0;
00260 }
00261 
00262 
00263 TAO_Transport*
00264 TAO_Connector::parallel_connect (TAO::Profile_Transport_Resolver *r,
00265                                  TAO_Transport_Descriptor_Interface *desc,
00266                                  ACE_Time_Value *timeout
00267                                  ACE_ENV_ARG_DECL_NOT_USED)
00268 {
00269   if (this->supports_parallel_connects() == 0)
00270     {
00271       errno = ENOTSUP;
00272       return 0;
00273     }
00274 
00275   errno = 0; // need to clear errno to ensure a stale enotsup is not set
00276   if (desc == 0)
00277     return 0;
00278   unsigned int endpoint_count = 0;
00279   TAO_Endpoint *root_ep = desc->endpoint();
00280   for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00281        ep != 0;
00282        ep = ep->next_filtered(this->orb_core(),root_ep))
00283     if (this->set_validate_endpoint (ep) == 0)
00284       ++endpoint_count;
00285   if (endpoint_count == 0)
00286     return 0;
00287 
00288   TAO_Transport *base_transport = 0;
00289 
00290   TAO::Transport_Cache_Manager &tcm =
00291     this->orb_core ()->lane_resources ().transport_cache ();
00292 
00293   // Iterate through the endpoints. Since find_transport takes a
00294   // Transport Descriptor rather than an endpoint, we must create a
00295   // local TDI for each endpoint. The first one found will be used.
00296   for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),0);
00297        ep != 0;
00298        ep = ep->next_filtered(this->orb_core(),root_ep))
00299     {
00300       TAO_Base_Transport_Property desc2(ep,0);
00301       if (tcm.find_transport (&desc2,
00302                               base_transport) == 0)
00303         {
00304           if (TAO_debug_level)
00305             ACE_DEBUG ((LM_DEBUG,
00306                         ACE_TEXT ("(%P|%t) TAO_Connector::parallel_connect: ")
00307                         ACE_TEXT ("found a transport [%d]\n"),
00308                         base_transport->id()));
00309           return base_transport;
00310         }
00311     }
00312 
00313   // Now we have searched the cache on all endpoints and come up
00314   // empty. We need to initiate connections on each of the
00315   // endpoints. Presumably only one will have a route and will succeed,
00316   // and the rest will fail. This requires the use of asynch
00317   // connection establishment. Maybe a custom wait strategy is needed
00318   // at this point to register several potential transports so that
00319   // when one succeeds the rest are cancelled or closed.
00320 
00321   return this->make_parallel_connection (r,*desc,timeout);
00322 }
00323 
00324 TAO_Transport*
00325 TAO_Connector::connect (TAO::Profile_Transport_Resolver *r,
00326                         TAO_Transport_Descriptor_Interface *desc,
00327                         ACE_Time_Value *timeout
00328                         ACE_ENV_ARG_DECL)
00329 {
00330   if (desc == 0 ||
00331       (this->set_validate_endpoint (desc->endpoint ()) == -1))
00332     return 0;
00333 
00334   TAO_Transport *base_transport = 0;
00335 
00336   TAO::Transport_Cache_Manager &tcm =
00337     this->orb_core ()->lane_resources ().transport_cache ();
00338 
00339   // Check the Cache first for connections
00340   // If transport found, reference count is incremented on assignment
00341   // @@todo: We need to send the timeout value to the cache registry
00342   // too. That should be the next step!
00343   if (tcm.find_transport (desc,
00344                           base_transport) != 0)
00345     {
00346       // @@TODO: This is not the right place for this!
00347       // Purge connections (if necessary)
00348       tcm.purge ();
00349 
00350       TAO_Transport* t = this->make_connection (r,
00351                                                 *desc,
00352                                                 timeout);
00353 
00354       if (t == 0)
00355         return t;
00356 
00357       t->opened_as (TAO::TAO_CLIENT_ROLE);
00358 
00359       if (TAO_debug_level > 4)
00360         ACE_DEBUG ((LM_DEBUG,
00361                     ACE_TEXT("(%P|%t) Transport_Connector::connect, ")
00362                     ACE_TEXT("opening Transport[%d] in TAO_CLIENT_ROLE\n"),
00363                     t->id ()));
00364 
00365       // Call post connect hook. If the post_connect_hook () returns
00366       // false, just purge the entry.
00367       if (!t->post_connect_hook ())
00368         {
00369           (void) t->purge_entry ();
00370 
00371           // Call connect again
00372           return this->connect (r,
00373                                 desc,
00374                                 timeout
00375                                 ACE_ENV_ARG_PARAMETER);
00376         }
00377 
00378       return t;
00379     }
00380 
00381   if (TAO_debug_level > 4)
00382     {
00383       TAO::Connection_Role cr =
00384         base_transport->opened_as ();
00385 
00386       ACE_DEBUG ((LM_DEBUG,
00387                   "TAO (%P|%t) - Transport_Connector::connect, "
00388                   "got an existing %s Transport[%d] in role %s\n",
00389                   base_transport->is_connected () ? "connected" : "unconnected",
00390                   base_transport->id (),
00391                   cr == TAO::TAO_SERVER_ROLE ? "TAO_SERVER_ROLE" :
00392                   cr == TAO::TAO_CLIENT_ROLE ? "TAO_CLIENT_ROLE" :
00393                   "TAO_UNSPECIFIED_ROLE" ));
00394     }
00395 
00396 
00397   // If connected return.
00398   if (base_transport->is_connected ())
00399     return base_transport;
00400 
00401   // It it possible to get a transport from the cache that is not
00402   // connected? If not, then the following code is bogus. We cannot
00403   // wait for a connection to complete on a transport in the cache.
00404   //
00405   // (mesnier_p@ociweb.com) It is indeed possible to reach this point.
00406   // The AMI_Buffering test does. When using non-blocking connects and
00407   // the first request(s) are asynch and may be queued, the connection
00408   // establishment may not be completed by the time the invocation is
00409   // done with it. In that case it is up to a subsequent invocation to
00410   // handle the connection completion.
00411 
00412   if (!this->wait_for_connection_completion (r,
00413                                              base_transport,
00414                                              timeout))
00415     {
00416       if (TAO_debug_level > 2)
00417         ACE_ERROR ((LM_ERROR,
00418                     "TAO (%P|%t) - Transport_Connector::"
00419                     "connect, "
00420                     "wait for completion failed\n"));
00421       return 0;
00422     }
00423 
00424   if (base_transport->is_connected () &&
00425       base_transport->wait_strategy ()->register_handler () == 0)
00426     {
00427       // Registration failures.
00428 
00429       // Purge from the connection cache, if we are not in the cache, this
00430       // just does nothing.
00431       (void) base_transport->purge_entry ();
00432 
00433       // Close the handler.
00434       (void) base_transport->close_connection ();
00435 
00436       if (TAO_debug_level > 0)
00437         ACE_ERROR ((LM_ERROR,
00438                     "TAO (%P|%t) - Transport_Connector [%d]::connect, "
00439                     "could not register the transport "
00440                     "in the reactor.\n",
00441                     base_transport->id ()));
00442 
00443       return 0;
00444     }
00445 
00446   return base_transport;
00447 }
00448 
00449 bool
00450 TAO_Connector::wait_for_connection_completion (
00451     TAO::Profile_Transport_Resolver *r,
00452     TAO_Transport *&transport,
00453     ACE_Time_Value *timeout)
00454 {
00455   if (TAO_debug_level > 2)
00456       ACE_DEBUG ((LM_DEBUG,
00457                   "TAO (%P|%t) - Transport_Connector::"
00458                   "wait_for_connection_completion, "
00459                   "going to wait for connection completion on transport"
00460                   "[%d]\n",
00461                   transport->id ()));
00462   // If we don't need to block for a transport just set the timeout to
00463   // be zero.
00464   ACE_Time_Value tmp_zero (ACE_Time_Value::zero);
00465   if (!r->blocked_connect ())
00466     {
00467       timeout = &tmp_zero;
00468     }
00469 
00470   // Wait until the connection is ready, when non-blocking we just do a wait
00471   // with zero time
00472   int result =
00473     this->active_connect_strategy_->wait (
00474       transport,
00475       timeout);
00476 
00477   if (TAO_debug_level > 2)
00478     ACE_DEBUG ((LM_DEBUG,
00479                 "TAO (%P|%t) - Transport_Connector::"
00480                 "wait_for_connection_completion, "
00481                 "transport [%d], wait done result = %d\n",
00482                 transport->id (), result));
00483 
00484   // There are three possibilities when wait() returns: (a)
00485   // connection succeeded; (b) connection failed; (c) wait()
00486   // failed because of some other error.  It is easy to deal with
00487   // (a) and (b).  (c) is tricky since the connection is still
00488   // pending and may get completed by some other thread.  The
00489   // following method deals with (c).
00490 
00491   if (result == -1)
00492     {
00493       if (!r->blocked_connect () && errno == ETIME)
00494         {
00495           if (TAO_debug_level > 2)
00496             ACE_DEBUG ((LM_DEBUG,
00497                         "TAO (%P|%t) - Transport_Connector::"
00498                         "wait_for_connection_completion, "
00499                         "transport [%d], timeout, resetting state.\n",
00500                         transport->id ()));
00501           transport->connection_handler()->
00502             reset_state(TAO_LF_Event::LFS_CONNECTION_WAIT);
00503           // If we did a non blocking connect, just ignore
00504           // any timeout errors
00505           result = 0;
00506         }
00507       else
00508         {
00509           // When we need to get a connected transport
00510           result =
00511             this->check_connection_closure (
00512               transport->connection_handler ());
00513         }
00514 
00515       // In case of errors.
00516       if (result == -1)
00517         {
00518           // Report that making the connection failed, don't print errno
00519           // because we touched the reactor and errno could be changed
00520           if (TAO_debug_level > 2)
00521             ACE_ERROR ((LM_ERROR,
00522                         "TAO (%P|%t) - Transport_Connector::"
00523                         "wait_for_connection_completion, "
00524                         "transport [%d], wait for completion failed\n",
00525                         transport->id()));
00526 
00527 
00528           // Set transport to zero, it is not usable, and the reference
00529           // count we added above was decremented by the base connector
00530           // handling the connection failure.
00531           transport = 0;
00532 
00533           return false;
00534         }
00535     }
00536 
00537   // Connection not ready yet but we can use this transport, if
00538   // we need a connected one we will block later to make sure
00539   // it is connected
00540   return true;
00541 }
00542 
00543 bool
00544 TAO_Connector::wait_for_connection_completion (
00545     TAO::Profile_Transport_Resolver *r,
00546     TAO_Transport *&the_winner,
00547     TAO_Transport **transport,
00548     unsigned int count,
00549     TAO_LF_Multi_Event *mev,
00550     ACE_Time_Value *timeout)
00551 {
00552   if (TAO_debug_level > 2)
00553     {
00554       ACE_DEBUG ((LM_DEBUG,
00555                   ACE_TEXT("(%P|%t) Transport_Connector::")
00556                   ACE_TEXT("wait_for_connection_completion, ")
00557                   ACE_TEXT("waiting for connection completion on ")
00558                   ACE_TEXT("%d transports, ["),
00559                   count));
00560       for (unsigned int i = 0; i < count; i++)
00561         ACE_DEBUG ((LM_DEBUG,
00562                     ACE_TEXT("%d%s"),transport[i]->id(),
00563                     (i < (count -1) ? ", " : "]\n")));
00564     }
00565 
00566   // If we don't need to block for a transport just set the timeout to
00567   // be zero.
00568   ACE_Time_Value tmp_zero (ACE_Time_Value::zero);
00569   if (!r->blocked_connect ())
00570     {
00571       timeout = &tmp_zero;
00572     }
00573 
00574   int result = this->active_connect_strategy_->wait (mev,timeout);
00575   the_winner = 0;
00576 
00577   if (result != -1)
00578     {
00579       the_winner = mev->winner()->transport();
00580       if (TAO_debug_level > 2)
00581         ACE_DEBUG ((LM_DEBUG,
00582                     ACE_TEXT("(%P|%t) Transport_Connector::")
00583                     ACE_TEXT("wait_for_connection_completion, ")
00584                     ACE_TEXT("transport [%d]\n"),
00585                     the_winner->id ()));
00586     }
00587   else if (errno == ETIME)
00588     {
00589       // this is the most difficult case. In this situation, there is no
00590       // nominated by the Multi_Event. The best we can do is pick one of
00591       // the pending connections.
00592       // Of course, this shouldn't happen in any case, since the wait
00593       // strategy is called with a timeout value of 0.
00594       for (unsigned int i = 0; i < count; i++)
00595         if (!transport[i]->connection_handler()->is_closed())
00596           {
00597             the_winner = transport[i];
00598             break;
00599           }
00600     }
00601 
00602   // It is possible that we have more than one connection that happened
00603   // to complete, or that none completed. Therefore we need to traverse
00604   // the list and ensure that all of the losers are closed.
00605   for (unsigned int i = 0; i < count; i++)
00606     {
00607       if (transport[i] != the_winner)
00608         this->check_connection_closure (transport[i]->connection_handler());
00609       // since we are doing this on may connections, the result isn't
00610       // particularly important.
00611     }
00612 
00613   // In case of errors.
00614   if (the_winner == 0)
00615     {
00616       // Report that making the connection failed, don't print errno
00617       // because we touched the reactor and errno could be changed
00618       if (TAO_debug_level > 2)
00619         ACE_ERROR ((LM_ERROR,
00620                     ACE_TEXT ("(%P|%t) Transport_Connector::")
00621                     ACE_TEXT ("wait_for_connection_completion, failed\n")
00622                     ));
00623 
00624       return false;
00625     }
00626 
00627   // Fix for a subtle problem. What happens if we are supposed to do
00628   // blocked connect but the transport is NOT connected? Force close
00629   // the connections
00630   if (r->blocked_connect () && !the_winner->is_connected ())
00631     {
00632       if (TAO_debug_level > 2)
00633         ACE_DEBUG ((LM_DEBUG,
00634                     "TAO (%P|%t) - Transport_Connector::"
00635                     "wait_for_connection_completion, "
00636                     "no connected transport for a blocked connection, "
00637                     "cancelling connections and reverting things \n"));
00638 
00639       // Forget the return value. We are busted anyway. Try our best
00640       // here.
00641       (void) this->cancel_svc_handler (the_winner->connection_handler ());
00642       the_winner = 0;
00643       return false;
00644     }
00645 
00646   // Connection may not ready for SYNC_NONE cases but we can use this
00647   // transport, if we need a connected one we will block later to make
00648   // sure it is connected
00649   return true;
00650 }
00651 
00652 int
00653 TAO_Connector::create_connect_strategy (void)
00654 {
00655   if (this->active_connect_strategy_ == 0)
00656     {
00657       this->active_connect_strategy_ =
00658         this->orb_core_->client_factory ()->create_connect_strategy (
00659           this->orb_core_);
00660     }
00661 
00662   if (this->active_connect_strategy_ == 0)
00663     {
00664       return -1;
00665     }
00666 
00667   return 0;
00668 }
00669 
00670 int
00671 TAO_Connector::check_connection_closure (
00672   TAO_Connection_Handler *connection_handler)
00673 {
00674   int result = -1;
00675 
00676   // Check if the handler has been closed.
00677   bool closed =
00678     connection_handler->is_closed ();
00679 
00680   // In case of failures and close() has not be called.
00681   if (!closed)
00682     {
00683       // First, cancel from connector.
00684       if (this->cancel_svc_handler (connection_handler) == -1)
00685         return -1;
00686 
00687       // Double check to make sure the handler has not been closed
00688       // yet.  This double check is required to ensure that the
00689       // connection handler was not closed yet by some other
00690       // thread since it was still registered with the connector.
00691       // Once connector.cancel() has been processed, we are
00692       // assured that the connector will no longer open/close this
00693       // handler.
00694       closed = connection_handler->is_closed ();
00695 
00696 
00697       // If closed, there is nothing to do here.  If not closed,
00698       // it was either opened or is still pending.
00699       if (!closed)
00700         {
00701           // Check if the handler has been opened.
00702           const bool open = connection_handler->is_open ();
00703 
00704           // Some other thread was able to open the handler even
00705           // though wait failed for this thread.
00706           if (open)
00707             {
00708               // Set the result to 0, we have an open connection
00709               result = 0;
00710             }
00711           else
00712             {
00713               // Assert that it is still connecting.
00714               ACE_ASSERT (connection_handler->is_connecting ());
00715 
00716               // Force close the handler now.
00717               connection_handler->close_handler ();
00718             }
00719         }
00720     }
00721 
00722   return result;
00723 }
00724 
00725 //@@ TAO_CONNECTOR_SPL_METHODS_ADD_HOOK
00726 
00727 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 11:54:26 2006 for TAO by doxygen 1.3.6