예제 #1
0
            static void EndPipe(IRedisSocket rds, IEnumerable <PipelineCommand> cmds)
            {
                var err = new List <PipelineCommand>();
                var ms  = new MemoryStream();

                try
                {
                    var respWriter = new RespHelper.Resp3Writer(ms, rds.Encoding, rds.Protocol);
                    foreach (var cmd in cmds)
                    {
                        respWriter.WriteCommand(cmd.Command);
                    }

                    if (rds.IsConnected == false)
                    {
                        rds.Connect();
                    }
                    ms.Position = 0;
                    ms.CopyTo(rds.Stream);

                    foreach (var pc in cmds)
                    {
                        pc.RedisResult = rds.Read(pc.IsBytes);
                        pc.Result      = pc.Parse(pc.RedisResult);
                        if (pc.RedisResult.IsError)
                        {
                            err.Add(pc);
                        }
#if net40
#else
                        pc.TrySetResult(pc.Result, pc.RedisResult.IsError ? new RedisServerException(pc.RedisResult.SimpleError) : null);
#endif
                    }
                }
                finally
                {
                    ms.Close();
                    ms.Dispose();
                }

                if (err.Any())
                {
                    var sb = new StringBuilder();
                    for (var a = 0; a < err.Count; a++)
                    {
                        var cmd = err[a].Command;
                        if (a > 0)
                        {
                            sb.Append("\r\n");
                        }
                        sb.Append(err[a].RedisResult.SimpleError).Append(" {").Append(cmd.ToString()).Append("}");
                    }
                    throw new RedisServerException(sb.ToString());
                }
            }
예제 #2
0
        public RedisClientPool(string connectionString, Action <RedisClient> connected, RedisClient topOwner) : base(null)
        {
            _policy = new RedisClientPoolPolicy
            {
                _pool = this
            };
            _policy.Connected += (s, o) =>
            {
                var cli     = s as RedisClient;
                var rds     = cli.Adapter.GetRedisSocket(null);
                var adapter = cli.Adapter as RedisClient.SingleInsideAdapter;
                rds.Socket.ReceiveTimeout = (int)_policy._connectionStringBuilder.ReceiveTimeout.TotalMilliseconds;
                rds.Socket.SendTimeout    = (int)_policy._connectionStringBuilder.SendTimeout.TotalMilliseconds;
                rds.Encoding = _policy._connectionStringBuilder.Encoding;

                var cmds = new List <CommandPacket>();
                if (_policy._connectionStringBuilder.Protocol == RedisProtocol.RESP3)
                {
                    cmds.Add("HELLO"
                             .Input(3)
                             .InputIf(!string.IsNullOrWhiteSpace(_policy._connectionStringBuilder.User) && !string.IsNullOrWhiteSpace(_policy._connectionStringBuilder.Password), "AUTH", _policy._connectionStringBuilder.User, _policy._connectionStringBuilder.Password)
                             .InputIf(!string.IsNullOrWhiteSpace(_policy._connectionStringBuilder.ClientName), "SETNAME", _policy._connectionStringBuilder.ClientName)
                             .OnData(rt =>
                    {
                        rt.ThrowOrNothing();
                        rds.Protocol = RedisProtocol.RESP3;
                    }));
                }
                else if (!string.IsNullOrEmpty(_policy._connectionStringBuilder.User) && !string.IsNullOrEmpty(_policy._connectionStringBuilder.Password))
                {
                    cmds.Add("AUTH".SubCommand(null)
                             .InputIf(!string.IsNullOrWhiteSpace(_policy._connectionStringBuilder.User), _policy._connectionStringBuilder.User)
                             .Input(_policy._connectionStringBuilder.Password)
                             .OnData(rt =>
                    {
                        rt.ThrowOrNothing();
                    }));
                }
                else if (!string.IsNullOrEmpty(_policy._connectionStringBuilder.Password))
                {
                    cmds.Add("AUTH".SubCommand(null)
                             .Input(_policy._connectionStringBuilder.Password)
                             .OnData(rt =>
                    {
                        if (rt.IsError && rt.SimpleError != "ERR Client sent AUTH, but no password is set")
                        {
                            rt.ThrowOrNothing();
                        }
                    }));
                }

                if (_policy._connectionStringBuilder.Database > 0)
                {
                    cmds.Add("SELECT".Input(_policy._connectionStringBuilder.Database)
                             .OnData(rt =>
                    {
                        if (rt.IsError)
                        {
                            if (rt.SimpleError == "ERR SELECT is not allowed in cluster mode")
                            {
                                _policy._connectionStringBuilder.Database = 0;
                            }
                            else
                            {
                                rt.ThrowOrNothing();
                            }
                        }
                        (rds as IRedisSocketModify).SetDatabase(_policy._connectionStringBuilder.Database);
                    }));
                }

                if (!string.IsNullOrEmpty(_policy._connectionStringBuilder.ClientName) && _policy._connectionStringBuilder.Protocol == RedisProtocol.RESP2)
                {
                    cmds.Add("CLIENT".SubCommand("SETNAME").InputRaw(_policy._connectionStringBuilder.ClientName)
                             .OnData(rt =>
                    {
                        rt.ThrowOrNothing();
                    }));
                }

                cmds.Add("CLIENT".SubCommand("ID")
                         .OnData(rt =>
                {
                    if (rt.IsError)
                    {
                        return;                 //ERR Syntax error, try CLIENT (LIST | KILL | GETNAME | SETNAME | PAUSE | REPLY)
                    }
                    (rds as IRedisSocketModify).SetClientId(rt.ThrowOrValue <long>());
                }));

                using (var ms = new MemoryStream()) {
                    var writer = new RespHelper.Resp3Writer(ms, rds.Encoding, RedisProtocol.RESP2);
                    cmds.ForEach(cmd =>
                    {
                        cmd.WriteHost = rds.Host;
                        writer.WriteCommand(cmd);
                    });

                    ms.Position = 0;
                    ms.CopyTo(rds.Stream);
                    ms.Close();
                    ms.Dispose();
                }
                cmds.ForEach(cmd =>
                {
                    topOwner.LogCall(cmd, () =>
                    {
                        var rt = rds.Read(cmd);
                        return(rt.Value);
                    });
                });

                connected?.Invoke(cli);
                topOwner?.OnConnected(TopOwner, new ConnectedEventArgs(_policy._connectionStringBuilder.Host, this, cli));
                topOwner?.OnNotice(TopOwner, new NoticeEventArgs(NoticeType.Info, null, $"{_policy._connectionStringBuilder.Host.PadRight(21)} > Connected, ClientId: {rds.ClientId}, Database: {rds.Database}, Pool: {_freeObjects.Count}/{_allObjects.Count}", cli));
            };
            this.Policy              = _policy;
            this.TopOwner            = topOwner;
            _policy.ConnectionString = connectionString;
        }