예제 #1
0
        protected virtual void Dispose(bool disposing)
        {
            if (Interlocked.Increment(ref disposeAttempts) > 1)
            {
                return;
            }

            if (disposing)
            {
                // get rid of managed resources
            }

            try
            {
                // get rid of unmanaged resources
                for (var i = 0; i < writeClients.Length; i++)
                {
                    Dispose(writeClients[i]);
                }
                for (var i = 0; i < readClients.Length; i++)
                {
                    Dispose(readClients[i]);
                }
            }
            catch (Exception ex)
            {
                Log.Error("Error when trying to dispose of PooledRedisClientManager", ex);
            }

            RedisState.DisposeAllDeactivatedClients();
        }
예제 #2
0
        public void FailoverTo(params string[] readWriteHosts)
        {
            Interlocked.Increment(ref RedisState.TotalFailovers);

            lock (clients)
            {
                for (var i = 0; i < clients.Length; i++)
                {
                    var redis = clients[i];
                    if (redis != null)
                    {
                        RedisState.DeactivateClient(redis);
                    }

                    clients[i] = null;
                }
                RedisResolver.ResetMasters(readWriteHosts);
            }

            if (this.OnFailover != null)
            {
                foreach (var callback in OnFailover)
                {
                    try
                    {
                        callback(this);
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Error firing OnFailover callback(): ", ex);
                    }
                }
            }
        }
