summaryrefslogtreecommitdiff
path: root/dotnet/Qpid.Client/qms
diff options
context:
space:
mode:
authorSteven Shaw <steshaw@apache.org>2006-11-25 22:04:39 +0000
committerSteven Shaw <steshaw@apache.org>2006-11-25 22:04:39 +0000
commit7c1f9158be7a5d1124a48f42f8d7dcfb6d5df2a6 (patch)
tree3122525268281cd9df870e0a9cb309ee7410a424 /dotnet/Qpid.Client/qms
parent8f32ca18d5281eaa5baafa769c99fa70c830b14f (diff)
downloadqpid-python-7c1f9158be7a5d1124a48f42f8d7dcfb6d5df2a6.tar.gz
QPID-128 Initial import of the C# sources.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@479211 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'dotnet/Qpid.Client/qms')
-rw-r--r--dotnet/Qpid.Client/qms/BrokerInfo.cs63
-rw-r--r--dotnet/Qpid.Client/qms/ConnectionInfo.cs76
-rw-r--r--dotnet/Qpid.Client/qms/FailoverPolicy.cs315
-rw-r--r--dotnet/Qpid.Client/qms/failover/FailoverMethod.cs79
-rw-r--r--dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs255
-rw-r--r--dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs147
6 files changed, 935 insertions, 0 deletions
diff --git a/dotnet/Qpid.Client/qms/BrokerInfo.cs b/dotnet/Qpid.Client/qms/BrokerInfo.cs
new file mode 100644
index 0000000000..dd0504968e
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/BrokerInfo.cs
@@ -0,0 +1,63 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+
+namespace Qpid.Client.qms
+{
+ /// <summary>
+ /// Know URL option names.
+ /// <seealso cref="ConnectionInfo"/>
+ /// </summary>
+ public class BrokerDetailsConstants
+ {
+ public const String OPTIONS_RETRY = "retries";
+ public const String OPTIONS_SSL = ConnectionUrlConstants.OPTIONS_SSL;
+ public const String OPTIONS_CONNECT_TIMEOUT = "connecttimeout";
+ public const int DEFAULT_PORT = 5672;
+ public const String DEFAULT_TRANSPORT = "tcp";
+
+ public readonly string URL_FORMAT_EXAMPLE =
+ "<transport>://<hostname>[:<port Default=\"" + DEFAULT_PORT + "\">][?<option>='<value>'[,<option>='<value>']]";
+
+ public const long DEFAULT_CONNECT_TIMEOUT = 30000L;
+ }
+
+ public interface BrokerInfo
+ {
+ String getHost();
+ void setHost(string host);
+
+ int getPort();
+ void setPort(int port);
+
+ String getTransport();
+ void setTransport(string transport);
+
+ bool useSSL();
+ void useSSL(bool ssl);
+
+ String getOption(string key);
+ void setOption(string key, string value);
+
+ long getTimeout();
+ void setTimeout(long timeout);
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Client/qms/ConnectionInfo.cs b/dotnet/Qpid.Client/qms/ConnectionInfo.cs
new file mode 100644
index 0000000000..1d099daa3e
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/ConnectionInfo.cs
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System.Collections;
+
+namespace Qpid.Client.qms
+{
+ class ConnectionUrlConstants
+ {
+ public const string AMQ_PROTOCOL = "amqp";
+ public const string OPTIONS_BROKERLIST = "brokerlist";
+ public const string OPTIONS_FAILOVER = "failover";
+ public const string OPTIONS_FAILOVER_CYCLE = "cyclecount";
+ public const string OPTIONS_SSL = "ssl";
+ }
+
+ /**
+ Connection URL format
+ amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\'&option=\'value\';vm://:3/virtualpath?option=\'value\''&failover='method?option=\'value\'&option='value''"
+ Options are of course optional except for requiring a single broker in the broker list.
+ The option seperator is defined to be either '&' or ','
+ */
+ public interface ConnectionInfo
+ {
+ string asUrl();
+
+ string getFailoverMethod();
+
+ string getFailoverOption(string key);
+
+ int getBrokerCount();
+
+ BrokerInfo GetBrokerDetails(int index);
+
+ void AddBrokerInfo(BrokerInfo broker);
+
+ IList GetAllBrokerInfos();
+
+ string GetClientName();
+
+ void SetClientName(string clientName);
+
+ string getUsername();
+
+ void setUsername(string username);
+
+ string getPassword();
+
+ void setPassword(string password);
+
+ string getVirtualHost();
+
+ void setVirtualHost(string virtualHost);
+
+ string getOption(string key);
+
+ void setOption(string key, string value);
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/FailoverPolicy.cs b/dotnet/Qpid.Client/qms/FailoverPolicy.cs
new file mode 100644
index 0000000000..15d52491df
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/FailoverPolicy.cs
@@ -0,0 +1,315 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Text;
+using log4net;
+using Qpid.Client.qms.failover;
+
+namespace Qpid.Client.qms
+{
+ public class FailoverPolicy
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(FailoverPolicy));
+
+ private const long MINUTE = 60000L;
+
+ private const long DEFAULT_METHOD_TIMEOUT = 1 * MINUTE;
+ private const long DEFAULT_FAILOVER_TIMEOUT = 4 * MINUTE;
+
+ private FailoverMethod[] _methods = new FailoverMethod[1];
+
+ private int _currentMethod;
+
+ private int _methodsRetries;
+
+ private int _currentRetry;
+
+ private bool _timing;
+
+ private long _lastMethodTime;
+ private long _lastFailTime;
+
+ public FailoverPolicy(ConnectionInfo connectionInfo)
+ {
+ FailoverMethod method;
+
+ //todo This should be integrated in to the connection url when it supports
+ // multiple strategies.
+
+ _methodsRetries = 0;
+
+ if (connectionInfo.getFailoverMethod() == null)
+ {
+ if (connectionInfo.getBrokerCount() > 1)
+ {
+ method = new FailoverRoundRobin(connectionInfo);
+ }
+ else
+ {
+ method = new FailoverSingleServer(connectionInfo);
+ }
+ }
+ else
+ {
+ string failoverMethod = connectionInfo.getFailoverMethod();
+
+ /*
+ if (failoverMethod.equals(FailoverMethod.RANDOM))
+ {
+ //todo write a random connection Failover
+ }
+ */
+ if (failoverMethod.Equals(FailoverMethodConstants.ROUND_ROBIN))
+ {
+ method = new FailoverRoundRobin(connectionInfo);
+ }
+ else
+ {
+ throw new NotImplementedException("Dynamic loading of FailoverMethods not yet implemented.");
+// try
+// {
+// Type[] constructorSpec = {ConnectionInfo.class};
+// Object [] params = {connectionInfo};
+//
+// method = (FailoverMethod) ClassLoader.getSystemClassLoader().
+// loadClass(failoverMethod).
+// getConstructor(constructorSpec).newInstance(params);
+// }
+// catch (Exception cnfe)
+// {
+// throw new IllegalArgumentException("Unknown failover method:" + failoverMethod);
+// }
+ }
+ }
+
+ if (method == null)
+ {
+ throw new ArgumentException("Unknown failover method specified.");
+ }
+
+ reset();
+
+ _methods[_currentMethod] = method;
+ }
+
+ public FailoverPolicy(FailoverMethod method) : this(method, 0)
+ {
+ }
+
+ public FailoverPolicy(FailoverMethod method, int retries)
+ {
+ _methodsRetries = retries;
+
+ reset();
+
+ _methods[_currentMethod] = method;
+ }
+
+ private void reset()
+ {
+ _currentMethod = 0;
+ _currentRetry = 0;
+ _timing = false;
+
+ }
+
+ public bool FailoverAllowed()
+ {
+ bool failoverAllowed;
+
+ if (_timing)
+ {
+ long now = CurrentTimeMilliseconds();
+
+ if ((now - _lastMethodTime) >= DEFAULT_METHOD_TIMEOUT)
+ {
+ _logger.Info("Failover method timeout");
+ _lastMethodTime = now;
+
+ if (!nextMethod())
+ {
+ return false;
+ }
+
+
+ }
+ else if ((now - _lastFailTime) >= DEFAULT_FAILOVER_TIMEOUT)
+ {
+ _logger.Info("Failover timeout");
+ return false;
+ }
+ else
+ {
+ _lastMethodTime = now;
+ }
+ }
+ else
+ {
+ _timing = true;
+ _lastMethodTime = CurrentTimeMilliseconds();
+ _lastFailTime = _lastMethodTime;
+ }
+
+
+ if (_methods[_currentMethod].failoverAllowed())
+ {
+ failoverAllowed = true;
+ }
+ else
+ {
+ if (_currentMethod < (_methods.Length - 1))
+ {
+ nextMethod();
+ _logger.Info("Changing method to " + _methods[_currentMethod].methodName());
+ return FailoverAllowed();
+ }
+ else
+ {
+ return cycleMethods();
+ }
+ }
+
+ return failoverAllowed;
+ }
+
+ private static long CurrentTimeMilliseconds()
+ {
+ return DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
+ }
+
+ private bool nextMethod()
+ {
+ if (_currentMethod < (_methods.Length - 1))
+ {
+ _currentMethod++;
+ _methods[_currentMethod].reset();
+ return true;
+ }
+ else
+ {
+ return cycleMethods();
+ }
+ }
+
+ private bool cycleMethods()
+ {
+ if (_currentRetry < _methodsRetries)
+ {
+ _currentRetry++;
+
+ _currentMethod = 0;
+
+ _logger.Info("Retrying methods starting with " + _methods[_currentMethod].methodName());
+ _methods[_currentMethod].reset();
+ return FailoverAllowed();
+ }
+ else
+ {
+ _logger.Debug("All failover methods exhausted");
+ return false;
+ }
+ }
+
+ /**
+ * Notification that connection was successful.
+ */
+ public void attainedConnection()
+ {
+ _currentRetry = 0;
+
+ _methods[_currentMethod].attainedConnection();
+
+ _timing = false;
+ }
+
+ public BrokerInfo GetCurrentBrokerInfo()
+ {
+ return _methods[_currentMethod].GetCurrentBrokerInfo();
+ }
+
+ public BrokerInfo GetNextBrokerInfo()
+ {
+ return _methods[_currentMethod].getNextBrokerDetails();
+ }
+
+ public void setBroker(BrokerInfo broker)
+ {
+ _methods[_currentMethod].setBroker(broker);
+ }
+
+ public void addMethod(FailoverMethod method)
+ {
+ int len = _methods.Length + 1;
+ FailoverMethod[] newMethods = new FailoverMethod[len];
+ _methods.CopyTo(newMethods, 0);
+// System.arraycopy(_methods, 0, newMethods, 0, _methods.length);
+ int index = len - 1;
+ newMethods[index] = method;
+ _methods = newMethods;
+ }
+
+ public void setMethodRetries(int retries)
+ {
+ _methodsRetries = retries;
+ }
+
+ public FailoverMethod getCurrentMethod()
+ {
+ if (_currentMethod >= 0 && _currentMethod < (_methods.Length - 1))
+ {
+ return _methods[_currentMethod];
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.Append("Failover Policy:\n");
+
+ if (FailoverAllowed())
+ {
+ sb.Append("Failover allowed\n");
+ }
+ else
+ {
+ sb.Append("Failover not allowed\n");
+ }
+
+ sb.Append("Failover policy methods\n");
+ for (int i = 0; i < _methods.Length; i++)
+ {
+
+ if (i == _currentMethod)
+ {
+ sb.Append(">");
+ }
+ sb.Append(_methods[i].ToString());
+ }
+
+ return sb.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs b/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs
new file mode 100644
index 0000000000..7db9ef32fa
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+
+namespace Qpid.Client.qms.failover
+{
+ public class FailoverMethodConstants
+ {
+ public const String ROUND_ROBIN = "roundrobin";
+ public const String RANDOM = "random";
+ }
+
+ public interface FailoverMethod
+ {
+ /**
+ * Reset the Failover to initial conditions
+ */
+ void reset();
+
+ /**
+ * Check if failover is possible for this method
+ *
+ * @return true if failover is allowed
+ */
+ bool failoverAllowed();
+
+ /**
+ * Notification to the Failover method that a connection has been attained.
+ */
+ void attainedConnection();
+
+ /**
+ * If there is no current BrokerInfo the null will be returned.
+ * @return The current BrokerDetail value to use
+ */
+ BrokerInfo GetCurrentBrokerInfo();
+
+ /**
+ * Move to the next BrokerInfo if one is available.
+ * @return the next BrokerDetail or null if there is none.
+ */
+ BrokerInfo getNextBrokerDetails();
+
+ /**
+ * Set the currently active broker to be the new value.
+ * @param broker The new BrokerDetail value
+ */
+ void setBroker(BrokerInfo broker);
+
+ /**
+ * Set the retries for this method
+ * @param maxRetries the maximum number of time to retry this Method
+ */
+ void setRetries(int maxRetries);
+
+ /**
+ * @return The name of this method for display purposes.
+ */
+ String methodName();
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs b/dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs
new file mode 100644
index 0000000000..c0e832ce21
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs
@@ -0,0 +1,255 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+using System.Text;
+using log4net;
+
+namespace Qpid.Client.qms.failover
+{
+ public class FailoverRoundRobin : FailoverMethod
+ {
+ private static readonly ILog _logger = LogManager.GetLogger(typeof(FailoverRoundRobin));
+
+ /** The default number of times to cycle through all servers */
+ public const int DEFAULT_CYCLE_RETRIES = 0;
+ /** The default number of times to retry each server */
+ public const int DEFAULT_SERVER_RETRIES = 0;
+
+ /**
+ * The index into the hostDetails array of the broker to which we are connected
+ */
+ private int _currentBrokerIndex = -1;
+
+ /**
+ * The number of times to retry connecting for each server
+ */
+ private int _serverRetries;
+
+ /**
+ * The current number of retry attempts made
+ */
+ private int _currentServerRetry;
+
+ /**
+ * The number of times to cycle through the servers
+ */
+ private int _cycleRetries;
+
+ /**
+ * The current number of cycles performed.
+ */
+ private int _currentCycleRetries;
+
+ /**
+ * Array of BrokerDetail used to make connections.
+ */
+ private ConnectionInfo _connectionDetails;
+
+ public FailoverRoundRobin(ConnectionInfo connectionDetails)
+ {
+ if (!(connectionDetails.getBrokerCount() > 0))
+ {
+ throw new ArgumentException("At least one broker details must be specified.");
+ }
+
+ _connectionDetails = connectionDetails;
+
+ //There is no current broker at startup so set it to -1.
+ _currentBrokerIndex = -1;
+
+ String cycleRetries = _connectionDetails.getFailoverOption(ConnectionUrlConstants.OPTIONS_FAILOVER_CYCLE);
+
+ if (cycleRetries != null)
+ {
+ try
+ {
+ _cycleRetries = int.Parse(cycleRetries);
+ }
+ catch (FormatException)
+ {
+ _cycleRetries = DEFAULT_CYCLE_RETRIES;
+ }
+ }
+
+ _currentCycleRetries = 0;
+
+ _serverRetries = 0;
+ _currentServerRetry = -1;
+ }
+
+ public void reset()
+ {
+ _currentBrokerIndex = 0;
+ _currentCycleRetries = 0;
+ _currentServerRetry = -1;
+ }
+
+ public bool failoverAllowed()
+ {
+ return ((_currentCycleRetries < _cycleRetries)
+ || (_currentServerRetry < _serverRetries)
+ || (_currentBrokerIndex < (_connectionDetails.getBrokerCount() - 1)));
+ }
+
+ public void attainedConnection()
+ {
+ _currentCycleRetries = 0;
+ _currentServerRetry = -1;
+ }
+
+ public BrokerInfo GetCurrentBrokerInfo()
+ {
+ if (_currentBrokerIndex == -1)
+ {
+ return null;
+ }
+
+ return _connectionDetails.GetBrokerDetails(_currentBrokerIndex);
+ }
+
+ public BrokerInfo getNextBrokerDetails()
+ {
+ if (_currentBrokerIndex == (_connectionDetails.getBrokerCount() - 1))
+ {
+ if (_currentServerRetry < _serverRetries)
+ {
+ if (_currentBrokerIndex == -1)
+ {
+ _currentBrokerIndex = 0;
+
+ setBroker(_connectionDetails.GetBrokerDetails(_currentBrokerIndex ));
+
+ _logger.Info("First Run using " + _connectionDetails.GetBrokerDetails(_currentBrokerIndex));
+ }
+ else
+ {
+ _logger.Info("Retrying " + _connectionDetails.GetBrokerDetails(_currentBrokerIndex));
+ }
+
+ _currentServerRetry++;
+ }
+ else
+ {
+ _currentCycleRetries++;
+ //failed to connect to first broker
+ _currentBrokerIndex = 0;
+
+ setBroker(_connectionDetails.GetBrokerDetails(_currentBrokerIndex ));
+
+ // This is zero rather than -1 as we are already retrieving the details.
+ _currentServerRetry = 0;
+ }
+ //else - should force client to stop as max retries has been reached.
+ }
+ else
+ {
+ if (_currentServerRetry < _serverRetries)
+ {
+ if (_currentBrokerIndex == -1)
+ {
+ _currentBrokerIndex = 0;
+
+ setBroker(_connectionDetails.GetBrokerDetails(_currentBrokerIndex ));
+
+ _logger.Info("First Run using " + _connectionDetails.GetBrokerDetails(_currentBrokerIndex));
+ }
+ else
+ {
+ _logger.Info("Retrying " + _connectionDetails.GetBrokerDetails(_currentBrokerIndex));
+ }
+ _currentServerRetry++;
+ }
+ else
+ {
+ _currentBrokerIndex++;
+
+ setBroker(_connectionDetails.GetBrokerDetails(_currentBrokerIndex ));
+ // This is zero rather than -1 as we are already retrieving the details.
+ _currentServerRetry = 0;
+ }
+ }
+
+ return _connectionDetails.GetBrokerDetails(_currentBrokerIndex);
+ }
+
+ public void setBroker(BrokerInfo broker)
+ {
+ _connectionDetails.AddBrokerInfo(broker);
+
+ int index = _connectionDetails.GetAllBrokerInfos().IndexOf(broker);
+
+ String serverRetries = broker.getOption(BrokerDetailsConstants.OPTIONS_RETRY);
+
+ if (serverRetries != null)
+ {
+ try
+ {
+ _serverRetries = int.Parse(serverRetries);
+ }
+ catch (FormatException)
+ {
+ _serverRetries = DEFAULT_SERVER_RETRIES;
+ }
+ }
+
+ _currentServerRetry = -1;
+ _currentBrokerIndex = index;
+ }
+
+ public void setRetries(int maxRetries)
+ {
+ _cycleRetries = maxRetries;
+ }
+
+ public String methodName()
+ {
+ return "Cycle Servers";
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.Append(GetType().Name).Append("\n");
+
+ sb.Append("Broker count: ").Append(_connectionDetails.getBrokerCount());
+ sb.Append("\ncurrent broker index: ").Append(_currentBrokerIndex);
+
+ sb.Append("\nCycle Retries: ").Append(_cycleRetries);
+ sb.Append("\nCurrent Cycle:").Append(_currentCycleRetries);
+ sb.Append("\nServer Retries:").Append(_serverRetries);
+ sb.Append("\nCurrent Retry:").Append(_currentServerRetry);
+ sb.Append("\n");
+
+ for(int i=0; i < _connectionDetails.getBrokerCount() ; i++)
+ {
+ if (i == _currentBrokerIndex)
+ {
+ sb.Append(">");
+ }
+ sb.Append(_connectionDetails.GetBrokerDetails(i));
+ sb.Append("\n");
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs b/dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs
new file mode 100644
index 0000000000..f077f75fdf
--- /dev/null
+++ b/dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs
@@ -0,0 +1,147 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+using System;
+
+namespace Qpid.Client.qms.failover
+{
+ public class FailoverSingleServer : FailoverMethod
+ {
+ /** The default number of times to rety a conection to this server */
+ public const int DEFAULT_SERVER_RETRIES = 1;
+
+ /**
+ * The details of the Single Server
+ */
+ private BrokerInfo _brokerDetail;
+
+ /**
+ * The number of times to retry connecting to the sever
+ */
+ private int _retries;
+
+ /**
+ * The current number of attempts made to the server
+ */
+ private int _currentRetries;
+
+
+ public FailoverSingleServer(ConnectionInfo connectionDetails)
+ {
+ if (connectionDetails.getBrokerCount() > 0)
+ {
+ setBroker(connectionDetails.GetBrokerDetails(0));
+ }
+ else
+ {
+ throw new ArgumentException("BrokerInfo details required for connection.");
+ }
+ }
+
+ public FailoverSingleServer(BrokerInfo brokerDetail)
+ {
+ setBroker(brokerDetail);
+ }
+
+ public void reset()
+ {
+ _currentRetries = -1;
+ }
+
+ public bool failoverAllowed()
+ {
+ return _currentRetries < _retries;
+ }
+
+ public void attainedConnection()
+ {
+ reset();
+ }
+
+ public BrokerInfo GetCurrentBrokerInfo()
+ {
+ return _brokerDetail;
+ }
+
+ public BrokerInfo getNextBrokerDetails()
+ {
+ if (_currentRetries == _retries)
+ {
+ return null;
+ }
+ else
+ {
+ if (_currentRetries < _retries)
+ {
+ _currentRetries ++;
+ }
+
+ return _brokerDetail;
+ }
+ }
+
+ public void setBroker(BrokerInfo broker)
+ {
+ if (broker == null)
+ {
+ throw new ArgumentException("BrokerInfo details cannot be null");
+ }
+ _brokerDetail = broker;
+
+ String retries = broker.getOption(BrokerDetailsConstants.OPTIONS_RETRY);
+ if (retries != null)
+ {
+ try
+ {
+ _retries = int.Parse(retries);
+ }
+ catch (FormatException nfe)
+ {
+ _retries = DEFAULT_SERVER_RETRIES;
+ }
+ }
+ else
+ {
+ _retries = DEFAULT_SERVER_RETRIES;
+ }
+
+ reset();
+ }
+
+ public void setRetries(int retries)
+ {
+ _retries = retries;
+ }
+
+ public String methodName()
+ {
+ return "Single Server";
+ }
+
+ public String toString()
+ {
+ return "SingleServer:\n"+
+ "Max Retries:"+_retries+
+ "\nCurrent Retry:"+_currentRetries+
+ "\n"+_brokerDetail+"\n";
+ }
+
+ }
+} \ No newline at end of file