Esempio n. 1
0
        protected override void DoAfterCompleteContext(RedisBufferContext context, RedisAsyncTask asyncTask)
        {
            if (context.ResultType == RedisRawObjectType.SimpleString)
            {
                var result = context.Result as RedisString;

                if (!ReferenceEquals(result, null) &&
                    result != RedisConstants.OK)
                {
                    var message = ToMonitorMessage(result);
                    if (message != null && !message.IsEmpty)
                    {
                        var callback = m_Callback;
                        if (callback != null)
                        {
                            callback(message);
                        }
                        return;
                    }
                }
            }

            if (asyncTask != null)
            {
                asyncTask.TrySetCompleted(context.Result);
            }
        }
 protected virtual void DoAfterCompleteContext(RedisBufferContext context, RedisAsyncTask asyncTask)
 {
     if (asyncTask != null)
     {
         asyncTask.TrySetCompleted(context.Result);
     }
 }
        protected override void DoAfterCompleteContext(RedisBufferContext context, RedisAsyncTask asyncTask)
        {
            if (context.ResultType == RedisRawObjectType.Array)
            {
                var result = context.Result as RedisArray;

                if (!ReferenceEquals(result, null))
                {
                    var message = ToPubSubMessage(result);

                    if (message != null && !message.IsEmpty)
                    {
                        if (asyncTask != null &&
                            !(message.Type == RedisPubSubMessageType.Message ||
                              message.Type == RedisPubSubMessageType.PMessage))
                        {
                            asyncTask.TrySetCompleted(context.Result);
                        }

                        var callback = m_Callback;
                        if (callback != null)
                        {
                            callback(message);
                        }
                        return;
                    }
                }
            }

            if (asyncTask != null)
            {
                asyncTask.TrySetCompleted(context.Result);
            }
        }
        private bool TryParseLine(RedisBufferContext context, out byte[] result)
        {
            result = null;
            var contextLength = context.Length;

            if (contextLength > 0)
            {
                var buffer = context.Buffer;

                var lineStart     = context.Offset;
                var contextOffset = context.Offset;

                var crState = false;
                while (contextLength-- > 0)
                {
                    if (crState)
                    {
                        if (buffer[contextOffset++] != LF)
                        {
                            crState = false;
                        }
                        else
                        {
                            context.Offset = contextOffset;
                            context.Length = contextLength;

                            var dataLength = (contextOffset - CRLFLength) - lineStart;
                            if (dataLength > 0)
                            {
                                result = new byte[dataLength];
                                Array.Copy(buffer, lineStart, result, 0, dataLength);
                            }
                            else
                            {
                                result = new byte[0];
                            }

                            return(true);
                        }
                    }
                    else if (buffer[contextOffset++] == CR)
                    {
                        crState = true;
                    }
                }
            }
            return(false);
        }
        public void TryParse(RedisBufferContext context)
        {
            var buffer = context.Buffer;

            if (buffer != null)
            {
                var bufferLen = buffer.Length;

                var contextLen    = context.Length;
                var contextOffset = context.Offset;

                if (bufferLen == 0 || contextLen <= 0 ||
                    contextOffset < 0 || contextOffset >= bufferLen)
                {
                    return;
                }

                context.Length = Math.Min(contextLen, bufferLen - contextOffset);

                var sign = buffer[contextOffset];
                switch (sign)
                {
                case BulkStringSign:
                {
                    context.Offset++;
                    context.Length--;

                    context.ResultType = RedisRawObjectType.BulkString;

                    byte[] bytes;
                    if (!TryParseLine(context, out bytes))
                    {
                        context.Offset--;
                        context.Length++;
                    }
                    else
                    {
                        long dataSize;
                        if (!bytes.TryParse(out dataSize))
                        {
                            throw new RedisException("Invalid bulk string size", RedisErrorCode.CorruptResponse);
                        }

                        if (dataSize > RedisConstants.MinusOne)
                        {
                            var iSize = checked ((int)dataSize);

                            if (context.Length >= iSize + CRLFLength)
                            {
                                var crPos = context.Offset + iSize;
                                if (!(buffer[crPos] == CR && buffer[crPos + 1] == LF))
                                {
                                    throw new RedisException("Invalid bulk string data termination", RedisErrorCode.CorruptResponse);
                                }

                                context.Completed = true;
                                if (iSize == 0)
                                {
                                    context.Result = new RedisBytes(new byte[0]);
                                }
                                else
                                {
                                    var result = new byte[iSize];
                                    Array.Copy(buffer, context.Offset, result, 0, iSize);

                                    context.Result = new RedisBytes(result);
                                }

                                context.Offset += iSize + CRLFLength;
                                context.Length -= iSize + CRLFLength;
                            }
                        }
                        else
                        {
                            if (dataSize < RedisConstants.MinusOne)
                            {
                                throw new RedisException("Invalid bulk string size", RedisErrorCode.CorruptResponse);
                            }

                            context.Completed = true;
                            context.Result    = new RedisBytes(null);
                        }
                    }
                }
                break;

                case ArraySign:
                {
                    context.Offset++;
                    context.Length--;

                    context.ResultType = RedisRawObjectType.Array;

                    byte[] bytes;
                    if (!TryParseLine(context, out bytes))
                    {
                        context.Offset--;
                        context.Length++;
                    }
                    else
                    {
                        long itemCount;
                        if (!bytes.TryParse(out itemCount))
                        {
                            throw new RedisException("Invalid bulk string size", RedisErrorCode.CorruptResponse);
                        }

                        if (itemCount > RedisConstants.Zero)
                        {
                            var iCount = checked ((int)itemCount);

                            var array = new RedisArray(iCount);
                            var items = array.RawData as IList <RedisResult>;

                            for (var i = 0; i < iCount; i++)
                            {
                                var innerContext =
                                    new RedisBufferContext
                                {
                                    Buffer = buffer,
                                    Length = context.Length,
                                    Offset = context.Offset,
                                };

                                TryParse(innerContext);
                                if (!innerContext.Completed)
                                {
                                    return;
                                }

                                context.Offset = innerContext.Offset;
                                context.Length = innerContext.Length;

                                items.Add(innerContext.Result);
                            }

                            array.TrySetCompleted();

                            context.Result    = array;
                            context.Completed = true;
                        }
                        else if (itemCount == RedisConstants.Zero)
                        {
                            context.Result    = new RedisArray(new List <RedisResult>(), 0);
                            context.Completed = true;
                        }
                        else
                        {
                            context.Result    = new RedisArray(null, -1);
                            context.Completed = true;
                        }
                    }
                }
                break;

                case SimpleStringSign:
                {
                    context.Offset++;
                    context.Length--;

                    context.ResultType = RedisRawObjectType.SimpleString;

                    byte[] bytes;
                    if (!TryParseLine(context, out bytes))
                    {
                        context.Offset--;
                        context.Length++;
                    }
                    else
                    {
                        context.Result    = new RedisString((bytes == null) ? null : RedisCommon.ToUTF8String(bytes));
                        context.Completed = true;
                    }
                }
                break;

                case ErrorSign:
                {
                    context.Offset++;
                    context.Length--;

                    context.ResultType = RedisRawObjectType.Error;

                    byte[] bytes;
                    if (!TryParseLine(context, out bytes))
                    {
                        context.Offset--;
                        context.Length++;
                    }
                    else
                    {
                        context.Result    = new RedisError((bytes == null) ? null : RedisCommon.ToUTF8String(bytes));
                        context.Completed = true;
                    }
                }
                break;

                case NumberSign:
                {
                    context.Offset++;
                    context.Length--;

                    context.ResultType = RedisRawObjectType.Integer;

                    byte[] bytes;
                    if (!TryParseLine(context, out bytes))
                    {
                        context.Offset--;
                        context.Length++;
                    }
                    else
                    {
                        long number;
                        if (!bytes.TryParse(out number))
                        {
                            throw new RedisException("Invalid integer value", RedisErrorCode.CorruptResponse);
                        }

                        context.Result    = new RedisInteger(number);
                        context.Completed = true;
                    }
                }
                break;

                default:
                    throw new RedisException("Undefined redis response type", RedisErrorCode.CorruptResponse);
                }
            }
        }
 protected virtual void DoBeforeCompleteContext(RedisBufferContext context, out bool @continue, out RedisAsyncTask asyncTask)
 {
     @continue = m_ReceiveWaitingQ.TryDequeue(out asyncTask);
 }
        private bool ReadResponse()
        {
            if (Disposed)
            {
                return(false);
            }

            var buffer = m_Buffer;

            if (buffer == null)
            {
                return(false);
            }

            var offset = m_Offset;

            var dataLength = m_CurrentPos - offset;

            if (dataLength <= 0)
            {
                return(false);
            }

            var context = new RedisBufferContext
            {
                Buffer = buffer,
                Offset = offset,
                Length = dataLength
            };

            m_Parser.TryParse(context);
            if (Disposed)
            {
                return(false);
            }

            if (context.Completed)
            {
                bool           @continue;
                RedisAsyncTask asyncTask;

                DoBeforeCompleteContext(context, out @continue, out asyncTask);
                if (!@continue || Disposed)
                {
                    return(false);
                }

                try
                {
                    var remaining = Math.Max(0, m_CurrentPos - context.Offset);
                    if (remaining == 0)
                    {
                        m_Offset     = 0;
                        m_CurrentPos = 0;

                        return(false);
                    }

                    // Has more
                    m_Offset = context.Offset;
                    if ((m_Capacity - m_CurrentPos) /* AvailableCapacity */ < MinAvailableCapacity)
                    {
                        Array.Copy(buffer, context.Offset, buffer, 0, remaining);

                        m_Offset     = 0;
                        m_CurrentPos = remaining;
                    }

                    return(true);
                }
                finally
                {
                    if (!Disposed)
                    {
                        DoAfterCompleteContext(context, asyncTask);
                    }
                }
            }

            if (m_Offset > 0 && dataLength > 0)
            {
                Array.Copy(buffer, m_Offset, buffer, 0, dataLength);

                m_Offset     = 0;
                m_CurrentPos = dataLength;
            }
            return(false);
        }
 protected override void DoBeforeCompleteContext(RedisBufferContext context, out bool @continue, out RedisAsyncTask asyncTask)
 {
     @continue = true;
     asyncTask = m_ReceiveWaitingQ.Dequeue();
 }