From f17aa1c26ea86d00ec1cf57cbccdaea829ba0220 Mon Sep 17 00:00:00 2001 From: irfan Date: Mon, 7 Jul 2003 23:58:34 +0000 Subject: ChangeLogTag: Mon Jul 07 18:00:38 2003 Irfan Pyarali --- TAO/tao/IIOP_Connector.cpp | 321 +++++++++++++++++++++++++++------------------ 1 file changed, 195 insertions(+), 126 deletions(-) (limited to 'TAO/tao/IIOP_Connector.cpp') diff --git a/TAO/tao/IIOP_Connector.cpp b/TAO/tao/IIOP_Connector.cpp index feaaeede5f9..fa3c81b0d21 100644 --- a/TAO/tao/IIOP_Connector.cpp +++ b/TAO/tao/IIOP_Connector.cpp @@ -15,25 +15,17 @@ #include "ace/Strategies_T.h" - ACE_RCSID (TAO, IIOP_Connector, "$Id$") - #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) template class TAO_Connect_Concurrency_Strategy; template class TAO_Connect_Creation_Strategy; template class ACE_Strategy_Connector; template class ACE_Connect_Strategy; template class ACE_Connector; -template class ACE_Svc_Tuple; - -template class ACE_Map_Manager *, TAO_SYNCH_RW_MUTEX>; -template class ACE_Map_Iterator_Base *, TAO_SYNCH_RW_MUTEX>; -template class ACE_Map_Entry*>; -template class ACE_Map_Iterator*,TAO_SYNCH_RW_MUTEX>; -template class ACE_Map_Reverse_Iterator*,TAO_SYNCH_RW_MUTEX>; +template class ACE_NonBlocking_Connect_Handler; #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) @@ -42,17 +34,10 @@ template class ACE_Map_Reverse_Iterator #pragma instantiate ACE_Connect_Strategy #pragma instantiate ACE_Connector -#pragma instantiate ACE_Svc_Tuple - -#pragma instantiate ACE_Map_Manager *, TAO_SYNCH_RW_MUTEX> -#pragma instantiate ACE_Map_Iterator_Base *, TAO_SYNCH_RW_MUTEX> -#pragma instantiate ACE_Map_Entry*> -#pragma instantiate ACE_Map_Iterator*,TAO_SYNCH_RW_MUTEX> -#pragma instantiate ACE_Map_Reverse_Iterator*,TAO_SYNCH_RW_MUTEX> +#pragma instantiate ACE_NonBlocking_Connect_Handler #endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ - TAO_IIOP_Connector::TAO_IIOP_Connector (CORBA::Boolean flag) : TAO_Connector (IOP::TAG_INTERNET_IOP), lite_flag_ (flag), @@ -154,130 +139,214 @@ TAO_IIOP_Connector::make_connection (TAO_GIOP_Invocation *invocation, TAO_IIOP_Endpoint *iiop_endpoint = this->remote_endpoint (desc->endpoint ()); - if (iiop_endpoint == 0) - return -1; - - const ACE_INET_Addr &remote_address = - iiop_endpoint->object_addr (); - - if (TAO_debug_level > 2) - ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - IIOP_Connector::make_connection, " - "to <%s:%d>\n", - iiop_endpoint->host(), iiop_endpoint->port())); - - // Get the right synch options - ACE_Synch_Options synch_options; - - this->active_connect_strategy_->synch_options (max_wait_time, - synch_options); - - TAO_IIOP_Connection_Handler *svc_handler = 0; - - // Active connect - int result = this->base_connector_.connect (svc_handler, - remote_address, - synch_options); - - - if (result == -1 && errno == EWOULDBLOCK) - { - if (TAO_debug_level > 2) - ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - IIOP_Connector::make_connection, " - "going to wait for connection completion on local" - "handle [%d]\n", - svc_handler->get_handle ())); - - result = - this->active_connect_strategy_->wait (svc_handler, - max_wait_time); - - if (TAO_debug_level > 2) - { - ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - IIOP_Connector::make_connection" - "wait done for handle[%d], result = %d\n", - svc_handler->get_handle (), result)); - } - - } - - int status = - svc_handler->is_finalized (); - - // Reduce the refcount to the svc_handler that we have. The - // increment to the handler is done in make_svc_handler (). Now - // that we dont need the reference to it anymore we can decrement - // the refcount whether the connection is successful ot not. - - // REFCNT: Matches with TAO_Connect_Strategy<>::make_svc_handler() - long refcount = svc_handler->decr_refcount (); + if (iiop_endpoint == 0) + return -1; - ACE_ASSERT (refcount >= 0); + const ACE_INET_Addr &remote_address = + iiop_endpoint->object_addr (); + + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - IIOP_Connector::make_connection, " + "to <%s:%d>\n", + iiop_endpoint->host(), iiop_endpoint->port())); + + // Get the right synch options + ACE_Synch_Options synch_options; + + this->active_connect_strategy_->synch_options (max_wait_time, + synch_options); + + TAO_IIOP_Connection_Handler *svc_handler = 0; + + // Connect. + int result = + this->base_connector_.connect (svc_handler, + remote_address, + synch_options); + + // The connect() method creates the service handler and bumps the + // #REFCOUNT# up one extra. There are three possibilities from + // calling connect(): (a) connection succeeds immediately - in this + // case, the #REFCOUNT# on the handler is two; (b) connection + // completion is pending - in this case, the #REFCOUNT# on the + // handler is also two; (c) connection fails immediately - in this + // case, the #REFCOUNT# on the handler is one since close() gets + // called on the handler. + // + // The extra reference count in + // TAO_Connect_Creation_Strategy::make_svc_handler() is needed in + // the case when connection completion is pending and we are going + // to wait on a variable in the handler to changes, signifying + // success or failure. Note, that this increment cannot be done + // once the connect() returns since this might be too late if + // another thread pick up the completion and potentially deletes the + // handler before we get a chance to increment the reference count. + + // No immediate result. Wait for completion. + if (result == -1 && errno == EWOULDBLOCK) + { + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - IIOP_Connector::make_connection, " + "going to wait for connection completion on local" + "handle [%d]\n", + svc_handler->get_handle ())); + + // Wait for connection completion. No need to specify timeout + // to wait() since the correct timeout was passed to the + // Connector. The Connector will close the handler in the case + // of timeouts, so the event will complete (either success or + // failure) within timeout. + result = + this->active_connect_strategy_->wait (svc_handler, + 0); + + if (TAO_debug_level > 2) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - IIOP_Connector::make_connection" + "wait done for handle[%d], result = %d\n", + svc_handler->get_handle (), result)); + } + + // There are three possibilities when wait() returns: (a) + // connection succeeded; (b) connection failed; (c) wait() + // failed because of some other error. It is easy to deal with + // (a) and (b). (c) is tricky since the connection is still + // pending and may get completed by some other thread. The + // following code deals with (c). + + // Check if the handler has been closed. + int closed = + svc_handler->is_closed (); + + // In case of failures and close() has not be called. + if (result == -1 && + !closed) + { + // First, cancel from connector. + this->base_connector_.cancel (svc_handler); + + // Double check to make sure the handler has not been closed + // yet. This double check is required to ensure that the + // connection handler was not closed yet by some other + // thread since it was still registered with the connector. + // Once connector.cancel() has been processed, we are + // assured that the connector will no longer open/close this + // handler. + closed = + svc_handler->is_closed (); + + // If closed, there is nothing to do here. If not closed, + // it was either opened or is still pending. + if (!closed) + { + // Check if the handler has been opened. + int open = + svc_handler->is_open (); + + // Some other thread was able to open the handler even + // though wait failed for this thread. + if (open) + // Overwrite . + result = 0; + else + { + // Assert that it is still connecting. + ACE_ASSERT (svc_handler->is_connecting ()); + + // Force close the handler now. + svc_handler->close (); + } + } + } + } - ACE_UNUSED_ARG (refcount); + // Irrespective of success or failure, remove the extra #REFCOUNT#. + svc_handler->remove_reference (); - if (result == -1) - { - // Give users a clue to the problem. - if (TAO_debug_level) - { - ACE_DEBUG ((LM_ERROR, - "TAO (%P|%t) - IIOP_Connector::make_connection, " - "connection to <%s:%d> failed (%p)\n", - iiop_endpoint->host (), iiop_endpoint->port (), - "errno")); - } + // In case of errors. + if (result == -1) + { + // Give users a clue to the problem. + if (TAO_debug_level) + { + ACE_DEBUG ((LM_ERROR, + "TAO (%P|%t) - IIOP_Connector::make_connection, " + "connection to <%s:%d> failed (%p)\n", + iiop_endpoint->host (), iiop_endpoint->port (), + "errno")); + } + + return -1; + } - (void) this->active_connect_strategy_->post_failed_connect (svc_handler, - status); + // At this point, the connection has be successfully connected. + // #REFCOUNT# is one. + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - IIOP_Connector::make_connection, " + "new connection to <%s:%d> on Transport[%d]\n", + iiop_endpoint->host (), iiop_endpoint->port (), + svc_handler->peer ().get_handle ())); + + TAO_Transport *transport = + svc_handler->transport (); + + // Add the handler to Cache + int retval = + this->orb_core ()->lane_resources ().transport_cache ().cache_transport (desc, + transport); + + // Failure in adding to cache. + if (retval != 0) + { + // Close the handler. + svc_handler->close (); - return -1; - } + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + "TAO (%P|%t) - IIOP_Connector::make_connection, " + "could not add the new connection to cache\n")); + } - if (TAO_debug_level > 2) - ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - IIOP_Connector::make_connection, " - "new connection to <%s:%d> on Transport[%d]\n", - iiop_endpoint->host (), iiop_endpoint->port (), - svc_handler->peer ().get_handle ())); + return -1; + } - TAO_Transport *base_transport = - TAO_Transport::_duplicate (svc_handler->transport ()); + // If the wait strategy wants us to be registered with the reactor + // then we do so. If registeration is required and it succeeds, + // #REFCOUNT# becomes two. + retval = transport->wait_strategy ()->register_handler (); - // Add the handler to Cache - int retval = - this->orb_core ()->lane_resources ().transport_cache ().cache_transport (desc, - base_transport); + // Registration failures. + if (retval != 0) + { + // Purge from the connection cache. + transport->purge_entry (); - if (retval != 0 && TAO_debug_level > 0) - { - ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - IIOP_Connector::make_connection, " - "could not add the new connection to cache\n")); - } + // Close the handler. + svc_handler->close (); - // If the wait strategy wants us to be registered with the reactor - // then we do so. - retval = base_transport->wait_strategy ()->register_handler (); + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + "TAO (%P|%t) - IIOP_Connector::make_connection, " + "could not register the new connection in the reactor\n")); + } - if (retval != 0 && TAO_debug_level > 0) - { - ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - IIOP_Connector::make_connection, " - "could not register the new connection in the reactor\n")); - } + return -1; + } - // Handover the transport pointer to the Invocation class. - TAO_Transport *&transport = invocation->transport (); - transport = base_transport; + // Handover the transport pointer to the Invocation class. + TAO_Transport *&invocation_transport = + invocation->transport (); + invocation_transport = transport; - return 0; + return 0; } - - TAO_Profile * TAO_IIOP_Connector::create_profile (TAO_InputCDR& cdr) { -- cgit v1.2.1