示例#1
0
        protected TValue Call <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
        {
            _redisSocket.Write(cmd);
            var rt = _redisSocket.Read(false);

            return(parse(rt));
        }
示例#2
0
 void StartRead()
 {
     new Thread(() =>
     {
         var timer = new Timer(state => { try { WriteInQueue("PING"); } catch { } }, null, 10000, 10000);
         while (_runing)
         {
             RedisResult rt;
             try
             {
                 rt = _rds.Read(false);
             }
             catch (Exception ioex)
             {
                 ClearAndTrySetExpcetion(ioex);
                 Interlocked.Exchange(ref _exception, ioex);
                 continue;
             }
             if (_writeQueue.TryDequeue(out var witem))
             {
                 witem.TaskCompletionSource.TrySetResult(rt);
             }
             else
             {
                 ClearAndTrySetExpcetion(new RedisClientException($"AsyncRedisSocket: Message sequence error"));
             }
         }
         timer.Dispose();
     }).Start();
 }
示例#3
0
 public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     TryMulti();
     return(TopOwner.LogCall(cmd, () =>
     {
         _redisSocket.Write(cmd);
         _redisSocket.Read(cmd._flagReadbytes).ThrowOrValue <TValue>(useDefaultValue: true);
         _commands.Add(new TransactionCommand
         {
             Command = cmd,
             Parse = obj => parse(new RedisResult(obj, true, RedisMessageType.SimpleString)
             {
                 Encoding = _redisSocket.Encoding
             })
         });
         return default(TValue);
     }));
 }
            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());
                }
            }
示例#5
0
 public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     return(TopOwner.LogCall(cmd, () =>
     {
         _redisSocket.Write(cmd);
         var rt = _redisSocket.Read(cmd);
         if (cmd._command == "QUIT")
         {
             _redisSocket.ReleaseSocket();
         }
         return parse(rt);
     }));
 }
示例#6
0
 public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     return(TopOwner.LogCall(cmd, () =>
     {
         _redisSocket.Write(cmd);
         var rt = _redisSocket.Read(cmd._flagReadbytes);
         if (cmd._command == "QUIT")
         {
             _redisSocket.ReleaseSocket();
         }
         rt.IsErrorThrow = TopOwner._isThrowRedisSimpleError;
         return parse(rt);
     }));
 }
示例#7
0
        WriteAsyncInfo WriteInQueue(CommandPacket cmd)
        {
            var ret = new WriteAsyncInfo {
                Command = cmd
            };

            if (_rds.ClientReply == ClientReplyType.on)
            {
                ret.TaskCompletionSource = new TaskCompletionSource <RedisResult>();
            }
            var isnew = false;

            lock (_writeAsyncLock)
            {
                _writeQueue.Enqueue(ret);
                if (_isfirst == false)
                {
                    isnew = _isfirst = true;
                }
                if (_bufferStream == null)
                {
                    _bufferStream = new MemoryStream();
                }
                new RespHelper.Resp3Writer(_bufferStream, _rds.Encoding, _rds.Protocol).WriteCommand(cmd);
            }
            if (isnew)
            {
                //Thread.CurrentThread.Join(TimeSpan.FromTicks(1000));
                try
                {
                    if (_rds.IsConnected == false)
                    {
                        _rds.Connect();
                    }
                }
                catch (Exception ioex)
                {
                    lock (_writeAsyncLock)
                    {
                        while (_writeQueue.TryDequeue(out var wq))
                        {
                            wq.TaskCompletionSource?.TrySetException(ioex);
                        }
                        _bufferStream.Close();
                        _bufferStream.Dispose();
                        _bufferStream = null;
                    }
                    _rds.ReleaseSocket();
                    _end(_rds, ioex);
                    throw ioex;
                }

                for (var a = 0; a < 100; a++)
                {
                    var cou = _writeQueue.Count;
                    if (cou > 100)
                    {
                        break;
                    }
                }
                var localQueue = new Queue <WriteAsyncInfo>();
                long localQueueThrowException(Exception exception)
                {
                    long counter = 0;

                    while (localQueue.Any())
                    {
                        var witem = localQueue.Dequeue();
                        if (exception != null)
                        {
                            witem.TaskCompletionSource?.TrySetException(exception);
                        }
                        else
                        {
                            witem.TaskCompletionSource?.TrySetCanceled();
                        }
                        counter = Interlocked.Decrement(ref _writeCounter);
                    }
                    return(counter);
                }

                var iswait = _writeCounter > 1;
                if (iswait)
                {
                    Thread.CurrentThread.Join(10);
                }
                _begin();
                while (true)
                {
                    if (_writeQueue.Any() == false)
                    {
                        Thread.CurrentThread.Join(10);
                        continue;
                    }
                    lock (_writeAsyncLock)
                    {
                        while (_writeQueue.TryDequeue(out var wq))
                        {
                            localQueue.Enqueue(wq);
                        }
                        _bufferStream.Position = 0;
                        try
                        {
                            _bufferStream.CopyTo(_rds.Stream);
                            _bufferStream.Close();
                            _bufferStream.Dispose();
                            _bufferStream = null;
                        }
                        catch (Exception ioex)
                        {
                            localQueueThrowException(ioex);
                            _bufferStream.Close();
                            _bufferStream.Dispose();
                            _bufferStream = null;
                            _rds.ReleaseSocket();
                            _end(_rds, ioex);
                            throw ioex;
                        }
                    }
                    long        counter = 0;
                    RedisResult rt      = null;
                    //sb.AppendLine($"{name} 线程{Thread.CurrentThread.ManagedThreadId}:合并读取 {localQueue.Count} 个命令 total:{sw.ElapsedMilliseconds} ms");
                    while (localQueue.Any())
                    {
                        var witem = localQueue.Dequeue();
                        try
                        {
                            rt = _rds.Read(false);
                        }
                        catch (Exception ioex)
                        {
                            localQueueThrowException(ioex);
                            _rds.ReleaseSocket();
                            _end(_rds, ioex);
                            throw ioex;
                        }
                        witem.TaskCompletionSource.TrySetResult(rt);
                        counter = Interlocked.Decrement(ref _writeCounter);
                    }
                    if (counter == 0 && _finish())
                    {
                        break;
                    }
                    Thread.CurrentThread.Join(1);
                    //sb.AppendLine($"{name} 线程{Thread.CurrentThread.ManagedThreadId}:等待 1ms + {_writeQueue.Count} total:{sw.ElapsedMilliseconds} ms");
                }
                //sb.AppendLine($"{name} 线程{Thread.CurrentThread.ManagedThreadId}:退出 total:{sw.ElapsedMilliseconds} ms");
                _end(_rds, null);
            }
            return(ret);
        }
