/// <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;
        }
示例#3
0
        /// <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;
        }
示例#4
0
        /// <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);
            }
        }