예제 #1
0
        private Queue <String> LoadUnexistentScripts(SocketReader reader, SocketWriter writer)
        {
            var loadQueue = new Queue <String>();

            // read results
            var result = RESPObject.Read(reader);
            var array  = result.Cast <RESPArray>();

            // if a script does not exists, send 'script load'
            for (int i = 0; i < array.Count; i++)
            {
                var found = array[i].Cast <RESPInteger>().Value != 0;
                if (!found)
                {
                    var digest = _procedures.Digests[i];
                    _logger.Info("Script with digest {0} not found, loading...", digest);
                    var load = GenerateLoadCommand(digest);
                    load.WriteTo(writer);
                    loadQueue.Enqueue(digest);
                }
            }

            writer.Flush();
            return(loadQueue);
        }
예제 #2
0
 private void RunInitializers(SocketReader reader, SocketWriter writer)
 {
     foreach (var initializer in Initializers)
     {
         initializer.Initialize(reader, writer);
     }
 }
예제 #3
0
        private async Task ConnectionWatchDog(TcpClient tcp)
        {
            while (!_connectionCancellation.IsCancellationRequested)
            {
                try
                {
                    using (tcp)
                        using (var nstream = tcp.GetStream())
                            using (var writer = new SocketWriter(nstream, _options.WriteBufferSize))
                                using (var reader = new SocketReader(nstream, _options.ReadBufferSize))
                                {
                                    RunInitializers(reader, writer);

                                    var tasks = new[]
                                    {
                                        Task.Run(() => ReadAsync(reader)),
                                        Task.Run(() => WriteAsync(writer)),
                                        _options.PingTimeout != Timeout.InfiniteTimeSpan ? Task.Run(() => TimeoutWatchdogAsync()) : new Task(() => {})
                                    };

                                    if (_interval != Timeout.InfiniteTimeSpan)
                                    {
                                        _pingTimer.Change(_interval, _interval); // start timer
                                    }
                                    _loadFactor = 1;
                                    OnConnection();

                                    await Task.WhenAny(tasks).ConfigureAwait(false);

                                    ThrowSocketExceptionIfExists(tasks);
                                }
                }
                catch (SocketException soex)
                {
                    // rotate endpoint
                    _currentEndpoint = (_currentEndpoint + 1) % _endpoints.Length;
                    _logger.Error(soex, "Connection {0} error. Switching endpoing.", _code);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "Connection {0} error.", _code);
                }

                _logger.Info("Connection {0} disconnected.", _code);
                _loadFactor = 100;
                _pending.CancelTokens();
                OnDisconnection();

                if (_connectionCancellation.IsCancellationRequested)
                {
                    continue;
                }

                tcp = new TcpClient();
                await ConnectWithTimeOut(tcp, _endpoints[_currentEndpoint]).ConfigureAwait(false);
            }
        }
예제 #4
0
        public void Initialize(SocketReader reader, SocketWriter writer)
        {
            if (!ShouldLoadScripts(writer))
            {
                return;
            }

            var loadQueue = LoadUnexistentScripts(reader, writer);

            ValidateScriptLoadingResults(reader, loadQueue);
        }
예제 #5
0
        public void Initialize(SocketReader reader, SocketWriter writer)
        {
            if (_commands == null || _commands.Length == 0)
            {
                return;
            }

            SendCommands(writer);

            writer.Flush();

            ReadResults(reader);
        }
예제 #6
0
        internal static RESPBulkString Load(SocketReader reader)
        {
            Int32 byteLength = reader.ReadInt32();

            if (byteLength < 0)
            {
                return(Null);
            }
            else
            {
                return(new RESPBulkString(reader.ReadString(byteLength)));
            }
        }
예제 #7
0
        internal static RESPError Load(SocketReader reader)
        {
            var line  = reader.ReadString();
            var space = line.IndexOf(' ');

            if (space != -1)
            {
                return(new RESPError(line.Substring(0, space), line.Substring(space + 1)));
            }
            else
            {
                return(new RESPError(line));
            }
        }
예제 #8
0
        public void Initialize(SocketReader reader, SocketWriter writer)
        {
            var currentSubscriptions = _subscriptions.GetAllSubscribeCommands();

            if (currentSubscriptions.Any())
            {
                foreach (var command in currentSubscriptions)
                {
                    command.WriteTo(writer);
                }

                writer.Flush();
            }
        }
