Revert "Minor modernization of DynamicAny code"
[ACE_TAO.git] / TAO / tao / Transport_Connector.cpp
blob9d920a75c559d5a96e182e21660dcce207ead2c9
1 // -*- C++ -*-
2 #include "tao/Transport_Connector.h"
3 #include "tao/Transport.h"
4 #include "tao/ORB_Core.h"
5 #include "tao/MProfile.h"
6 #include "tao/Profile.h"
7 #include "tao/Thread_Lane_Resources.h"
8 #include "tao/debug.h"
9 #include "tao/Connect_Strategy.h"
10 #include "tao/LF_Multi_Event.h"
11 #include "tao/Client_Strategy_Factory.h"
12 #include "tao/Connection_Handler.h"
13 #include "tao/Profile_Transport_Resolver.h"
14 #include "tao/Wait_Strategy.h"
15 #include "tao/SystemException.h"
16 #include "tao/Endpoint.h"
17 #include "tao/Base_Transport_Property.h"
19 #include "ace/OS_NS_string.h"
20 #include <cstring>
22 #if !defined (__ACE_INLINE__)
23 # include "tao/Transport_Connector.inl"
24 #endif /* __ACE_INLINE__ */
26 namespace
28 class TransportCleanupGuard
30 public:
31 // Constructor. Initially assume that we're going to clean up the
32 // transport upon destruction.
33 TransportCleanupGuard (TAO_Transport *tp)
34 : tp_ (tp),
35 awake_ (true)
39 ~TransportCleanupGuard ()
41 if (this->awake_ && this->tp_)
43 // Purge from the connection cache. If we are not in the
44 // cache, this does nothing.
45 this->tp_->purge_entry ();
47 // Close the handler and remove the reference.
48 this->tp_->close_connection ();
49 this->tp_->remove_reference ();
53 /// Turn off the guard.
54 void clear ()
56 this->awake_ = false;
59 private:
60 TAO_Transport * const tp_;
61 bool awake_;
65 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
67 // Connector
68 TAO_Connector::TAO_Connector (CORBA::ULong tag)
69 : active_connect_strategy_ (nullptr),
70 tag_ (tag),
71 orb_core_ (nullptr)
75 TAO_Connector::~TAO_Connector ()
77 delete this->active_connect_strategy_;
80 TAO_Profile *
81 TAO_Connector::corbaloc_scan (const char *str, size_t &len)
83 if (this->check_prefix (str) != 0)
84 return nullptr;
85 const char *comma_pos = std::strchr (str,',');
86 const char *slash_pos = std::strchr (str,'/');
87 if (comma_pos == nullptr && slash_pos == nullptr)
89 len = std::strlen (str);
91 else if (comma_pos == nullptr || comma_pos > slash_pos)
92 len = (slash_pos - str);
93 else len = comma_pos - str;
94 return this->make_profile();
97 int
98 TAO_Connector::make_mprofile (const char *string, TAO_MProfile &mprofile)
100 // This method utilizes the "Template Method" design pattern to
101 // parse the given URL style IOR for the protocol being used
102 // and create an mprofile from it.
104 // The methods that must be defined by all Connector sub-classes are:
105 // make_profile
106 // check_prefix
108 // Check for a valid string
109 if (!string || !*string)
111 throw ::CORBA::INV_OBJREF (
112 CORBA::SystemException::_tao_minor_code (
114 EINVAL),
115 CORBA::COMPLETED_NO);
118 // Check for the proper prefix in the IOR. If the proper prefix isn't
119 // in the IOR then it is not an IOR we can use.
120 if (this->check_prefix (string) != 0)
122 return 1;
123 // Failure: not the correct IOR for this protocol.
124 // DO NOT throw an exception here since the Connector_Registry
125 // should be allowed the opportunity to continue looking for
126 // an appropriate connector.
129 if (TAO_debug_level > 0)
131 TAOLIB_DEBUG ((LM_DEBUG,
132 ACE_TEXT ("TAO (%P|%t) - TAO_Connector::make_mprofile ")
133 ACE_TEXT ("<%C>\n"),
134 string));
137 ACE_CString ior;
139 ior.set (string, std::strlen (string), 1);
141 // Find out where the protocol ends
142 ACE_CString::size_type ior_index = ior.find ("://");
144 if (ior_index == ACE_CString::npos)
146 throw ::CORBA::INV_OBJREF ();
147 // No colon ':' in the IOR!
149 else
151 ior_index += 3;
152 // Add the length of the colon and the two forward slashes `://'
153 // to the IOR string index (i.e. 3)
156 // Find the object key
157 const ACE_CString::size_type objkey_index =
158 ior.find (this->object_key_delimiter (), ior_index);
160 if (objkey_index == 0 || objkey_index == ACE_CString::npos)
162 throw ::CORBA::INV_OBJREF ();
163 // Failure: No endpoints specified or no object key specified.
166 const char endpoint_delimiter = ',';
167 // The delimiter used to separate individual addresses.
169 // Count the number of endpoints in the IOR. This will be the number
170 // of entries in the MProfile.
172 CORBA::ULong profile_count = 1;
173 // Number of endpoints in the IOR (initialized to 1).
175 // Only check for endpoints after the protocol specification and
176 // before the object key.
177 for (ACE_CString::size_type i = ior_index; i < objkey_index; ++i)
179 if (ior[i] == endpoint_delimiter)
180 ++profile_count;
183 // Tell the MProfile object how many Profiles it should hold.
184 // MProfile::set(size) returns the number profiles it can hold.
185 if (mprofile.set (profile_count) != static_cast<int> (profile_count))
187 throw ::CORBA::INV_OBJREF (
188 CORBA::SystemException::_tao_minor_code (
189 TAO_MPROFILE_CREATION_ERROR,
191 CORBA::COMPLETED_NO);
192 // Error while setting the MProfile size!
195 // The idea behind the following loop is to split the IOR into several
196 // strings that can be parsed by each profile.
197 // For example,
198 // `1.3@moo,shu,1.1@chicken/arf'
199 // will be parsed into:
200 // `1.3@moo/arf'
201 // `shu/arf'
202 // `1.1@chicken/arf'
204 ACE_CString::size_type begin = 0;
205 ACE_CString::size_type end = ior_index - 1;
206 // Initialize the end of the endpoint index
208 for (CORBA::ULong j = 0; j < profile_count; ++j)
210 begin = end + 1;
212 if (j < profile_count - 1)
214 end = ior.find (endpoint_delimiter, begin);
216 else
218 end = objkey_index; // Handle last endpoint differently
221 if (end < ior.length () && end != ior.npos)
223 ACE_CString endpoint = ior.substring (begin, end - begin);
225 // Add the object key to the string.
226 endpoint += ior.substring (objkey_index);
228 // The endpoint should now be of the form:
229 // `N.n@endpoint/object_key'
230 // or
231 // `endpoint/object_key'
233 TAO_Profile *profile =
234 this->make_profile ();
235 // Failure: Problem during profile creation
237 // Initialize a Profile using the individual endpoint
238 // string.
239 // @@ Not exception safe! We need a TAO_Profile_var!
240 profile->parse_string (endpoint.c_str ());
242 // Give up ownership of the profile.
243 if (mprofile.give_profile (profile) == -1)
245 profile->_decr_refcnt ();
247 throw ::CORBA::INV_OBJREF (
248 CORBA::SystemException::_tao_minor_code (
249 TAO_MPROFILE_CREATION_ERROR,
251 CORBA::COMPLETED_NO);
252 // Failure presumably only occurs when MProfile is full!
253 // This should never happen.
256 else
258 throw ::CORBA::INV_OBJREF ();
259 // Unable to separate endpoints
263 return 0; // Success
267 TAO_Connector::supports_parallel_connects() const
269 return 0; // by default, we don't support parallel connection attempts;
272 TAO_Transport*
273 TAO_Connector::make_parallel_connection (TAO::Profile_Transport_Resolver *,
274 TAO_Transport_Descriptor_Interface &,
275 ACE_Time_Value *)
277 return nullptr;
281 TAO_Transport*
282 TAO_Connector::parallel_connect (TAO::Profile_Transport_Resolver *r,
283 TAO_Transport_Descriptor_Interface *desc,
284 ACE_Time_Value *timeout)
286 if (this->supports_parallel_connects() == 0)
288 errno = ENOTSUP;
289 return nullptr;
292 errno = 0; // need to clear errno to ensure a stale enotsup is not set
293 if (desc == nullptr)
294 return nullptr;
295 TAO_Endpoint *root_ep = desc->endpoint();
296 TAO_Transport *base_transport = nullptr;
298 TAO::Transport_Cache_Manager &tcm =
299 this->orb_core ()->lane_resources ().transport_cache ();
301 // Iterate through the endpoints. Since find_transport takes a
302 // Transport Descriptor rather than an endpoint, we must create a
303 // local TDI for each endpoint. The first one found will be used.
304 for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),nullptr);
305 ep != nullptr;
306 ep = ep->next_filtered(this->orb_core(),root_ep))
308 TAO_Base_Transport_Property desc2(ep,0);
309 size_t busy_count = 0;
310 if (tcm.find_transport (&desc2, base_transport, busy_count) ==
311 TAO::Transport_Cache_Manager::CACHE_FOUND_AVAILABLE)
313 if (TAO_debug_level)
315 TAOLIB_DEBUG ((LM_DEBUG,
316 ACE_TEXT ("TAO (%P|%t) - TAO_Connector::parallel_connect: ")
317 ACE_TEXT ("found a transport [%d]\n"),
318 base_transport->id ()));
320 return base_transport;
324 // Now we have searched the cache on all endpoints and come up
325 // empty. We need to initiate connections on each of the
326 // endpoints. Presumably only one will have a route and will succeed,
327 // and the rest will fail. This requires the use of asynch
328 // connection establishment. Maybe a custom wait strategy is needed
329 // at this point to register several potential transports so that
330 // when one succeeds the rest are cancelled or closed.
332 unsigned int endpoint_count = 0;
333 for (TAO_Endpoint *ep = root_ep->next_filtered (this->orb_core(),nullptr);
334 ep != nullptr;
335 ep = ep->next_filtered(this->orb_core(),root_ep))
336 if (this->set_validate_endpoint (ep) == 0)
337 ++endpoint_count;
338 if (endpoint_count == 0)
339 return nullptr;
340 return this->make_parallel_connection (r,*desc,timeout);
343 bool
344 TAO_Connector::wait_for_transport (TAO::Profile_Transport_Resolver *r,
345 TAO_Transport *transport,
346 ACE_Time_Value *timeout,
347 bool force_wait)
349 if (transport->connection_handler ()->is_timeout ())
351 if (TAO_debug_level > 2)
353 TAOLIB_DEBUG ((LM_DEBUG,
354 ACE_TEXT ("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
355 ACE_TEXT ("transport [%d], Connection Timed out.\n"),
356 transport->id ()));
358 transport->purge_entry ();
359 return false;
361 else if (transport->connection_handler ()->is_closed ())
363 if (TAO_debug_level > 2)
365 TAOLIB_DEBUG ((LM_DEBUG,
366 ACE_TEXT ("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
367 ACE_TEXT ("transport [%d], Connection failed. (%d)\n"),
368 transport->id (), ACE_ERRNO_GET));
371 // purge from the connection cache. If we are not in the
372 // cache, this does nothing.
373 transport->purge_entry ();
375 // Close the handler.
376 transport->close_connection ();
378 return false;
380 else if (transport->connection_handler ()->is_open ())
382 if (TAO_debug_level > 5)
384 TAOLIB_DEBUG ((LM_DEBUG,
385 ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
386 ACE_TEXT("transport [%d], connection is open: no wait.\n"),
387 transport->id () ));
390 return true;
392 else if (force_wait || r->blocked_connect ())
394 if (TAO_debug_level > 2)
396 TAOLIB_DEBUG ((LM_DEBUG,
397 ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
398 ACE_TEXT("waiting on transport [%d]\n"),
399 transport->id () ));
402 // We must ensure that there is a timeout if there was none
403 // supplied and the connection isn't a blocking connection. If
404 // another thread has called ORB::run() prior to this attempted
405 // connection, the wait() call will block forever (or until the ORB
406 // thread leaves the reactor, which may not happen).
407 int result = 0;
408 if (timeout == nullptr && !r->blocked_connect ())
410 ACE_Time_Value tv (0, 500);
411 result = this->active_connect_strategy_->wait (transport, &tv);
413 else
414 result = this->active_connect_strategy_->wait (transport, timeout);
416 if (result == -1 && errno == ETIME)
418 if (TAO_debug_level > 2)
420 TAOLIB_DEBUG ((LM_DEBUG,
421 ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
422 ACE_TEXT(" timeout while waiting on transport [%d]\n"),
423 transport->id () ));
426 else if (result == -1)
428 if (TAO_debug_level > 2)
430 static int complain10times = 10;
431 if (complain10times > 0)
433 --complain10times;
434 TAOLIB_DEBUG ((LM_DEBUG,
435 ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
436 ACE_TEXT(" unknown error waiting on transport [%d] (%d)\n"),
437 transport->id (),
438 ACE_ERRNO_GET));
441 // purge from the connection cache. If we are not in the
442 // cache, this does nothing.
443 transport->purge_entry ();
445 // Close the handler.
446 transport->close_connection ();
448 else
450 if (TAO_debug_level > 5)
452 TAOLIB_DEBUG ((LM_DEBUG,
453 ACE_TEXT("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
454 ACE_TEXT("transport [%d], wait completed ok.\n"),
455 transport->id () ));
457 return true;
460 else
462 if (TAO_debug_level > 2)
464 TAOLIB_DEBUG ((LM_DEBUG,
465 ACE_TEXT ("TAO (%P|%t) - TAO_Connector::wait_for_transport, ")
466 ACE_TEXT ("Connection not complete [%d] reset state to ")
467 ACE_TEXT ("LFS_CONNECTION_WAIT\n"), transport->id ()));
469 transport->connection_handler ()->reset_state (
470 TAO_LF_Event::LFS_CONNECTION_WAIT);
472 return true;
475 return false;
478 TAO_Transport*
479 TAO_Connector::connect (TAO::Profile_Transport_Resolver *r,
480 TAO_Transport_Descriptor_Interface *desc,
481 ACE_Time_Value *timeout)
483 TAO::Transport_Cache_Manager &tcm =
484 this->orb_core ()->lane_resources ().transport_cache ();
486 // Stay in this loop until we find:
487 // a usable connection, or a timeout happens
488 while (true)
490 // Find a connection in the cache
491 // If transport found, reference count is incremented on assignment
492 TAO_Transport *base_transport = nullptr;
493 size_t busy_count = 0;
494 TAO::Transport_Cache_Manager::Find_Result found =
495 tcm.find_transport (desc,
496 base_transport,
497 busy_count);
499 if (found == TAO::Transport_Cache_Manager::CACHE_FOUND_AVAILABLE)
501 TAO_Connection_Handler *ch = base_transport->connection_handler ();
502 // one last check before using the cached connection
503 if (ch->error_detected (this->orb_core ()->leader_follower ()))
505 if (TAO_debug_level > 0)
507 TAOLIB_DEBUG ((LM_DEBUG,
508 ACE_TEXT("TAO (%P|%t) Transport_Connector::connect, ")
509 ACE_TEXT("error in transport from cache\n")));
511 (void) base_transport->close_connection ();
512 (void) base_transport->purge_entry ();
513 base_transport->remove_reference ();
515 else if (ch->is_closed ())
517 if (TAO_debug_level > 0)
519 TAOLIB_DEBUG ((LM_DEBUG,
520 ACE_TEXT("TAO (%P|%t) Transport_Connector::connect, ")
521 ACE_TEXT("closed transport from cache\n")));
523 (void) base_transport->purge_entry ();
524 base_transport->remove_reference ();
526 else
528 if (TAO_debug_level > 4)
530 TAO::Connection_Role cr = base_transport->opened_as ();
532 TAOLIB_DEBUG ((LM_DEBUG,
533 ACE_TEXT("TAO (%P|%t) - Transport_Connector::connect, ")
534 ACE_TEXT("got an existing %C Transport[%d] in role %C\n"),
535 base_transport->is_connected () ? "connected" :
536 "unconnected",
537 base_transport->id (),
538 cr == TAO::TAO_SERVER_ROLE ? "TAO_SERVER_ROLE" :
539 cr == TAO::TAO_CLIENT_ROLE ? "TAO_CLIENT_ROLE" :
540 "TAO_UNSPECIFIED_ROLE" ));
543 // If connected return.
544 if (base_transport->is_connected ())
545 return base_transport;
547 // Is it possible to get a transport from the cache that
548 // is not connected? If not, then the following code is
549 // bogus. We cannot wait for a connection to complete on
550 // a transport in the cache.
552 // (mesnier_p@ociweb.com) It is indeed possible to reach
553 // this point. The AMI_Buffering test does. When using
554 // non-blocking connects and the first request(s) are
555 // asynch and may be queued, the connection
556 // establishment may not be completed by the time the
557 // invocation is done with it. In that case it is up to
558 // a subsequent invocation to handle the connection
559 // completion.
560 TransportCleanupGuard tg(base_transport);
561 if (!this->wait_for_connection_completion (r, *desc,
562 base_transport,
563 timeout))
565 if (TAO_debug_level > 2)
567 TAOLIB_ERROR ((LM_ERROR,
568 "TAO (%P|%t) - Transport_Connector::connect,"
569 " wait for completion failed\n"));
571 return nullptr;
574 if (base_transport->is_connected () &&
575 base_transport->wait_strategy ()->register_handler () == -1)
577 // Registration failures.
578 if (TAO_debug_level > 0)
580 TAOLIB_ERROR ((LM_ERROR,
581 "TAO (%P|%t) - Transport_Connector::connect, "
582 "could not register the transport [%d]"
583 "in the reactor.\n",
584 base_transport->id ()));
586 return nullptr;
589 tg.clear ();
590 return base_transport;
593 else if (found == TAO::Transport_Cache_Manager::CACHE_FOUND_CONNECTING)
595 if (r->blocked_connect ())
597 if (TAO_debug_level > 4)
599 TAOLIB_DEBUG ((LM_DEBUG,
600 ACE_TEXT("TAO (%P|%t) - ")
601 ACE_TEXT("Transport_Connector::waiting ")
602 ACE_TEXT("for connection on transport [%d]\n"),
603 base_transport->id ()));
606 // If wait_for_transport returns no errors, the base_transport
607 // points to the connection we wait for.
608 if (this->wait_for_transport (r, base_transport, timeout, false))
610 // be sure this transport is registered with the reactor
611 // before using it.
612 if (!base_transport->register_if_necessary ())
614 base_transport->remove_reference ();
615 return nullptr;
619 // In either success or failure cases of wait_for_transport, the
620 // ref counter in corresponding to the ref counter added by
621 // find_transport is decremented.
622 base_transport->remove_reference ();
624 else
626 if (TAO_debug_level > 4)
628 TAOLIB_DEBUG ((LM_DEBUG,
629 ACE_TEXT("TAO (%P|%t) - ")
630 ACE_TEXT("Transport_Connector::non-blocking:")
631 ACE_TEXT("returning unconnected ")
632 ACE_TEXT("transport [%d]\n"),
633 base_transport->id ()));
636 // return the transport in it's current, unconnected state
637 return base_transport;
640 else
642 if (desc == nullptr ||
643 (this->set_validate_endpoint (desc->endpoint ()) == -1))
644 return nullptr;
646 // @todo: This is not the right place for this! (bugzilla 3023)
647 // Purge connections (if necessary)
648 tcm.purge ();
649 bool const make_new_connection =
650 (found == TAO::Transport_Cache_Manager::CACHE_FOUND_NONE) ||
651 (found == TAO::Transport_Cache_Manager::CACHE_FOUND_BUSY
652 && this->new_connection_is_ok (busy_count));
654 if (make_new_connection)
656 // we aren't going to use the transport returned from the cache
657 // (if any)
658 if (base_transport != nullptr)
660 base_transport->remove_reference ();
663 base_transport = this->make_connection (r, *desc, timeout);
664 if (base_transport == nullptr)
666 if (TAO_debug_level > 4)
668 TAOLIB_DEBUG ((LM_DEBUG,
669 ACE_TEXT ("TAO (%P|%t) - Transport_Connector::")
670 ACE_TEXT ("connect, make_connection failed\n")));
672 return nullptr;
675 if (TAO_debug_level > 4)
677 TAOLIB_DEBUG ((LM_DEBUG,
678 ACE_TEXT("TAO (%P|%t) - ")
679 ACE_TEXT("Transport_Connector::connect, ")
680 ACE_TEXT("opening Transport[%d] in ")
681 ACE_TEXT("TAO_CLIENT_ROLE\n"),
682 base_transport->id ()));
685 // Call post connect hook. If the post_connect_hook () returns
686 // false, just purge the entry.
687 if (!base_transport->post_connect_hook ())
689 if (TAO_debug_level > 4)
691 TAOLIB_DEBUG ((LM_DEBUG,
692 ACE_TEXT("TAO (%P|%t) - Post_connect_hook ")
693 ACE_TEXT("failed. ")
694 ACE_TEXT("Purging transport[%d]\n"),
695 base_transport->id ()));
697 (void) base_transport->purge_entry ();
699 // The new transport is in the cache. We'll pick it up from the
700 // next time thru this loop (using it from here causes more
701 // problems than it fixes due to the changes that allow a new
702 // connection to be re-used by a nested upcall before we get back
703 // here.)
704 base_transport->remove_reference ();
706 else // not making new connection
708 (void) this->wait_for_transport (r, base_transport,
709 timeout, true);
710 base_transport->remove_reference ();
716 bool
717 TAO_Connector::wait_for_connection_completion (
718 TAO::Profile_Transport_Resolver *r,
719 TAO_Transport_Descriptor_Interface &desc,
720 TAO_Transport *&transport,
721 ACE_Time_Value *timeout)
723 int result = -1;
724 if (transport->connection_handler ()->is_open ())
726 TAO::Transport_Cache_Manager &tcm =
727 this->orb_core ()->lane_resources ().transport_cache ();
728 result = tcm.cache_transport (&desc, transport);
729 if (result == -1)
731 if (TAO_debug_level > 2)
733 TAOLIB_DEBUG ((LM_DEBUG,
734 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
735 ACE_TEXT("wait_for_connection_completion, ")
736 ACE_TEXT("transport [%d], Failed to cache transport.\n"),
737 transport->id ()));
741 else if (transport->connection_handler ()->is_timeout ())
743 if (TAO_debug_level > 2)
745 TAOLIB_DEBUG ((LM_DEBUG,
746 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
747 ACE_TEXT("wait_for_connection_completion, ")
748 ACE_TEXT("transport [%d], Connection timed out.\n"),
749 transport->id ()));
751 result = -1;
752 errno = ETIME;
754 else if (transport->connection_handler ()->is_closed ())
756 if (TAO_debug_level > 2)
758 TAOLIB_DEBUG ((LM_DEBUG,
759 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
760 ACE_TEXT("wait_for_connection_completion, ")
761 ACE_TEXT("transport [%d], Connection failed. (%d) %p\n"),
762 transport->id (), ACE_ERRNO_GET, ACE_TEXT("")));
764 result = -1;
766 else
768 if (TAO_debug_level > 2)
770 TAOLIB_DEBUG ((LM_DEBUG,
771 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
772 ACE_TEXT("wait_for_connection_completion, ")
773 ACE_TEXT("transport [%d], Connection not complete.\n"),
774 transport->id ()));
777 TAO::Transport_Cache_Manager &tcm =
778 this->orb_core ()->lane_resources ().transport_cache ();
779 result = tcm.cache_transport (&desc, transport, TAO::ENTRY_CONNECTING);
781 if (result != -1)
783 if (r->blocked_connect ())
785 if (TAO_debug_level > 2)
787 TAOLIB_DEBUG ((LM_DEBUG,
788 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
789 ACE_TEXT("wait_for_connection_completion, ")
790 ACE_TEXT("going to wait for connection completion on ")
791 ACE_TEXT("transport[%d]\n"),
792 transport->id ()));
795 result = this->active_connect_strategy_->wait (transport, timeout);
797 if (TAO_debug_level > 2)
799 TAOLIB_DEBUG ((LM_DEBUG,
800 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
801 ACE_TEXT("wait_for_connection_completion, ")
802 ACE_TEXT("transport [%d], wait done result = %d\n"),
803 transport->id (), result));
807 // There are three possibilities when wait() returns: (a)
808 // connection succeeded; (b) connection failed; (c) wait()
809 // failed because of some other error. It is easy to deal with
810 // (a) and (b). (c) is tricky since the connection is still
811 // pending and may get completed by some other thread. The
812 // following code deals with (c).
814 if (result == -1)
816 if (errno == ETIME)
818 if (timeout == nullptr)
820 // There was an error during connecting and the errno was
821 // ETIME. We didn't pass in a timeout, so there's
822 // something wrong with this transport. So, it must be
823 // purged.
824 transport->purge_entry ();
827 if (TAO_debug_level > 2)
829 TAOLIB_DEBUG ((LM_DEBUG,
830 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
831 ACE_TEXT("wait_for_connection_completion, ")
832 ACE_TEXT("transport [%d], Connection timed out.\n"),
833 transport->id ()));
836 else
838 // The wait failed for some other reason.
839 // Report that making the connection failed
840 if (TAO_debug_level > 2)
842 TAOLIB_ERROR ((LM_ERROR,
843 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
844 ACE_TEXT("wait_for_connection_completion, ")
845 ACE_TEXT("transport [%d], wait for completion failed")
846 ACE_TEXT(" (%d) %p\n"),
847 transport->id (), ACE_ERRNO_GET, ACE_TEXT("")));
849 TAO_Connection_Handler *con =
850 transport->connection_handler ();
851 result = this->check_connection_closure (con);
852 transport->purge_entry ();
856 else //non-blocked connect (based on invocation, not connect strategy)
858 transport->connection_handler ()->
859 reset_state (TAO_LF_Event::LFS_CONNECTION_WAIT);
860 if (TAO_debug_level > 9)
862 TAOLIB_DEBUG ((LM_DEBUG,
863 ACE_TEXT("TAO (%P|%t) - TAO_Connector[%d]::")
864 ACE_TEXT("wait_for_connection_completion reset_state to ")
865 ACE_TEXT("LFS_CONNECTION_WAIT\n"), transport->id ()));
867 result = 0;
872 if (result == -1)
874 // Set transport to zero, it is not usable, and the reference
875 // count we added above was decremented by the base connector
876 // handling the connection failure.
877 transport = nullptr;
878 return false;
880 // Connection not ready yet but we can use this transport, if
881 // we need a connected one we will block later to make sure
882 // it is connected
883 return true;
886 void
887 TAO_Connector::cleanup_pending (TAO_Transport *&the_winner,
888 TAO_Transport **transport,
889 unsigned int count)
891 // It is possible that we have more than one connection that happened
892 // to complete, or that none completed. Therefore we need to traverse
893 // the list and ensure that all of the losers are closed.
894 for (unsigned int i = 0; i < count; i++)
896 if (transport[i] != the_winner)
897 this->check_connection_closure (transport[i]->connection_handler());
898 // since we are doing this on may connections, the result isn't
899 // particularly important.
903 bool
904 TAO_Connector::wait_for_connection_completion (
905 TAO::Profile_Transport_Resolver *r,
906 TAO_Transport *&the_winner,
907 TAO_Transport **transport,
908 unsigned int count,
909 TAO_LF_Multi_Event *mev,
910 ACE_Time_Value *timeout)
912 if (TAO_debug_level > 2)
914 TAOLIB_DEBUG ((LM_DEBUG,
915 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
916 ACE_TEXT("wait_for_connection_completion, ")
917 ACE_TEXT("waiting for connection completion on ")
918 ACE_TEXT("%d transports, ["),
919 count));
920 for (unsigned int i = 0; i < count; i++)
921 TAOLIB_DEBUG ((LM_DEBUG,
922 ACE_TEXT("%d%C"),transport[i]->id (),
923 (i < (count -1) ? ", " : "]\n")));
926 int result = -1;
927 if (r->blocked_connect ())
929 result = this->active_connect_strategy_->wait (mev, timeout);
930 the_winner = nullptr;
932 else
934 errno = ETIME;
937 if (result != -1)
939 the_winner = mev->winner()->transport();
940 if (TAO_debug_level > 2)
942 TAOLIB_DEBUG ((LM_DEBUG,
943 ACE_TEXT ("TAO (%P|%t) - Transport_Connector::")
944 ACE_TEXT ("wait_for_connection_completion, ")
945 ACE_TEXT ("winner transport [%d]\n"),
946 the_winner->id ()));
949 else if (errno == ETIME)
951 // this is the most difficult case. In this situation, there is no
952 // nominated by the Multi_Event. The best we can do is pick one of
953 // the pending connections.
954 // Of course, this shouldn't happen in any case, since the wait
955 // strategy is called with a timeout value of 0.
956 for (unsigned int i = 0; i < count; i++)
957 if (!transport[i]->connection_handler()->is_closed())
959 the_winner = transport[i];
960 break;
964 this->cleanup_pending (the_winner, transport, count);
966 // In case of errors.
967 if (the_winner == nullptr)
969 // Report that making the connection failed, don't print errno
970 // because we touched the reactor and errno could be changed
971 if (TAO_debug_level > 2)
973 TAOLIB_ERROR ((LM_ERROR,
974 ACE_TEXT ("TAO (%P|%t) - Transport_Connector::")
975 ACE_TEXT ("wait_for_connection_completion, failed\n")
979 return false;
982 // Fix for a subtle problem. What happens if we are supposed to do
983 // blocked connect but the transport is NOT connected? Force close
984 // the connections
985 if (r->blocked_connect () && !the_winner->is_connected ())
987 if (TAO_debug_level > 2)
989 TAOLIB_DEBUG ((LM_DEBUG,
990 ACE_TEXT("TAO (%P|%t) - Transport_Connector::")
991 ACE_TEXT("wait_for_connection_completion, ")
992 ACE_TEXT("no connected transport for a blocked connection, ")
993 ACE_TEXT("cancelling connections and reverting things\n")));
996 // Forget the return value. We are busted anyway. Try our best
997 // here.
998 (void) this->cancel_svc_handler (the_winner->connection_handler ());
999 the_winner = nullptr;
1000 return false;
1003 // Connection may not ready for SYNC_NONE and SYNC_DELAYED_BUFFERING cases
1004 // but we can use this transport, if we need a connected one we will poll
1005 // later to make sure it is connected
1006 return true;
1010 TAO_Connector::create_connect_strategy ()
1012 if (this->active_connect_strategy_ == nullptr)
1014 this->active_connect_strategy_ =
1015 this->orb_core_->client_factory ()->create_connect_strategy (
1016 this->orb_core_);
1019 if (this->active_connect_strategy_ == nullptr)
1021 return -1;
1024 return 0;
1027 bool
1028 TAO_Connector::new_connection_is_ok (size_t busy_count)
1030 if (this->orb_core_ == nullptr)
1031 return true;
1033 unsigned int mux_limit = this->orb_core_->resource_factory ()
1034 ->max_muxed_connections ();
1036 return mux_limit == 0 || busy_count < mux_limit;
1040 TAO_Connector::check_connection_closure (
1041 TAO_Connection_Handler *connection_handler)
1043 int result = -1;
1045 // Check if the handler has been closed.
1046 bool closed = connection_handler->is_closed ();
1048 // In case of failures and close() has not be called.
1049 if (!closed)
1051 // First, cancel from connector.
1052 if (this->cancel_svc_handler (connection_handler) == -1)
1053 return -1;
1055 // Double check to make sure the handler has not been closed
1056 // yet. This double check is required to ensure that the
1057 // connection handler was not closed yet by some other
1058 // thread since it was still registered with the connector.
1059 // Once connector.cancel() has been processed, we are
1060 // assured that the connector will no longer open/close this
1061 // handler.
1062 closed = connection_handler->is_closed ();
1064 // If closed, there is nothing to do here. If not closed,
1065 // it was either opened or is still pending.
1066 if (!closed)
1068 // Check if the handler has been opened.
1069 const bool open = connection_handler->is_open ();
1071 // Some other thread was able to open the handler even
1072 // though wait failed for this thread.
1073 if (open)
1075 // Set the result to 0, we have an open connection
1076 result = 0;
1078 else
1080 // Assert that it is still connecting.
1081 ACE_ASSERT (connection_handler->is_connecting ());
1083 // Force close the handler now.
1084 connection_handler->close_handler ();
1089 return result;
1092 TAO_END_VERSIONED_NAMESPACE_DECL