diff options
Diffstat (limited to 'TAO/tao/Strategies/UIOP_Connector.cpp')
-rw-r--r-- | TAO/tao/Strategies/UIOP_Connector.cpp | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/TAO/tao/Strategies/UIOP_Connector.cpp b/TAO/tao/Strategies/UIOP_Connector.cpp index 89dcdab3cbe..bb5bb554eb5 100644 --- a/TAO/tao/Strategies/UIOP_Connector.cpp +++ b/TAO/tao/Strategies/UIOP_Connector.cpp @@ -347,6 +347,216 @@ TAO_UIOP_Connector::make_connection (TAO_GIOP_Invocation *invocation, return 0; } +TAO_Transport * +TAO_UIOP_Connector::make_connection (TAO::Profile_Transport_Resolver *, + TAO_Transport_Descriptor_Interface &desc, + ACE_Time_Value *max_wait_time) +{ + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) Connector::connect - ") + ACE_TEXT ("looking for UIOP connection.\n"))); + + TAO_UIOP_Endpoint *uiop_endpoint = + this->remote_endpoint (desc.endpoint ()); + + if (uiop_endpoint == 0) + return 0; + + const ACE_UNIX_Addr &remote_address = + uiop_endpoint->object_addr (); + + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) UIOP_Connector::connect ") + ACE_TEXT ("making a new connection \n"))); + + // Get the right synch options + ACE_Synch_Options synch_options; + + this->active_connect_strategy_->synch_options (max_wait_time, + synch_options); + + TAO_UIOP_Connection_Handler *svc_handler = 0; + + // Connect. + int result = + this->base_connector_.connect (svc_handler, + remote_address, + synch_options); + + // This call creates the service handler and bumps the #REFCOUNT# up + // one extra. There are three possibilities: (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) - UIOP_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) - UIOP_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>. + result = 0; + else + { + // Assert that it is still connecting. + ACE_ASSERT (svc_handler->is_connecting ()); + + // Force close the handler now. + svc_handler->close (); + } + } + } + } + + // Irrespective of success or failure, remove the extra #REFCOUNT#. + svc_handler->remove_reference (); + + // In case of errors. + if (result == -1) + { + // Give users a clue to the problem. + if (TAO_debug_level) + { + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P|%t) %s:%u, connection to ") + ACE_TEXT ("%s failed (%p)\n"), + __FILE__, + __LINE__, + uiop_endpoint->rendezvous_point (), + ACE_TEXT ("errno"))); + } + + return 0; + } + + // At this point, the connection has be successfully connected. + // #REFCOUNT# is one. + + 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 (); + + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) UIOP_Connector::connect ") + ACE_TEXT ("could not add the new connection to Cache \n"))); + } + + return 0; + } + + // 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 (); + + // Registration failures. + if (retval != 0) + { + // Purge from the connection cache. + transport->purge_entry (); + + // Close the handler. + svc_handler->close (); + + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + "TAO (%P|%t) - UIOP_Connector::make_connection, " + "could not register the new connection in the reactor\n")); + } + + return 0; + } + + return transport; +} + + TAO_Profile * TAO_UIOP_Connector::create_profile (TAO_InputCDR& cdr) { |