예제 #3
0
        public void FailoverTo(IEnumerable <string> readWriteHosts, IEnumerable <string> readOnlyHosts)
        {
            Interlocked.Increment(ref RedisState.TotalFailovers);

            lock (readClients)
            {
                for (var i = 0; i < readClients.Length; i++)
                {
                    var redis = readClients[i];
                    if (redis != null)
                    {
                        RedisState.DeactivateClient(redis);
                    }

                    readClients[i] = null;
                }
                RedisResolver.ResetSlaves(readOnlyHosts);
            }

            lock (writeClients)
            {
                for (var i = 0; i < writeClients.Length; i++)
                {
                    var redis = writeClients[i];
                    if (redis != null)
                    {
                        RedisState.DeactivateClient(redis);
                    }

                    writeClients[i] = null;
                }
                RedisResolver.ResetMasters(readWriteHosts);
            }

            if (this.OnFailover != null)
            {
                foreach (var callback in OnFailover)
                {
                    try
                    {
                        callback(this);
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Error firing OnFailover callback(): ", ex);
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Returns a ReadOnly client using the hosts defined in ReadOnlyHosts.
        /// </summary>
        /// <returns></returns>
        public virtual IRedisClient GetReadOnlyClient()
        {
            try
            {
                var poolTimedOut      = false;
                var inactivePoolIndex = -1;
                lock (readClients)
                {
                    AssertValidReadOnlyPool();

                    RedisClient inActiveClient;
                    while ((inactivePoolIndex = GetInActiveReadClient(out inActiveClient)) == -1)
                    {
                        if (PoolTimeout.HasValue)
                        {
                            // wait for a connection, break out if made to wait too long
                            if (!Monitor.Wait(readClients, PoolTimeout.Value))
                            {
                                poolTimedOut = true;
                                break;
                            }
                        }
                        else
                        {
                            Monitor.Wait(readClients, RecheckPoolAfterMs);
                        }
                    }

                    //inActiveClient != null only for Valid InActive Clients
                    if (inActiveClient != null)
                    {
                        ReadPoolIndex++;
                        inActiveClient.Active = true;

                        InitClient(inActiveClient);

                        return(inActiveClient);
                    }
                }

                if (poolTimedOut)
                {
                    throw new TimeoutException(PoolTimeoutError);
                }

                //Reaches here when there's no Valid InActive Clients
                try
                {
                    //inactivePoolIndex = index of reservedSlot || index of invalid client
                    var existingClient = readClients[inactivePoolIndex];
                    if (existingClient != null && existingClient != reservedSlot && existingClient.HadExceptions)
                    {
                        RedisState.DeactivateClient(existingClient);
                    }

                    var newClient = InitNewClient(RedisResolver.CreateSlaveClient(inactivePoolIndex));

                    //Put all blocking I/O or potential Exceptions before lock
                    lock (readClients)
                    {
                        //If existingClient at inactivePoolIndex changed (failover) return new client outside of pool
                        if (readClients[inactivePoolIndex] != existingClient)
                        {
                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug("readClients[inactivePoolIndex] != existingClient: {0}".Fmt(readClients[inactivePoolIndex]));
                            }

                            Interlocked.Increment(ref RedisState.TotalClientsCreatedOutsidePool);

                            //Don't handle callbacks for new client outside pool
                            newClient.ClientManager = null;
                            return(newClient); //return client outside of pool
                        }

                        ReadPoolIndex++;
                        readClients[inactivePoolIndex] = newClient;
                        return(newClient);
                    }
                }
                catch
                {
                    //Revert free-slot for any I/O exceptions that can throw
                    lock (readClients)
                    {
                        readClients[inactivePoolIndex] = null; //free slot
                    }
                    throw;
                }
            }
            finally
            {
                RedisState.DisposeExpiredClients();
            }
        }
예제 #5
0
        /// <summary>
        /// Returns a Read/Write client (The default) using the hosts defined in ReadWriteHosts
        /// </summary>
        /// <returns></returns>
        public IRedisClient GetClient()
        {
            try
            {
                var poolTimedOut      = false;
                var inactivePoolIndex = -1;
                lock (writeClients)
                {
                    AssertValidReadWritePool();

                    RedisClient inActiveClient;
                    while ((inactivePoolIndex = GetInActiveWriteClient(out inActiveClient)) == -1)
                    {
                        if (PoolTimeout.HasValue)
                        {
                            // wait for a connection, cry out if made to wait too long
                            if (!Monitor.Wait(writeClients, PoolTimeout.Value))
                            {
                                poolTimedOut = true;
                                break;
                            }
                        }
                        else
                        {
                            Monitor.Wait(writeClients, RecheckPoolAfterMs);
                        }
                    }

                    //inActiveClient != null only for Valid InActive Clients
                    if (inActiveClient != null)
                    {
                        WritePoolIndex++;
                        inActiveClient.Active = true;

                        InitClient(inActiveClient);

                        return(inActiveClient);
                    }
                }

                if (poolTimedOut)
                {
                    throw new TimeoutException(PoolTimeoutError);
                }

                //Reaches here when there's no Valid InActive Clients
                try
                {
                    //inactivePoolIndex = index of reservedSlot || index of invalid client
                    var existingClient = writeClients[inactivePoolIndex];
                    if (existingClient != null && existingClient != reservedSlot && existingClient.HadExceptions)
                    {
                        RedisState.DeactivateClient(existingClient);
                    }

                    var newClient = InitNewClient(RedisResolver.CreateMasterClient(inactivePoolIndex));

                    //Put all blocking I/O or potential Exceptions before lock
                    lock (writeClients)
                    {
                        //If existingClient at inactivePoolIndex changed (failover) return new client outside of pool
                        if (writeClients[inactivePoolIndex] != existingClient)
                        {
                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug("writeClients[inactivePoolIndex] != existingClient: {0}".Fmt(writeClients[inactivePoolIndex]));
                            }

                            return(newClient); //return client outside of pool
                        }

                        WritePoolIndex++;
                        writeClients[inactivePoolIndex] = newClient;
                        return(newClient);
                    }
                }
                catch
                {
                    //Revert free-slot for any I/O exceptions that can throw (before lock)
                    lock (writeClients)
                    {
                        writeClients[inactivePoolIndex] = null; //free slot
                    }
                    throw;
                }
            }
            finally
            {
                RedisState.DisposeExpiredClients();
            }
        }
예제 #6
0
        /// <summary>
        /// Returns a Read/Write client (The default) using the hosts defined in ReadWriteHosts
        /// </summary>
        /// <returns></returns>
        public IRedisClient GetClient()
        {
            try
            {
                var inactivePoolIndex = -1;
                lock (clients)
                {
                    AssertValidPool();

                    RedisClient inActiveClient;
                    //-1 when no available clients otherwise index of reservedSlot or existing Client
                    inactivePoolIndex = GetInActiveClient(out inActiveClient);

                    //inActiveClient != null only for Valid InActive Clients
                    if (inActiveClient != null)
                    {
                        poolIndex++;
                        inActiveClient.Active = true;

                        return(inActiveClient);
                    }
                }

                //Reaches here when there's no Valid InActive Clients
                try
                {
                    //inactivePoolIndex == -1 || index of reservedSlot || index of invalid client
                    var existingClient = inactivePoolIndex >= 0 && inactivePoolIndex < clients.Length
                        ? clients[inactivePoolIndex]
                        : null;

                    if (existingClient != null && existingClient != reservedSlot && existingClient.HadExceptions)
                    {
                        RedisState.DeactivateClient(existingClient);
                    }

                    var newClient = InitNewClient(RedisResolver.CreateMasterClient(Math.Max(inactivePoolIndex, 0)));

                    //Put all blocking I/O or potential Exceptions before lock
                    lock (clients)
                    {
                        //Create new client outside of pool when max pool size exceeded
                        //Reverting free-slot not needed when -1 since slwo wasn't reserved or
                        //when existingClient changed (failover) since no longer reserver
                        var stillReserved = inactivePoolIndex >= 0 && inactivePoolIndex < clients.Length &&
                                            clients[inactivePoolIndex] == existingClient;
                        if (inactivePoolIndex == -1 || !stillReserved)
                        {
                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug("clients[inactivePoolIndex] != existingClient: {0}".Fmt(!stillReserved ? "!stillReserved" : "-1"));
                            }

                            Interlocked.Increment(ref RedisState.TotalClientsCreatedOutsidePool);

                            //Don't handle callbacks for new client outside pool
                            newClient.ClientManager = null;
                            return(newClient);
                        }

                        poolIndex++;
                        clients[inactivePoolIndex] = newClient;
                        return(newClient);
                    }
                }
                catch
                {
                    //Revert free-slot for any I/O exceptions that can throw (before lock)
                    lock (clients)
                    {
                        if (inactivePoolIndex >= 0 && inactivePoolIndex < clients.Length)
                        {
                            clients[inactivePoolIndex] = null;
                        }
                    }
                    throw;
                }
            }
            finally
            {
                RedisState.DisposeExpiredClients();
            }
        }