Commit c002a00e authored by Marc Gravell's avatar Marc Gravell

migrate BookSleeve "Scripting" suite; fix "eval inside transaction" bug

parent 6c191d56
......@@ -188,11 +188,11 @@ where Attribute.IsDefined(method, typeof(TestAttribute))
}
Console.WriteLine("Passed: {0}; Failed: {1}", pass, fail);
foreach (var msg in epicFail) Console.WriteLine(msg);
#if DEBUG
Console.WriteLine();
Console.WriteLine("Callbacks: {0:###,###,##0} sync, {1:###,###,##0} async",
BookSleeve.RedisConnectionBase.AllSyncCallbacks, BookSleeve.RedisConnectionBase.AllAsyncCallbacks);
#endif
//#if DEBUG
// Console.WriteLine();
// Console.WriteLine("Callbacks: {0:###,###,##0} sync, {1:###,###,##0} async",
// BookSleeve.RedisConnectionBase.AllSyncCallbacks, BookSleeve.RedisConnectionBase.AllAsyncCallbacks);
//#endif
}
}
......
This diff is collapsed.
......@@ -273,9 +273,18 @@ internal Message GetSelectDatabaseCommand(int targetDatabase, Message message)
}
return null;
}
if(message.Command == RedisCommand.SELECT)
{
// this could come from an EVAL/EVALSHA inside a transaction, for example; we'll accept it
bridge.Trace("Switching database: " + targetDatabase);
currentDatabase = targetDatabase;
return null;
}
if (TransactionActive)
{// should never see this, since the API doesn't allow it; thus not too worried about ExceptionFactory
throw new RedisCommandException("Multiple databases inside a transaction are not currently supported" + targetDatabase);
throw new RedisCommandException("Multiple databases inside a transaction are not currently supported: " + targetDatabase);
}
if (available != 0 && targetDatabase >= available) // we positively know it is out of range
......@@ -284,12 +293,16 @@ internal Message GetSelectDatabaseCommand(int targetDatabase, Message message)
}
bridge.Trace("Switching database: " + targetDatabase);
currentDatabase = targetDatabase;
return GetSelectDatabaseCommand(targetDatabase);
}
return null;
}
internal static Message GetSelectDatabaseCommand(int targetDatabase)
{
return targetDatabase < DefaultRedisDatabaseCount
? ReusableChangeDatabaseCommands[targetDatabase] // 0-15 by default
: Message.Create(targetDatabase, CommandFlags.FireAndForget, RedisCommand.SELECT);
}
return null;
}
internal int GetSentAwaitingResponseCount()
{
......
......@@ -7,6 +7,7 @@ namespace StackExchange.Redis
/// </summary>
public abstract class RedisResult
{
// 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
......@@ -42,6 +43,11 @@ internal static RedisResult TryCreate(PhysicalConnection connection, RawResult r
}
}
/// <summary>
/// Indicates whether this result was a null result
/// </summary>
public abstract bool IsNull { get; }
/// <summary>
/// Interprets the result as a String
/// </summary>
......@@ -168,6 +174,10 @@ internal static RedisResult TryCreate(PhysicalConnection connection, RawResult r
internal abstract string[] AsStringArray();
private sealed class ArrayRedisResult : RedisResult
{
public override bool IsNull
{
get { return value == null; }
}
private readonly RedisResult[] value;
public ArrayRedisResult(RedisResult[] value)
{
......@@ -275,6 +285,10 @@ public ErrorRedisResult(string value)
if (value == null) throw new ArgumentNullException("value");
this.value = value;
}
public override bool IsNull
{
get { return value == null; }
}
public override string ToString() { return value; }
internal override bool AsBoolean() { throw new RedisServerException(value); }
......@@ -326,6 +340,11 @@ public SingleRedisResult(RedisValue value)
this.value = value;
}
public override bool IsNull
{
get { return value.IsNull; }
}
public override string ToString() { return value.ToString(); }
internal override bool AsBoolean() { return (bool)value; }
......
......@@ -86,6 +86,22 @@ internal override Task<T> ExecuteAsync<T>(Message message, ResultProcessor<T> pr
// store it, and return the task of the *outer* command
// (there is no task for the inner command)
(pending ?? (pending = new List<QueuedMessage>())).Add(queued);
switch(message.Command)
{
case RedisCommand.EVAL:
case RedisCommand.EVALSHA:
// people can do very naughty things in an EVAL
// including change the DB; change it back to what we
// think it should be!
var sel = PhysicalConnection.GetSelectDatabaseCommand(message.Db);
queued = new QueuedMessage(sel);
wasQueued = ResultBox<bool>.Get(null);
queued.SetSource(wasQueued, QueuedProcessor.Default);
pending.Add(queued);
break;
}
return task;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment