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"
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"
22 #if !defined (__ACE_INLINE__)
23 # include "tao/Transport_Connector.inl"
24 #endif /* __ACE_INLINE__ */
28 class TransportCleanupGuard
31 // Constructor. Initially assume that we're going to clean up the
32 // transport upon destruction.
33 TransportCleanupGuard (TAO_Transport
*tp
)
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.
60 TAO_Transport
* const tp_
;
65 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
68 TAO_Connector::TAO_Connector (CORBA::ULong tag
)
69 : active_connect_strategy_ (nullptr),
75 TAO_Connector::~TAO_Connector ()
77 delete this->active_connect_strategy_
;
81 TAO_Connector::corbaloc_scan (const char *str
, size_t &len
)
83 if (this->check_prefix (str
) != 0)
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();
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:
108 // Check for a valid string
109 if (!string
|| !*string
)
111 throw ::CORBA::INV_OBJREF (
112 CORBA::SystemException::_tao_minor_code (
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)
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 ")
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!
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
)
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.
198 // `1.3@moo,shu,1.1@chicken/arf'
199 // will be parsed into:
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
)
212 if (j
< profile_count
- 1)
214 end
= ior
.find (endpoint_delimiter
, begin
);
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'
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
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.
258 throw ::CORBA::INV_OBJREF ();
259 // Unable to separate endpoints
267 TAO_Connector::supports_parallel_connects() const
269 return 0; // by default, we don't support parallel connection attempts;
273 TAO_Connector::make_parallel_connection (TAO::Profile_Transport_Resolver
*,
274 TAO_Transport_Descriptor_Interface
&,
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)
292 errno
= 0; // need to clear errno to ensure a stale enotsup is not set
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);
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
)
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);
335 ep
= ep
->next_filtered(this->orb_core(),root_ep
))
336 if (this->set_validate_endpoint (ep
) == 0)
338 if (endpoint_count
== 0)
340 return this->make_parallel_connection (r
,*desc
,timeout
);
344 TAO_Connector::wait_for_transport (TAO::Profile_Transport_Resolver
*r
,
345 TAO_Transport
*transport
,
346 ACE_Time_Value
*timeout
,
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"),
358 transport
->purge_entry ();
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 ();
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"),
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"),
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).
408 if (timeout
== nullptr && !r
->blocked_connect ())
410 ACE_Time_Value
tv (0, 500);
411 result
= this->active_connect_strategy_
->wait (transport
, &tv
);
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"),
426 else if (result
== -1)
428 if (TAO_debug_level
> 2)
430 static int complain10times
= 10;
431 if (complain10times
> 0)
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"),
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 ();
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"),
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
);
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
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
,
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 ();
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" :
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
560 TransportCleanupGuard
tg(base_transport
);
561 if (!this->wait_for_connection_completion (r
, *desc
,
565 if (TAO_debug_level
> 2)
567 TAOLIB_ERROR ((LM_ERROR
,
568 "TAO (%P|%t) - Transport_Connector::connect,"
569 " wait for completion failed\n"));
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]"
584 base_transport
->id ()));
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
612 if (!base_transport
->register_if_necessary ())
614 base_transport
->remove_reference ();
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 ();
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
;
642 if (desc
== nullptr ||
643 (this->set_validate_endpoint (desc
->endpoint ()) == -1))
646 // @todo: This is not the right place for this! (bugzilla 3023)
647 // Purge connections (if necessary)
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
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")));
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 ")
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
704 base_transport
->remove_reference ();
706 else // not making new connection
708 (void) this->wait_for_transport (r
, base_transport
,
710 base_transport
->remove_reference ();
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
)
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
);
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"),
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"),
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("")));
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"),
777 TAO::Transport_Cache_Manager
&tcm
=
778 this->orb_core ()->lane_resources ().transport_cache ();
779 result
= tcm
.cache_transport (&desc
, transport
, TAO::ENTRY_CONNECTING
);
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"),
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).
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
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"),
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 ()));
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.
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
887 TAO_Connector::cleanup_pending (TAO_Transport
*&the_winner
,
888 TAO_Transport
**transport
,
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.
904 TAO_Connector::wait_for_connection_completion (
905 TAO::Profile_Transport_Resolver
*r
,
906 TAO_Transport
*&the_winner
,
907 TAO_Transport
**transport
,
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, ["),
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")));
927 if (r
->blocked_connect ())
929 result
= this->active_connect_strategy_
->wait (mev
, timeout
);
930 the_winner
= nullptr;
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"),
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
];
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")
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
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
998 (void) this->cancel_svc_handler (the_winner
->connection_handler ());
999 the_winner
= nullptr;
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
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 (
1019 if (this->active_connect_strategy_
== nullptr)
1028 TAO_Connector::new_connection_is_ok (size_t busy_count
)
1030 if (this->orb_core_
== nullptr)
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
)
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.
1051 // First, cancel from connector.
1052 if (this->cancel_svc_handler (connection_handler
) == -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
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.
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.
1075 // Set the result to 0, we have an open connection
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 ();
1092 TAO_END_VERSIONED_NAMESPACE_DECL