diff options
Diffstat (limited to 'qpid/dotnet/Qpid.Client/qms/failover')
3 files changed, 480 insertions, 0 deletions
diff --git a/qpid/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs b/qpid/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs new file mode 100644 index 0000000000..f32b275e84 --- /dev/null +++ b/qpid/dotnet/Qpid.Client/qms/failover/FailoverMethod.cs @@ -0,0 +1,78 @@ +/* + * + * 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 Apache.Qpid.Client.Qms.Failover +{ + public class FailoverMethodConstants + { + public const String ROUND_ROBIN = "roundrobin"; + public const String RANDOM = "random"; + } + + public interface IFailoverMethod + { + /// <summary> + /// The name of this method for display purposes. + /// </summary> + String MethodName { get; } + + /// <summary> + /// Reset the Failover to initial conditions + /// </summary> + void Reset(); + + /// <summary> + /// Check if failover is possible for this method + /// </summary> + /// <returns>true if failover is allowed</returns> + bool FailoverAllowed(); + + /// <summary> + /// Notification to the Failover method that a connection has been attained. + /// </summary> + void AttainedConnection(); + + /// <summary> + /// If there is no current BrokerInfo the null will be returned. + /// </summary> + /// <returns>The current BrokerDetail value to use</returns> + IBrokerInfo GetCurrentBrokerInfo(); + + /// <summary> + /// Move to the next BrokerInfo if one is available. + /// </summary> + /// <returns>the next BrokerDetail or null if there is none.</returns> + IBrokerInfo GetNextBrokerDetails(); + + /// <summary> + /// Set the currently active broker to be the new value. + /// </summary> + /// <param name="broker">The new BrokerDetail value</param> + void SetBroker(IBrokerInfo broker); + + /// <summary> + /// Set the retries for this method + /// </summary> + /// <param name="maxRetries">the maximum number of time to retry this Method</param> + void SetRetries(int maxRetries); + } +} diff --git a/qpid/dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs b/qpid/dotnet/Qpid.Client/qms/failover/FailoverRoundRobin.cs new file mode 100644 index 0000000000..8103940fb4 --- /dev/null +++ b/qpid/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 Apache.Qpid.Client.Qms.Failover +{ + public class FailoverRoundRobin : IFailoverMethod + { + 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 IConnectionInfo _connectionDetails; + + public FailoverRoundRobin(IConnectionInfo connectionDetails) + { + if (!(connectionDetails.BrokerCount > 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.BrokerCount - 1))); + } + + public void AttainedConnection() + { + _currentCycleRetries = 0; + _currentServerRetry = -1; + } + + public IBrokerInfo GetCurrentBrokerInfo() + { + if (_currentBrokerIndex == -1) + { + return null; + } + + return _connectionDetails.GetBrokerInfo(_currentBrokerIndex); + } + + public IBrokerInfo GetNextBrokerDetails() + { + if (_currentBrokerIndex == (_connectionDetails.BrokerCount - 1)) + { + if (_currentServerRetry < _serverRetries) + { + if (_currentBrokerIndex == -1) + { + _currentBrokerIndex = 0; + + SetBroker(_connectionDetails.GetBrokerInfo(_currentBrokerIndex )); + + _logger.Info("First Run using " + _connectionDetails.GetBrokerInfo(_currentBrokerIndex)); + } + else + { + _logger.Info("Retrying " + _connectionDetails.GetBrokerInfo(_currentBrokerIndex)); + } + + _currentServerRetry++; + } + else + { + _currentCycleRetries++; + //failed to connect to first broker + _currentBrokerIndex = 0; + + SetBroker(_connectionDetails.GetBrokerInfo(_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.GetBrokerInfo(_currentBrokerIndex )); + + _logger.Info("First Run using " + _connectionDetails.GetBrokerInfo(_currentBrokerIndex)); + } + else + { + _logger.Info("Retrying " + _connectionDetails.GetBrokerInfo(_currentBrokerIndex)); + } + _currentServerRetry++; + } + else + { + _currentBrokerIndex++; + + SetBroker(_connectionDetails.GetBrokerInfo(_currentBrokerIndex )); + // This is zero rather than -1 as we are already retrieving the details. + _currentServerRetry = 0; + } + } + + return _connectionDetails.GetBrokerInfo(_currentBrokerIndex); + } + + public void SetBroker(IBrokerInfo broker) + { + _connectionDetails.AddBrokerInfo(broker); + + int index = _connectionDetails.GetAllBrokerInfos().IndexOf(broker); + + String serverRetries = broker.GetOption(BrokerInfoConstants.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 + { + get { return "Cycle Servers"; } + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + sb.Append(GetType().Name).Append("\n"); + + sb.Append("Broker count: ").Append(_connectionDetails.BrokerCount); + 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.BrokerCount ; i++) + { + if (i == _currentBrokerIndex) + { + sb.Append(">"); + } + sb.Append(_connectionDetails.GetBrokerInfo(i)); + sb.Append("\n"); + } + + return sb.ToString(); + } + } +} diff --git a/qpid/dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs b/qpid/dotnet/Qpid.Client/qms/failover/FailoverSingleServer.cs new file mode 100644 index 0000000000..5e502b897e --- /dev/null +++ b/qpid/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 Apache.Qpid.Client.Qms.Failover +{ + public class FailoverSingleServer : IFailoverMethod + { + /** 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 IBrokerInfo _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(IConnectionInfo connectionDetails) + { + if (connectionDetails.BrokerCount > 0) + { + SetBroker(connectionDetails.GetBrokerInfo(0)); + } + else + { + throw new ArgumentException("BrokerInfo details required for connection."); + } + } + + public FailoverSingleServer(IBrokerInfo brokerDetail) + { + SetBroker(brokerDetail); + } + + public void Reset() + { + _currentRetries = -1; + } + + public bool FailoverAllowed() + { + return _currentRetries < _retries; + } + + public void AttainedConnection() + { + Reset(); + } + + public IBrokerInfo GetCurrentBrokerInfo() + { + return _brokerDetail; + } + + public IBrokerInfo GetNextBrokerDetails() + { + if (_currentRetries == _retries) + { + return null; + } + else + { + if (_currentRetries < _retries) + { + _currentRetries ++; + } + + return _brokerDetail; + } + } + + public void SetBroker(IBrokerInfo broker) + { + if (broker == null) + { + throw new ArgumentException("BrokerInfo details cannot be null"); + } + _brokerDetail = broker; + + String retries = broker.GetOption(BrokerInfoConstants.OPTIONS_RETRY); + if (retries != null) + { + try + { + _retries = int.Parse(retries); + } + catch (FormatException) + { + _retries = DEFAULT_SERVER_RETRIES; + } + } + else + { + _retries = DEFAULT_SERVER_RETRIES; + } + + Reset(); + } + + public void SetRetries(int retries) + { + _retries = retries; + } + + public String MethodName + { + get { return "Single Server"; } + } + + public String toString() + { + return "SingleServer:\n"+ + "Max Retries:"+_retries+ + "\nCurrent Retry:"+_currentRetries+ + "\n"+_brokerDetail+"\n"; + } + + } +} |