示例#8
0
            internal IDisposable Subscribe(bool psub, string[] channels, Action <string, string, object> handler)
            {
                if (_stoped)
                {
                    return(new PubSubSubscribeDisposable(this, null));
                }
                channels = channels?.Distinct().Where(a => !string.IsNullOrEmpty(a)).ToArray(); //In case of external modification
                if (channels?.Any() != true)
                {
                    return(new PubSubSubscribeDisposable(this, null));
                }

                var id      = Guid.NewGuid();
                var time    = DateTime.Now;
                var regkeys = channels.Select(a => psub ? $"{_psub_regkey_prefix}{a}" : a).ToArray();

                for (var a = 0; a < regkeys.Length; a++)
                {
                    ConcurrentDictionary <Guid, RegisterInfo> dict = null;
                    lock (_lock) dict = _registers.GetOrAdd(regkeys[a], k1 => new ConcurrentDictionary <Guid, RegisterInfo>());
                    dict.TryAdd(id, new RegisterInfo(id, handler, time));
                }
                lock (_lock)
                    _cancels.TryAdd(id, regkeys);
                var isnew = false;

                if (IsSubscribed == false)
                {
                    lock (_lock)
                    {
                        if (IsSubscribed == false)
                        {
                            _redisSocket = _topOwner.Adapter.GetRedisSocket(null);
                            IsSubscribed = isnew = true;
                        }
                    }
                }
                if (isnew)
                {
                    new Thread(() =>
                    {
                        _redisSocketReceiveTimeoutOld = _redisSocket.ReceiveTimeout;
                        _redisSocket.ReceiveTimeout   = TimeSpan.Zero;
                        var timer = new Timer(state =>
                        {
                            _topOwner.Adapter.Refersh(_redisSocket); //防止 IdleBus 超时回收
                            try { _redisSocket.Write("PING"); } catch { }
                        }, null, 10000, 10000);
                        var readCmd = "PubSubRead".SubCommand(null).FlagReadbytes(false);
                        while (_stoped == false)
                        {
                            RedisResult rt = null;
                            try
                            {
                                rt = _redisSocket.Read(readCmd);
                            }
                            catch
                            {
                                Thread.CurrentThread.Join(100);
                                if (_cancels.Any())
                                {
                                    continue;
                                }
                                break;
                            }
                            var val = rt.Value as object[];
                            if (val == null)
                            {
                                continue;              //special case
                            }
                            var val1 = val[0].ConvertTo <string>();
                            switch (val1)
                            {
                            case "pong":
                            case "punsubscribe":
                            case "unsubscribe":
                                continue;

                            case "pmessage":
                                OnData(val[1].ConvertTo <string>(), val[2].ConvertTo <string>(), val[3]);
                                continue;

                            case "message":
                                OnData(null, val[1].ConvertTo <string>(), val[2]);
                                continue;
                            }
                        }
                        timer.Dispose();
                        lock (_lock)
                        {
                            IsSubscribed = false;
                            _redisSocket.ReceiveTimeout = _redisSocketReceiveTimeoutOld;
                            _redisSocket.ReleaseSocket();
                            _redisSocket.Dispose();
                            _redisSocket = null;
                        }
                    }).Start();
                }
                Call((psub ? "PSUBSCRIBE" : "SUBSCRIBE").Input(channels));
                return(new PubSubSubscribeDisposable(this, () => Cancel(id)));
            }