public bool TryParse(RawResult result, out T[] pairs) { switch (result.Type) { case ResultType.MultiBulk: var arr = result.GetItems(); if (arr == null) { pairs = null; } else { int count = arr.Length / 2; if (count == 0) { pairs = nix; } else { pairs = new T[count]; int offset = 0; for (int i = 0; i < pairs.Length; i++) { pairs[i] = Parse(arr[offset++], arr[offset++]); } } } return(true); default: pairs = null; return(false); } }
// internally, this is very similar to RawResult, except it is designed to be usable // outside of the IO-processing pipeline: the buffers are standalone, etc internal static RedisResult TryCreate(PhysicalConnection connection, RawResult result) { try { switch (result.Type) { case ResultType.Integer: case ResultType.SimpleString: case ResultType.BulkString: return new SingleRedisResult(result.AsRedisValue()); case ResultType.MultiBulk: var items = result.GetItems(); var arr = new RedisResult[items.Length]; for (int i = 0; i < arr.Length; i++) { var next = TryCreate(connection, items[i]); if (next == null) return null; // means we didn't understand arr[i] = next; } return new ArrayRedisResult(arr); case ResultType.Error: return new ErrorRedisResult(result.GetString()); default: return null; } } catch(Exception ex) { connection?.OnInternalError(ex); return null; // will be logged as a protocol fail by the processor } }
public bool TryParse(RawResult result, out TimeSpan?expiry) { switch (result.Type) { case ResultType.Integer: long time; if (result.TryGetInt64(out time)) { if (time < 0) { expiry = null; } else if (isMilliseconds) { expiry = TimeSpan.FromMilliseconds(time); } else { expiry = TimeSpan.FromSeconds(time); } return(true); } break; } expiry = null; return(false); }
private RawResult ReadArray(byte[] buffer, ref int offset, ref int count) { var itemCount = ReadLineTerminatedString(ResultType.Integer, buffer, ref offset, ref count); if (itemCount.HasValue) { if (!itemCount.TryGetInt64(out long i64)) { throw ExceptionFactory.ConnectionFailure(Multiplexer.IncludeDetailInExceptions, ConnectionFailureType.ProtocolFailure, "Invalid array length", Bridge.ServerEndPoint); } int itemCountActual = checked ((int)i64); if (itemCountActual < 0) { //for null response by command like EXEC, RESP array: *-1\r\n return(new RawResult(ResultType.SimpleString, null, 0, 0)); } else if (itemCountActual == 0) { //for zero array response by command like SCAN, Resp array: *0\r\n return(RawResult.EmptyArray); } var arr = new RawResult[itemCountActual]; for (int i = 0; i < itemCountActual; i++) { if (!(arr[i] = TryParseResult(buffer, ref offset, ref count)).HasValue) { return(RawResult.Nil); } } return(new RawResult(arr)); } return(RawResult.Nil); }
private RawResult ReadArray(byte[] buffer, ref int offset, ref int count) { var itemCount = ReadLineTerminatedString(ResultType.Integer, buffer, ref offset, ref count); if (itemCount.HasValue) { long i64; if (!itemCount.TryGetInt64(out i64)) { throw ExceptionFactory.ConnectionFailure(multiplexer.IncludeDetailInExceptions, ConnectionFailureType.ProtocolFailure, "Invalid array length", bridge.ServerEndPoint); } int itemCountActual = checked ((int)i64); if (itemCountActual <= 0) { return(RawResult.EmptyArray); } var arr = new RawResult[itemCountActual]; for (int i = 0; i < itemCountActual; i++) { if (!(arr[i] = TryParseResult(buffer, ref offset, ref count)).HasValue) { return(RawResult.Nil); } } return(new RawResult(arr)); } return(RawResult.Nil); }
private RawResult ReadBulkString(byte[] buffer, ref int offset, ref int count) { var prefix = ReadLineTerminatedString(ResultType.Integer, buffer, ref offset, ref count); if (prefix.HasValue) { long i64; if (!prefix.TryGetInt64(out i64)) { throw ExceptionFactory.ConnectionFailure(Multiplexer.IncludeDetailInExceptions, ConnectionFailureType.ProtocolFailure, "Invalid bulk string length", Bridge.ServerEndPoint); } int bodySize = checked ((int)i64); if (bodySize < 0) { return(new RawResult(ResultType.BulkString, null, 0, 0)); } else if (count >= bodySize + 2) { if (buffer[offset + bodySize] != '\r' || buffer[offset + bodySize + 1] != '\n') { throw ExceptionFactory.ConnectionFailure(Multiplexer.IncludeDetailInExceptions, ConnectionFailureType.ProtocolFailure, "Invalid bulk string terminator", Bridge.ServerEndPoint); } var result = new RawResult(ResultType.BulkString, buffer, offset, bodySize); offset += bodySize + 2; count -= bodySize + 2; return(result); } } return(RawResult.Nil); }
public RawResult(RawResult[] arr) { if (arr == null) throw new ArgumentNullException(nameof(arr)); Type = ResultType.MultiBulk; offset = 0; count = arr.Length; this.arr = arr; }
public RawResult(RawResult[] arr) { if (arr == null) throw new ArgumentNullException("arr"); this.resultType = ResultType.MultiBulk; this.offset = 0; this.count = arr.Length; this.arr = arr; }
internal override bool TryValidate(RawResult result, out bool value) { bool parsed; if (ResultProcessor.DemandZeroOrOneProcessor.TryGet(result, out parsed)) { value = parsed == expectedResult; ConnectionMultiplexer.TraceWithoutContext("exists: " + parsed + "; expected: " + expectedResult + "; voting: " + value); return(true); } value = false; return(false); }
internal override bool TryValidate(RawResult result, out bool value) { switch (result.Type) { case ResultType.BulkString: case ResultType.SimpleString: case ResultType.Integer: var parsed = result.AsRedisValue(); value = parsed.IsInteger && (expectedLength.CompareTo((long)parsed) == compareToResult); ConnectionMultiplexer.TraceWithoutContext("actual: " + (string)parsed + "; expected: " + expectedLength + "; wanted: " + GetComparisonString() + "; voting: " + value); return(true); } value = false; return(false); }
internal override bool TryValidate(RawResult result, out bool value) { switch (result.Type) { case ResultType.BulkString: case ResultType.SimpleString: case ResultType.Integer: var parsed = result.AsRedisValue(); value = (parsed == expectedValue) == expectedEqual; ConnectionMultiplexer.TraceWithoutContext("actual: " + (string)parsed + "; expected: " + (string)expectedValue + "; wanted: " + (expectedEqual ? "==" : "!=") + "; voting: " + value); return(true); } value = false; return(false); }
private RawResult ReadLineTerminatedString(ResultType type, byte[] buffer, ref int offset, ref int count) { int max = offset + count - 2; for (int i = offset; i < max; i++) { if (buffer[i + 1] == '\r' && buffer[i + 2] == '\n') { int len = i - offset + 1; var result = new RawResult(type, buffer, offset, len); count -= (len + 2); offset += (len + 2); return(result); } } return(RawResult.Nil); }
// internally, this is very similar to RawResult, except it is designed to be usable // outside of the IO-processing pipeline: the buffers are standalone, etc internal static RedisResult TryCreate(PhysicalConnection connection, RawResult result) { try { switch (result.Type) { case ResultType.Integer: case ResultType.SimpleString: case ResultType.BulkString: return(new SingleRedisResult(result.AsRedisValue(), result.Type)); case ResultType.MultiBulk: if (result.IsNull) { return(NullArray); } var items = result.GetItems(); if (items.Length == 0) { return(EmptyArray); } var arr = new RedisResult[items.Length]; for (int i = 0; i < arr.Length; i++) { var next = TryCreate(connection, items[i]); if (next == null) { return(null); // means we didn't understand } arr[i] = next; } return(new ArrayRedisResult(arr)); case ResultType.Error: return(new ErrorRedisResult(result.GetString())); default: return(null); } } catch (Exception ex) { connection?.OnInternalError(ex); return(null); // will be logged as a protocol fail by the processor } }
public static bool TryGet(RawResult result, out bool value) { switch (result.Type) { case ResultType.Integer: case ResultType.SimpleString: case ResultType.BulkString: if (result.IsEqual(one)) { value = true; return(true); } else if (result.IsEqual(zero)) { value = false; return(true); } break; } value = false; return(false); }
// returns an array of RawResults internal RawResult[] GetArrayOfRawResults() { if (arr == null) { return(null); } else if (arr.Length == 0) { return(new RawResult[0]); } else { var rawResultArray = new RawResult[arr.Length]; for (int i = 0; i < arr.Length; i++) { var rawResult = (RawResult)arr.GetValue(i); rawResultArray.SetValue(rawResult, i); } return(rawResultArray); } }
internal override bool TryValidate(RawResult result, out bool value) { switch (type) { case RedisType.SortedSet: var parsedValue = result.AsRedisValue(); value = (parsedValue.IsNull != expectedResult); ConnectionMultiplexer.TraceWithoutContext("exists: " + parsedValue + "; expected: " + expectedResult + "; voting: " + value); return(true); default: bool parsed; if (ResultProcessor.DemandZeroOrOneProcessor.TryGet(result, out parsed)) { value = parsed == expectedResult; ConnectionMultiplexer.TraceWithoutContext("exists: " + parsed + "; expected: " + expectedResult + "; voting: " + value); return(true); } value = false; return(false); } }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { switch (result.Type) { case ResultType.MultiBulk: var arr = result.GetItemsAsKeys(); SetResult(message, arr); return(true); } return(false); }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { var msg = message as ConditionMessage; var condition = msg == null ? null : msg.Condition; bool final; if (condition != null && condition.TryValidate(result, out final)) { SetResult(message, final); return(true); } return(false); }
internal abstract bool TryValidate(RawResult result, out bool value);
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { switch (result.Type) { case ResultType.Integer: case ResultType.SimpleString: case ResultType.BulkString: SetResult(message, result.AsRedisKey()); return(true); } return(false); }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { switch (result.Type) { case ResultType.SimpleString: case ResultType.BulkString: string s = result.GetString(); RedisType value; if (string.Equals(s, "zset", StringComparison.OrdinalIgnoreCase)) { value = Redis.RedisType.SortedSet; } else if (!Enum.TryParse <RedisType>(s, true, out value)) { value = global::StackExchange.Redis.RedisType.Unknown; } SetResult(message, value); return(true); } return(false); }
// returns an array of RawResults internal RawResult[] GetArrayOfRawResults() { if (arr == null) { return null; } else if (arr.Length == 0) { return new RawResult[0]; } else { var rawResultArray = new RawResult[arr.Length]; for (int i = 0; i < arr.Length; i++) { var rawResult = (RawResult)arr.GetValue(i); rawResultArray.SetValue(rawResult, i); } return rawResultArray; } }
private RawResult ReadLineTerminatedString(ResultType type, byte[] buffer, ref int offset, ref int count) { int max = offset + count - 2; for (int i = offset; i < max; i++) { if (buffer[i + 1] == '\r' && buffer[i + 2] == '\n') { int len = i - offset + 1; var result = new RawResult(type, buffer, offset, len); count -= (len + 2); offset += (len + 2); return result; } } return RawResult.Nil; }
private RawResult ReadBulkString(byte[] buffer, ref int offset, ref int count) { var prefix = ReadLineTerminatedString(ResultType.Integer, buffer, ref offset, ref count); if (prefix.HasValue) { long i64; if (!prefix.TryGetInt64(out i64)) throw ExceptionFactory.ConnectionFailure(multiplexer.IncludeDetailInExceptions, ConnectionFailureType.ProtocolFailure, "Invalid bulk string length", bridge.ServerEndPoint); int bodySize = checked((int)i64); if (bodySize < 0) { return new RawResult(ResultType.BulkString, null, 0, 0); } else if (count >= bodySize + 2) { if (buffer[offset + bodySize] != '\r' || buffer[offset + bodySize + 1] != '\n') { throw ExceptionFactory.ConnectionFailure(multiplexer.IncludeDetailInExceptions, ConnectionFailureType.ProtocolFailure, "Invalid bulk string terminator", bridge.ServerEndPoint); } var result = new RawResult(ResultType.BulkString, buffer, offset, bodySize); offset += bodySize + 2; count -= bodySize + 2; return result; } } return RawResult.Nil; }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { switch (result.Type) { case ResultType.Integer: case ResultType.SimpleString: case ResultType.BulkString: if (result.IsNull) { SetResult(message, null); return(true); } long i64; if (result.TryGetInt64(out i64)) { SetResult(message, i64); return(true); } break; } return(false); }
// true if ready to be completed (i.e. false if re-issued to another server) internal bool ComputeResult(PhysicalConnection connection, RawResult result) { return(resultProcessor == null || resultProcessor.SetResult(connection, this, result)); }
private RawResult ReadArray(byte[] buffer, ref int offset, ref int count) { var itemCount = ReadLineTerminatedString(ResultType.Integer, buffer, ref offset, ref count); if (itemCount.HasValue) { long i64; if (!itemCount.TryGetInt64(out i64)) throw ExceptionFactory.ConnectionFailure(multiplexer.IncludeDetailInExceptions, ConnectionFailureType.ProtocolFailure, "Invalid array length", bridge.ServerEndPoint); int itemCountActual = checked((int)i64); if (itemCountActual < 0) { //for null response by command like EXEC, RESP array: *-1\r\n return new RawResult(ResultType.SimpleString, null, 0, 0); } else if (itemCountActual == 0) { //for zero array response by command like SCAN, Resp array: *0\r\n return RawResult.EmptyArray; } var arr = new RawResult[itemCountActual]; for (int i = 0; i < itemCountActual; i++) { if (!(arr[i] = TryParseResult(buffer, ref offset, ref count)).HasValue) return RawResult.Nil; } return new RawResult(arr); } return RawResult.Nil; }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { connection?.BridgeCouldBeNull?.Multiplexer?.OnTransactionLog($"condition '{message.CommandAndKey}' got '{result.ToString()}'"); var msg = message as ConditionMessage; var condition = msg?.Condition; if (condition != null && condition.TryValidate(result, out bool final)) { SetResult(message, final); return(true); } return(false); }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { switch (result.Type) { case ResultType.MultiBulk: var arr = result.GetItems(); RedisChannel[] final; if (arr.Length == 0) { final = RedisChannel.EmptyArray; } else { final = new RedisChannel[arr.Length]; byte[] channelPrefix = connection.ChannelPrefix; for (int i = 0; i < final.Length; i++) { final[i] = result.AsRedisChannel(channelPrefix); } } SetResult(message, final); return(true); } return(false); }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { if (result.Type == ResultType.SimpleString && result.IsEqual(QUEUED)) { var q = message as QueuedMessage; if (q != null) { q.WasQueued = true; } return(true); } return(false); }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { switch (result.Type) { case ResultType.MultiBulk: var parts = result.GetItems(); CommandTrace[] arr = new CommandTrace[parts.Length]; for (int i = 0; i < parts.Length; i++) { var subParts = parts[i].GetItems(); long uniqueid, time, duration; if (!subParts[0].TryGetInt64(out uniqueid) || !subParts[1].TryGetInt64(out time) || !subParts[2].TryGetInt64(out duration)) { return(false); } arr[i] = new CommandTrace(uniqueid, time, duration, subParts[3].GetItemsAsValues()); } SetResult(message, arr); return(true); } return(false); }
void MatchResult(RawResult result) { // check to see if it could be an out-of-band pubsub message if (connectionType == ConnectionType.Subscription && result.Type == ResultType.MultiBulk) { // out of band message does not match to a queued message var items = result.GetItems(); if (items.Length >= 3 && items[0].IsEqual(message)) { // special-case the configuration change broadcasts (we don't keep that in the usual pub/sub registry) var configChanged = Multiplexer.ConfigurationChangedChannel; if (configChanged != null && items[1].IsEqual(configChanged)) { EndPoint blame = null; try { if (!items[2].IsEqual(RedisLiterals.ByteWildcard)) { blame = Format.TryParseEndPoint(items[2].GetString()); } } catch { /* no biggie */ } Multiplexer.Trace("Configuration changed: " + Format.ToString(blame), physicalName); Multiplexer.ReconfigureIfNeeded(blame, true, "broadcast"); } // invoke the handlers var channel = items[1].AsRedisChannel(ChannelPrefix, RedisChannel.PatternMode.Literal); Multiplexer.Trace("MESSAGE: " + channel, physicalName); if (!channel.IsNull) { Multiplexer.OnMessage(channel, channel, items[2].AsRedisValue()); } return; // AND STOP PROCESSING! } else if (items.Length >= 4 && items[0].IsEqual(pmessage)) { var channel = items[2].AsRedisChannel(ChannelPrefix, RedisChannel.PatternMode.Literal); Multiplexer.Trace("PMESSAGE: " + channel, physicalName); if (!channel.IsNull) { var sub = items[1].AsRedisChannel(ChannelPrefix, RedisChannel.PatternMode.Pattern); Multiplexer.OnMessage(sub, channel, items[3].AsRedisValue()); } return; // AND STOP PROCESSING! } // if it didn't look like "[p]message", then we still need to process the pending queue } Multiplexer.Trace("Matching result...", physicalName); Message msg; lock (outstanding) { Multiplexer.Trace(outstanding.Count == 0, "Nothing to respond to!", physicalName); msg = outstanding.Dequeue(); } Multiplexer.Trace("Response to: " + msg.ToString(), physicalName); if (msg.ComputeResult(this, result)) { Bridge.CompleteSyncOrAsync(msg); } }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { var tran = message as TransactionMessage; if (tran != null) { var bridge = connection.Bridge; var wrapped = tran.InnerOperations; switch (result.Type) { case ResultType.SimpleString: if (tran.IsAborted && result.IsEqual(RedisLiterals.BytesOK)) { connection.Multiplexer.Trace("Acknowledging UNWATCH (aborted electively)"); SetResult(message, false); return(true); } break; case ResultType.MultiBulk: if (!tran.IsAborted) { var arr = result.GetItems(); if (arr == null) { connection.Multiplexer.Trace("Server aborted due to failed WATCH"); foreach (var op in wrapped) { op.Wrapped.Cancel(); bridge.CompleteSyncOrAsync(op.Wrapped); } SetResult(message, false); return(true); } else if (wrapped.Length == arr.Length) { connection.Multiplexer.Trace("Server committed; processing nested replies"); for (int i = 0; i < arr.Length; i++) { if (wrapped[i].Wrapped.ComputeResult(connection, arr[i])) { bridge.CompleteSyncOrAsync(wrapped[i].Wrapped); } } SetResult(message, true); return(true); } } break; } // even if we didn't fully understand the result, we still need to do something with // the pending tasks foreach (var op in wrapped) { op.Wrapped.Fail(ConnectionFailureType.ProtocolFailure, null); bridge.CompleteSyncOrAsync(op.Wrapped); } } return(false); }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { switch (result.Type) { case ResultType.BulkString: var raw = result.GetString(); var clients = Parse(raw); SetResult(message, clients); return(true); } return(false); }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { if (result.Type == ResultType.BulkString) { string category = Normalize(null), line; var list = new List <Tuple <string, KeyValuePair <string, string> > >(); using (var reader = new StringReader(result.GetString())) { while ((line = reader.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line)) { continue; } if (line.StartsWith("# ")) { category = Normalize(line.Substring(2)); continue; } int idx = line.IndexOf(':'); if (idx < 0) { continue; } var pair = new KeyValuePair <string, string>( line.Substring(0, idx).Trim(), line.Substring(idx + 1).Trim()); list.Add(Tuple.Create(category, pair)); } } var final = list.GroupBy(x => x.Item1, x => x.Item2).ToArray(); SetResult(message, final); return(true); } return(false); }
public override bool SetResult(PhysicalConnection connection, Message message, RawResult result) { if (result.IsError) { var tran = message as TransactionMessage; if (tran != null) { string error = result.GetString(); var bridge = connection.Bridge; foreach (var op in tran.InnerOperations) { ServerFail(op.Wrapped, error); bridge.CompleteSyncOrAsync(op.Wrapped); } } } return(base.SetResult(connection, message, result)); }
void MatchResult(RawResult result) { // check to see if it could be an out-of-band pubsub message if (connectionType == ConnectionType.Subscription && result.Type == ResultType.MultiBulk) { // out of band message does not match to a queued message var items = result.GetItems(); if (items.Length >= 3 && items[0].IsEqual(message)) { // special-case the configuration change broadcasts (we don't keep that in the usual pub/sub registry) var configChanged = multiplexer.ConfigurationChangedChannel; if (configChanged != null && items[1].IsEqual(configChanged)) { EndPoint blame = null; try { if (!items[2].IsEqual(RedisLiterals.ByteWildcard)) { blame = Format.TryParseEndPoint(items[2].GetString()); } } catch { /* no biggie */ } multiplexer.Trace("Configuration changed: " + Format.ToString(blame), physicalName); multiplexer.ReconfigureIfNeeded(blame, true, "broadcast"); } // invoke the handlers var channel = items[1].AsRedisChannel(ChannelPrefix, RedisChannel.PatternMode.Literal); multiplexer.Trace("MESSAGE: " + channel, physicalName); if (!channel.IsNull) { multiplexer.OnMessage(channel, channel, items[2].AsRedisValue()); } return; // AND STOP PROCESSING! } else if (items.Length >= 4 && items[0].IsEqual(pmessage)) { var channel = items[2].AsRedisChannel(ChannelPrefix, RedisChannel.PatternMode.Literal); multiplexer.Trace("PMESSAGE: " + channel, physicalName); if (!channel.IsNull) { var sub = items[1].AsRedisChannel(ChannelPrefix, RedisChannel.PatternMode.Pattern); multiplexer.OnMessage(sub, channel, items[3].AsRedisValue()); } return; // AND STOP PROCESSING! } // if it didn't look like "[p]message", then we still need to process the pending queue } multiplexer.Trace("Matching result...", physicalName); Message msg; lock (outstanding) { multiplexer.Trace(outstanding.Count == 0, "Nothing to respond to!", physicalName); msg = outstanding.Dequeue(); } multiplexer.Trace("Response to: " + msg.ToString(), physicalName); if (msg.ComputeResult(this, result)) { bridge.CompleteSyncOrAsync(msg); } }
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result) { switch (result.Type) { case ResultType.MultiBulk: var arr = result.GetItems(); long i64; if (arr.Length == 2 && arr[1].Type == ResultType.MultiBulk && arr[0].TryGetInt64(out i64)) { var keysResult = new ScanResult(i64, arr[1].GetItemsAsKeys()); SetResult(message, keysResult); return(true); } break; } return(false); }
private RawResult ReadArray(byte[] buffer, ref int offset, ref int count) { var itemCount = ReadLineTerminatedString(ResultType.Integer, buffer, ref offset, ref count); if (itemCount.HasValue) { long i64; if (!itemCount.TryGetInt64(out i64)) throw ExceptionFactory.ConnectionFailure(multiplexer.IncludeDetailInExceptions, ConnectionFailureType.ProtocolFailure, "Invalid array length", bridge.ServerEndPoint); int itemCountActual = checked((int)i64); if (itemCountActual <= 0) return RawResult.EmptyArray; var arr = new RawResult[itemCountActual]; for (int i = 0; i < itemCountActual; i++) { if (!(arr[i] = TryParseResult(buffer, ref offset, ref count)).HasValue) return RawResult.Nil; } return new RawResult(arr); } return RawResult.Nil; }