private Conversation doConnect ( ConversationReceiveListener conversationReceiveListener , ConversationUsageType usageType , JFapAddressHolder jfapAddressHolder , final NetworkConnectionFactoryHolder ncfHolder ) throws JFapConnectFailedException , SIResourceException { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) SibTr . entry ( this , tc , "doConnect" , new Object [ ] { conversationReceiveListener , usageType , jfapAddressHolder , ncfHolder } ) ; Conversation retConversation ; ConnectionData connectionDataToUse ; synchronized ( connectionMonitor ) { try { connectionDataToUse = findConnectionDataToUse ( ) ; boolean isNewConnectionData = false ; if ( connectionDataToUse == null ) { // We were either unable to find a connection at all, or we could not // find a connection with a use count lower than the maximum number of // conversations we want to share a connection. Either way, create a // new connection and add it to the group. if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , "connection data does not already exist" ) ; try { NetworkConnection vc = connectOverNetwork ( jfapAddressHolder , ncfHolder ) ; connectionDataToUse = createnewConnectionData ( vc ) ; isNewConnectionData = true ; } catch ( FrameworkException frameworkException ) { // Something went wrong attempting to establish the outbound connection. // Link the exception that was thrown to a new SICommsException and throw // it back to the caller. FFDCFilter . processException ( frameworkException , "com.ibm.ws.sib.jfapchannel.impl.octracker.ConnectionDataGroup.doConnect" , JFapChannelConstants . CONNDATAGROUP_CONNECT_04 , this ) ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEventEnabled ( ) ) SibTr . exception ( this , tc , frameworkException ) ; throw new SIErrorException ( nls . getFormattedMessage ( "CONNDATAGROUP_INTERNAL_SICJ0062" , null , "CONNDATAGROUP_INTERNAL_SICJ0062" ) , frameworkException ) ; } } retConversation = startNewConversation ( connectionDataToUse , conversationReceiveListener , isNewConnectionData , usageType . requiresNormalHandshakeProcessing ( ) ) ; } finally { // Whatever happened, this connection attempt is no longer pending. // //We have to hold the connectionMonitor lock prior to obtaining the lock on 'this' as there is the potential for deadlock in the following //scenario. // //Thread 1 starts the first conversation over the connection and has to perform handshaking. //Thread 2 starts another conversation and has to wait for thread 1 to perform the handshake. This means that thread 2 has acquired the lock on 'this'. //Thread 1 tries to acquire the lock on 'this' below. //Deadlock... synchronized ( this ) { -- connectAttemptsPending ; if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) SibTr . debug ( this , tc , connectAttemptsPending + " connection attempts still pending" ) ; } } } if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) SibTr . exit ( this , tc , "doConnect" , retConversation ) ; return retConversation ; }
Actually do the connecting creating a new ConnectionData if required