Exemplo n.º 1
0
 public void Dispose()
 {
     _rds.ReceiveTimeout = _oldReceiveTimeout;
     _runing             = false;
     _rds.ReleaseSocket();
     ClearAndTrySetExpcetion(null);
 }
Exemplo n.º 2
0
            internal void Cancel(params Guid[] ids)
            {
                if (ids == null)
                {
                    return;
                }
                var readyUnsubInterKeys = new List <string>();

                foreach (var id in ids)
                {
                    if (_cancels.TryRemove(id, out var oldkeys))
                    {
                        foreach (var oldkey in oldkeys)
                        {
                            if (_registers.TryGetValue(oldkey, out var oldrecvs) &&
                                oldrecvs.TryRemove(id, out var oldrecv) &&
                                oldrecvs.Any() == false)
                            {
                                readyUnsubInterKeys.Add(oldkey);
                            }
                        }
                    }
                }
                var unsub  = readyUnsubInterKeys.Where(a => !a.StartsWith(_psub_regkey_prefix)).ToArray();
                var punsub = readyUnsubInterKeys.Where(a => a.StartsWith(_psub_regkey_prefix)).Select(a => a.Replace(_psub_regkey_prefix, "")).ToArray();

                if (unsub.Any())
                {
                    Call("UNSUBSCRIBE".Input(unsub));
                }
                if (punsub.Any())
                {
                    Call("PUNSUBSCRIBE".Input(punsub));
                }

                if (!_cancels.Any())
                {
                    lock (_lock)
                        if (!_cancels.Any())
                        {
                            _redisSocket.ReleaseSocket();
                        }
                }
            }
Exemplo n.º 3
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);
     }));
 }
Exemplo n.º 4
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);
     }));
 }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
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)));
            }