private bool DoConnect()
{
lock(reconnectMutex)
{
if(ConnectedTransport != null || disposed || connectionFailure != null)
{
return false;
}
else
{
List<Uri> connectList = ConnectList;
if(connectList.Count == 0)
{
Failure = new NMSConnectionException("No URIs available for connection.");
}
else
{
if(!UseExponentialBackOff)
{
ReconnectDelay = InitialReconnectDelay;
}
try
{
backupMutex.WaitOne();
if(Backup && backups.Count != 0)
{
BackupTransport bt = backups[0];
backups.RemoveAt(0);
ITransport t = bt.Transport;
Uri uri = bt.Uri;
t.Command = OnCommand;
t.Exception = OnException;
try
{
if(started)
{
RestoreTransport(t);
}
ReconnectDelay = InitialReconnectDelay;
failedConnectTransportURI = null;
ConnectedTransportURI = uri;
ConnectedTransport = t;
connectFailures = 0;
connected = true;
if(this.Resumed != null)
{
this.Resumed(t);
}
Tracer.InfoFormat("Successfully reconnected to backup {0}", uri.ToString());
return false;
}
catch(Exception e)
{
Tracer.DebugFormat("Backup transport failed: {0}", e.Message);
}
}
}
finally
{
backupMutex.ReleaseMutex();
}
ManualResetEvent allDone = new ManualResetEvent(false);
ITransport transport = null;
Uri chosenUri = null;
object syncLock = new object();
try
{
foreach(Uri uri in connectList)
{
if(ConnectedTransport != null || disposed)
{
break;
}
if(asyncConnect)
{
Tracer.DebugFormat("Attempting async connect to: {0}", uri);
// set connector up
Connector connector = new Connector(
delegate(ITransport transportToUse, Uri uriToUse)
{
if(transport == null)
{
lock(syncLock)
{
if(transport == null)
{
//the transport has not yet been set asynchronously so set it
transport = transportToUse;
chosenUri = uriToUse;
}
//notify issuing thread to move on
allDone.Set();
}
}
}, uri, this);
// initiate a thread to try connecting to broker
Thread thread = new Thread(connector.DoConnect) {Name = uri.ToString()};
thread.Start();
}
else
{
// synchronous connect
try
{
Tracer.DebugFormat("Attempting sync connect to: {0}", uri);
transport = TransportFactory.CompositeConnect(uri);
chosenUri = transport.RemoteAddress;
break;
}
catch(Exception e)
{
Failure = e;
Tracer.DebugFormat("Connect fail to: {0}, reason: {1}", uri, e.Message);
}
}
}
if(asyncConnect)
{
// now wait for transport to be populated, but timeout eventually
allDone.WaitOne(asyncTimeout, false);
}
if(transport != null)
{
transport.Command = OnCommand;
transport.Exception = OnException;
transport.Start();
if(started)
{
RestoreTransport(transport);
}
if(this.Resumed != null)
{
this.Resumed(transport);
}
Tracer.Debug("Connection established");
ReconnectDelay = InitialReconnectDelay;
ConnectedTransportURI = chosenUri;
ConnectedTransport = transport;
connectFailures = 0;
connected = true;
if(firstConnection)
{
firstConnection = false;
Tracer.InfoFormat("Successfully connected to: {0}", chosenUri.ToString());
}
else
{
Tracer.InfoFormat("Successfully reconnected to: {0}", chosenUri.ToString());
}
return false;
}
if(asyncConnect)
{
Tracer.DebugFormat("Connect failed after waiting for asynchronous callback.");
}
}
catch(Exception e)
{
Failure = e;
Tracer.DebugFormat("Connect attempt failed. Reason: {0}", e.Message);
}
}
int reconnectAttempts = 0;
if( firstConnection ) {
if( StartupMaxReconnectAttempts != 0 ) {
reconnectAttempts = StartupMaxReconnectAttempts;
}
}
if( reconnectAttempts == 0 ) {
reconnectAttempts = MaxReconnectAttempts;
}
if(reconnectAttempts > 0 && ++connectFailures >= reconnectAttempts)
{
Tracer.ErrorFormat("Failed to connect to transport after {0} attempt(s)", connectFailures);
connectionFailure = Failure;
this.Exception(this, connectionFailure);
return false;
}
}
}
if(!disposed)
{
Tracer.DebugFormat("Waiting {0}ms before attempting connection.", ReconnectDelay);
lock(sleepMutex)
{
try
{
Thread.Sleep(ReconnectDelay);
}
catch(ThreadInterruptedException)
{
}
}
if(UseExponentialBackOff)
{
// Exponential increment of reconnect delay.
ReconnectDelay *= ReconnectDelayExponent;
if(ReconnectDelay > MaxReconnectDelay)
{
ReconnectDelay = MaxReconnectDelay;
}
}
}
return !disposed;
}