예제 #9
0
 private void ReadResults(SocketReader reader)
 {
     foreach (var command in _commands)
     {
         var response = RESPObject.Read(reader);
         _logger.Info(" <- Response for initialization command '{0}' is type '{1}'.", command.Header, response != null ? response.Header.ToString() : "<null>.");
         if (response == null)
         {
             throw new RedisClientSocketException("Initialization command did not return any response.");
         }
         if (response.Header == RESPHeaders.Error)
         {
             throw new RedisClientCommandException(response.Cast <RESPError>());
         }
     }
 }
예제 #10
0
        private async Task ReadAsync(SocketReader reader)
        {
            try
            {
                while (!_connectionCancellation.IsCancellationRequested)
                {
                    _logger.Debug("{0} listening...", _code);
                    var resp = await RESPObject.ReadAsync(reader, _connectionCancellation.Token).ConfigureAwait(false);

                    _logger.Debug("{0} Received response of type {1}.", _code, resp.Header);
                    RegisterActivity();
                    ProcessResponse(resp);
                }
            }
            catch (OperationCanceledException) { }
            catch (ObjectDisposedException) { }
            catch (IOException) { }
        }
예제 #11
0
        internal static RESPArray Load(SocketReader reader)
        {
            Int32 itemCount = reader.ReadInt32();

            if (itemCount < 0)
            {
                return(RESPArray.Empty);
            }

            var array = new RESPArray(itemCount);

            for (int i = 0; i < itemCount; i++)
            {
                var obj = RESPObject.Read(reader);
                if (obj == null)
                {
                    throw new RESPException("Cannot read array elements.");
                }
                array._items[i] = obj;
            }
            return(array);
        }
예제 #12
0
        static RESPObject ProcessResponse(Char?header, SocketReader reader)
        {
            if (!header.HasValue)
            {
                return(null);
            }

            switch (header)
            {
            case RESPHeaders.SimpleString: return(RESPSimpleString.Load(reader));

            case RESPHeaders.BulkString: return(RESPBulkString.Load(reader));

            case RESPHeaders.Array: return(RESPArray.Load(reader));

            case RESPHeaders.Error: return(RESPError.Load(reader));

            case RESPHeaders.Integer: return(RESPInteger.Load(reader));

            default: throw new RESPException("Unrecognized RESP header (byte): " + (byte)header.Value);
            }
        }
예제 #13
0
        private void ValidateScriptLoadingResults(SocketReader reader, Queue <String> loadQueue)
        {
            // for loaded scripts, read responses and ensure
            // returned SHA1 fits the locally calculated one
            while (loadQueue.Any())
            {
                var digest = loadQueue.Dequeue();
                var result = RESPObject.Read(reader);

                if (result == null)
                {
                    throw new RedisClientParsingException("Cannot read responses.");
                }

                try
                {
                    var resultDigest = result.Cast <RESPString>().Value;
                    if (digest != resultDigest)
                    {
                        throw new RedisClientParsingException("Script digest differs.");
                    }

                    _logger.Info("Script with digest {0} loaded.", digest);
                }
                catch (RedisClientException rcex)
                {
                    _logger.Error(rcex, "Script with digest {0} failed to load.", digest);
                    _procedures.SetFaulted(digest, rcex);
                }
                catch (Exception cmdEx)
                {
                    _logger.Error(cmdEx, "Script with digest {0} failed to load.", digest);
                    _procedures.SetFaulted(digest, new RedisClientParsingException("Error validating script digest", cmdEx));
                }
            }
        }
예제 #14
0
        internal static RESPObject Read(SocketReader reader)
        {
            var first = reader.ReadRESPHeader();

            return(ProcessResponse(first, reader));
        }
예제 #15
0
 internal static TRESP Read <TRESP>(SocketReader reader)
     where TRESP : RESPObject
 {
     return((TRESP)Read(reader));
 }
예제 #16
0
        internal static async Task <RESPObject> ReadAsync(SocketReader reader, CancellationToken cancel)
        {
            var first = await reader.ReadRESPHeaderAsync(cancel).ConfigureAwait(false);

            return(ProcessResponse(first, reader));
        }
예제 #17
0
 internal static RESPInteger Load(SocketReader reader)
 {
     return(new RESPInteger(reader.ReadInt64()));
 }
예제 #18
0
 internal static RESPSimpleString Load(SocketReader reader)
 {
     return(new RESPSimpleString(reader.ReadString()));
 }