private ServerEndPoint FindSlave(ServerEndPoint endpoint, RedisCommand command)
        {
            if (endpoint.IsSlave && endpoint.IsSelectable(command))
            {
                return(endpoint);
            }

            var slaves = endpoint.Slaves;

            for (int i = 0; i < slaves.Length; i++)
            {
                endpoint = slaves[i];
                if (endpoint.IsSlave && endpoint.IsSelectable(command))
                {
                    return(endpoint);
                }
            }
            return(null);
        }
        private ServerEndPoint FindSlave(ServerEndPoint endpoint, RedisCommand command, bool allowDisconnected = false)
        {
            if (endpoint.IsSlave && endpoint.IsSelectable(command, allowDisconnected))
            {
                return(endpoint);
            }

            var  slaves      = endpoint.Slaves;
            var  len         = slaves.Length;
            uint startOffset = len <= 1 ? 0 : endpoint.NextReplicaOffset();

            for (int i = 0; i < len; i++)
            {
                endpoint = slaves[(int)(((uint)i + startOffset) % len)];
                if (endpoint.IsSlave && endpoint.IsSelectable(command, allowDisconnected))
                {
                    return(endpoint);
                }
            }
            return(null);
        }
        private ServerEndPoint FindMaster(ServerEndPoint endpoint, RedisCommand command)
        {
            int max = 5;

            do
            {
                if (!endpoint.IsSlave && endpoint.IsSelectable(command))
                {
                    return(endpoint);
                }

                endpoint = endpoint.Master;
            } while (endpoint != null && --max != 0);
            return(null);
        }
        private ServerEndPoint Select(int slot, RedisCommand command, CommandFlags flags)
        {
            flags = Message.GetMasterSlaveFlags(flags); // only intersted in master/slave preferences

            ServerEndPoint[] arr;
            if (slot == NoSlot || (arr = map) == null)
            {
                return(Any(command, flags));
            }

            ServerEndPoint endpoint = arr[slot], testing;

            // but: ^^^ is the MASTER slots; if we want a slave, we need to do some thinking

            if (endpoint != null)
            {
                switch (flags)
                {
                case CommandFlags.DemandSlave:
                    return(FindSlave(endpoint, command) ?? Any(command, flags));

                case CommandFlags.PreferSlave:
                    testing = FindSlave(endpoint, command);
                    if (testing != null)
                    {
                        return(testing);
                    }
                    break;

                case CommandFlags.DemandMaster:
                    return(FindMaster(endpoint, command) ?? Any(command, flags));

                case CommandFlags.PreferMaster:
                    testing = FindMaster(endpoint, command);
                    if (testing != null)
                    {
                        return(testing);
                    }
                    break;
                }
                if (endpoint.IsSelectable(command))
                {
                    return(endpoint);
                }
            }
            return(Any(command, flags));
        }
        private ServerEndPoint FindSlave(ServerEndPoint endpoint, RedisCommand command)
        {
            if (endpoint.IsSlave && endpoint.IsSelectable(command)) return endpoint;

            var slaves = endpoint.Slaves;
            for (int i = 0; i < slaves.Length; i++)
            {
                endpoint = slaves[i];
                if (endpoint.IsSlave && endpoint.IsSelectable(command)) return endpoint;
            }
            return null;
        }
        private ServerEndPoint FindMaster(ServerEndPoint endpoint, RedisCommand command)
        {
            int max = 5;
            do
            {
                if (!endpoint.IsSlave && endpoint.IsSelectable(command)) return endpoint;

                endpoint = endpoint.Master;
            } while (endpoint != null && --max != 0);
            return null;
        }
        public bool TryResend(int hashSlot, Message message, EndPoint endpoint, bool isMoved)
        {
            try
            {
                if (serverType == ServerType.Standalone || hashSlot < 0 || hashSlot >= RedisClusterSlotCount)
                {
                    return(false);
                }

                ServerEndPoint server = multiplexer.GetServerEndPoint(endpoint);
                if (server != null)
                {
                    bool retry = false;
                    if ((message.Flags & CommandFlags.NoRedirect) == 0)
                    {
                        message.SetAsking(!isMoved);
                        message.SetNoRedirect(); // once is enough

                        // note that everything so far is talking about MASTER nodes; we might be
                        // wanting a SLAVE, so we'll check
                        ServerEndPoint resendVia = null;
                        var            command   = message.Command;
                        switch (Message.GetMasterSlaveFlags(message.Flags))
                        {
                        case CommandFlags.DemandMaster:
                            resendVia = server.IsSelectable(command) ? null : server;
                            break;

                        case CommandFlags.PreferMaster:
                            resendVia = server.IsSelectable(command) ? FindSlave(server, command) : server;
                            break;

                        case CommandFlags.PreferSlave:
                            resendVia = FindSlave(server, command) ?? (server.IsSelectable(command) ? null : server);
                            break;

                        case CommandFlags.DemandSlave:
                            resendVia = FindSlave(server, command);
                            break;
                        }
                        if (resendVia == null)
                        {
                            multiplexer.Trace("Unable to resend to " + endpoint);
                        }
                        else
                        {
                            message.PrepareToResend(resendVia, isMoved);
                            retry = resendVia.TryEnqueue(message);
                        }
                    }

                    if (isMoved) // update map; note we can still update the map even if we aren't actually goint to resend
                    {
                        var arr       = MapForMutation();
                        var oldServer = arr[hashSlot];
                        arr[hashSlot] = server;
                        if (oldServer != server)
                        {
                            multiplexer.OnHashSlotMoved(hashSlot, oldServer == null ? null : oldServer.EndPoint, endpoint);
                        }
                    }

                    return(retry);
                }
                return(false);
            }
            catch
            {
                return(false);
            }
        }