/// <summary> /// Determines the next host. /// </summary> /// <returns>A <see cref="FailoverServer"/> object that represents the next available host.</returns> protected internal override FailoverServer GetNextHost() { if (Hosts == null || Hosts?.Count == 0) { throw new MySqlException(Resources.Replication_NoAvailableServer); } var currentServer = Hosts.Find(h => h.Host == _currentHost.Host && h.Port == _currentHost.Port); currentServer.IsActive = false; _hostIndex = Hosts.IndexOf(currentServer); if (Hosts.Count > 1) { _activeHost = _hostIndex == Hosts.Count - 1 ? Hosts[0] : Hosts[_hostIndex + 1]; _activeHost.IsActive = true; _currentHost = _activeHost; _hostIndex++; } else { _activeHost = _initialHost; } return(_activeHost); }
/// <summary> /// Sets the initial active host. /// </summary> protected internal override void SetInitialActiveServer() { if (Hosts == null || Hosts.Count == 0) { throw new MySqlException(Resources.Replication_NoAvailableServer); } _initialHost = Hosts[0]; Hosts[0].IsActive = true; _activeHost = Hosts[0]; _currentHost = _activeHost; }
/// <summary> /// Sets the initial active host. /// </summary> protected internal override void SetInitialActiveServer() { if (Hosts == null || Hosts.Count == 0) { throw new MySqlException(Resources.Replication_NoAvailableServer); } var initialIndex = rnd.Next(Hosts.Count); _initialHost = Hosts[initialIndex]; _initialHost.IsActive = true; _initialHost.Attempted = true; _activeHost = _initialHost; _currentHost = _activeHost; }
/// <summary> /// Determines the next host. /// </summary> /// <returns>A <see cref="FailoverServer"/> object that represents the next available host.</returns> protected internal override FailoverServer GetNextHost() { if (Hosts == null || Hosts?.Count == 0) { throw new MySqlException(Resources.Replication_NoAvailableServer); } Hosts.Find(h => h.Host == _currentHost.Host && h.Port == _currentHost.Port).IsActive = false; var notAttemptedHosts = Hosts.FindAll(h => h.Attempted == false); if (notAttemptedHosts.Count > 0) { _activeHost = notAttemptedHosts[rnd.Next(notAttemptedHosts.Count)]; _activeHost.IsActive = true; _activeHost.Attempted = true; _currentHost = _activeHost; } else { _activeHost = _initialHost; } return(_activeHost); }
/// <summary> /// Attempts to establish a connection to a host specified from the list. /// </summary> /// <param name="originalConnectionString">The original connection string set by the user.</param> /// <param name="connectionString">An out parameter that stores the updated connection string.</param> /// <param name="client">A <see cref="Client"/> object in case this is a pooling scenario.</param> /// <param name="isDefaultPort">A flag indicating if the default port is used in the connection.</param> /// <returns>An <see cref="InternalSession"/> instance if the connection was succesfully established, a <see cref="MySqlException"/> exception is thrown otherwise.</returns> internal static InternalSession AttemptConnectionXProtocol(string originalConnectionString, out string connectionString, bool isDefaultPort, Client client = null) { if (FailoverGroup == null || originalConnectionString == null) { connectionString = null; return(null); } if (client != null) { if (client.Hosts == null) { client.Hosts = FailoverGroup.Hosts; client.DemotedHosts = new ConcurrentQueue <FailoverServer>(); } else { FailoverGroup.Hosts = client.Hosts; } } FailoverServer currentHost = FailoverGroup.ActiveHost; FailoverServer initialHost = currentHost; MySqlXConnectionStringBuilder Settings = null; InternalSession internalSession = null; do { // Attempt to connect to each host by retrieving the next host based on the failover method being used. connectionString = originalConnectionString.Contains("server") ? originalConnectionString.Replace(originalConnectionString.Split(';').First(p => p.Contains("server")).Split('=')[1], currentHost.Host) : "server=" + currentHost.Host + ";" + originalConnectionString; if (currentHost != null && currentHost.Port != -1) { connectionString = connectionString.Replace(connectionString.Split(';').First(p => p.Contains("port")).Split('=')[1], currentHost.Port.ToString()); } Settings = new MySqlXConnectionStringBuilder(connectionString, isDefaultPort); try { internalSession = InternalSession.GetSession(Settings); } catch (Exception) { } if (internalSession != null) { break; } var tmpHost = currentHost; currentHost = FailoverGroup.GetNextHost(); if (client != null) { tmpHost.DemotedTime = DateTime.Now; client.Hosts.Remove(tmpHost); client.DemotedHosts.Enqueue(tmpHost); if (client.DemotedServersTimer == null) { client.DemotedServersTimer = new Timer(new TimerCallback(client.ReleaseDemotedHosts), null, Client.DEMOTED_TIMEOUT, Timeout.Infinite); } } }while (!currentHost.Equals(initialHost)); // All connection attempts failed. if (internalSession == null) { throw new MySqlException(Resources.UnableToConnectToHost); } return(internalSession); }
/// <summary> /// Attempts to establish a connection to a host specified from the list. /// </summary> /// <param name="connection">MySqlConnection object where the new driver will be assigned</param> /// <param name="originalConnectionString">The original connection string set by the user.</param> /// <param name="connectionString">An out parameter that stores the updated connection string.</param> /// <param name="mySqlPoolManager">A <see cref="MySqlPoolManager"> in case this is a pooling scenario."/></param> internal static void AttemptConnection(MySqlConnection connection, string originalConnectionString, out string connectionString, bool mySqlPoolManager = false) { if (mySqlPoolManager) { if (MySqlPoolManager.Hosts == null) { MySqlPoolManager.Hosts = FailoverGroup.Hosts; MySqlPoolManager.DemotedHosts = new ConcurrentQueue <FailoverServer>(); } else { FailoverGroup.Hosts = MySqlPoolManager.Hosts; } } FailoverServer currentHost = FailoverGroup.ActiveHost; FailoverServer initialHost = currentHost; Driver driver = null; do { // Attempt to connect to each host by retrieving the next host based on the failover method being used MySqlConnectionStringBuilder msb; connectionString = "server=" + currentHost.Host + ";" + originalConnectionString.Substring(originalConnectionString.IndexOf(';') + 1); if (currentHost != null && currentHost.Port != -1) { connectionString += ";port=" + currentHost.Port; } msb = new MySqlConnectionStringBuilder(connectionString); if ((FailoverGroup.Hosts.Count == 1 && !mySqlPoolManager) || (mySqlPoolManager && MySqlPoolManager.Hosts.Count == 1 && MySqlPoolManager.DemotedHosts.IsEmpty)) { return; } try { driver = Driver.Create(msb); if (!mySqlPoolManager) { connection.driver = driver; } break; } catch (Exception) { } var tmpHost = currentHost; currentHost = FailoverGroup.GetNextHost(); if (mySqlPoolManager) { tmpHost.DemotedTime = DateTime.Now; MySqlPoolManager.Hosts.Remove(tmpHost); MySqlPoolManager.DemotedHosts.Enqueue(tmpHost); if (MySqlPoolManager.DemotedServersTimer == null) { MySqlPoolManager.DemotedServersTimer = new Timer(new TimerCallback(MySqlPoolManager.ReleaseDemotedHosts), null, MySqlPoolManager.DEMOTED_TIMEOUT, Timeout.Infinite); } } } while (!currentHost.Equals(initialHost)); if (driver == null) { throw new MySqlException(Resources.UnableToConnectToHost); } }