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(); }