Commit fe8544b2 authored by Jeremy Meng's avatar Jeremy Meng

Attempt to fix the whitespace/encoding issue with Emacs.

parent 790bb080
.hg .hg
bin bin
bin.snk bin.snk
obj obj
*.suo *.suo
*.user *.user
*.nupkg *.nupkg
packages/NuGet.CommandLine.* packages/NuGet.CommandLine.*
*.sln.docstates *.sln.docstates
_ReSharper.* _ReSharper.*
Mono/ Mono/
*.sln.ide *.sln.ide
*.rdb *.rdb
*.aof *.aof
*.orig *.orig
redis-cli.exe redis-cli.exe
Redis Configs/*.dat Redis Configs/*.dat
RedisQFork*.dat RedisQFork*.dat
StackExchange.Redis.*.zip StackExchange.Redis.*.zip
.vs/ .vs/
*.lock.json *.lock.json
\ No newline at end of file
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
#if FEATURE_BOOKSLEEVE #if FEATURE_BOOKSLEEVE
using BookSleeve; using BookSleeve;
#endif #endif
using NUnit.Framework; using NUnit.Framework;
using StackExchange.Redis.KeyspaceIsolation; using StackExchange.Redis.KeyspaceIsolation;
namespace StackExchange.Redis.Tests namespace StackExchange.Redis.Tests
{ {
[TestFixture] [TestFixture]
public class BasicOpsTests : TestBase public class BasicOpsTests : TestBase
{ {
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void PingOnce(bool preserveOrder) public void PingOnce(bool preserveOrder)
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
var task = conn.PingAsync(); var task = conn.PingAsync();
var duration = muxer.Wait(task); var duration = muxer.Wait(task);
Console.WriteLine("Ping took: " + duration); Console.WriteLine("Ping took: " + duration);
Assert.IsTrue(duration.TotalMilliseconds > 0); Assert.IsTrue(duration.TotalMilliseconds > 0);
} }
} }
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void RapidDispose(bool preserverOrder) public void RapidDispose(bool preserverOrder)
{ {
RedisKey key = Me(); RedisKey key = Me();
using (var primary = Create()) using (var primary = Create())
{ {
var conn = primary.GetDatabase(); var conn = primary.GetDatabase();
conn.KeyDelete(key); conn.KeyDelete(key);
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
using (var secondary = Create(fail: true)) using (var secondary = Create(fail: true))
{ {
secondary.GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget); secondary.GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
} }
} }
Assert.AreEqual(10, (int)conn.StringGet(key)); Assert.AreEqual(10, (int)conn.StringGet(key));
} }
} }
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void PingMany(bool preserveOrder) public void PingMany(bool preserveOrder)
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
var tasks = new Task<TimeSpan>[10000]; var tasks = new Task<TimeSpan>[10000];
for (int i = 0; i < tasks.Length; i++) for (int i = 0; i < tasks.Length; i++)
{ {
tasks[i] = conn.PingAsync(); tasks[i] = conn.PingAsync();
} }
muxer.WaitAll(tasks); muxer.WaitAll(tasks);
Assert.IsTrue(tasks[0].Result.TotalMilliseconds > 0); Assert.IsTrue(tasks[0].Result.TotalMilliseconds > 0);
Assert.IsTrue(tasks[tasks.Length - 1].Result.TotalMilliseconds > 0); Assert.IsTrue(tasks[tasks.Length - 1].Result.TotalMilliseconds > 0);
} }
} }
[Test] [Test]
public void GetWithNullKey() public void GetWithNullKey()
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
var db = muxer.GetDatabase(); var db = muxer.GetDatabase();
string key = null; string key = null;
Assert.Throws<ArgumentException>( Assert.Throws<ArgumentException>(
() => db.StringGet(key), () => db.StringGet(key),
"A null key is not valid in this context"); "A null key is not valid in this context");
} }
} }
[Test] [Test]
public void SetWithNullKey() public void SetWithNullKey()
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
var db = muxer.GetDatabase(); var db = muxer.GetDatabase();
string key = null, value = "abc"; string key = null, value = "abc";
Assert.Throws<ArgumentException>( Assert.Throws<ArgumentException>(
() => db.StringSet(key, value), () => db.StringSet(key, value),
"A null key is not valid in this context"); "A null key is not valid in this context");
} }
} }
[Test] [Test]
public void SetWithNullValue() public void SetWithNullValue()
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
var db = muxer.GetDatabase(); var db = muxer.GetDatabase();
string key = Me(), value = null; string key = Me(), value = null;
db.KeyDelete(key, CommandFlags.FireAndForget); db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget); db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key)); Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value); db.StringSet(key, value);
var actual = (string)db.StringGet(key); var actual = (string)db.StringGet(key);
Assert.IsNull(actual); Assert.IsNull(actual);
Assert.IsFalse(db.KeyExists(key)); Assert.IsFalse(db.KeyExists(key));
} }
} }
[Test] [Test]
public void SetWithDefaultValue() public void SetWithDefaultValue()
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
var db = muxer.GetDatabase(); var db = muxer.GetDatabase();
string key = Me(); string key = Me();
var value = default(RedisValue); // this is kinda 0... ish var value = default(RedisValue); // this is kinda 0... ish
db.KeyDelete(key, CommandFlags.FireAndForget); db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget); db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key)); Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value); db.StringSet(key, value);
var actual = (string)db.StringGet(key); var actual = (string)db.StringGet(key);
Assert.IsNull(actual); Assert.IsNull(actual);
Assert.IsFalse(db.KeyExists(key)); Assert.IsFalse(db.KeyExists(key));
} }
} }
[Test] [Test]
public void SetWithZeroValue() public void SetWithZeroValue()
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
var db = muxer.GetDatabase(); var db = muxer.GetDatabase();
string key = Me(); string key = Me();
long value = 0; long value = 0;
db.KeyDelete(key, CommandFlags.FireAndForget); db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget); db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key)); Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value); db.StringSet(key, value);
var actual = (string)db.StringGet(key); var actual = (string)db.StringGet(key);
Assert.AreEqual("0", actual); Assert.AreEqual("0", actual);
Assert.IsTrue(db.KeyExists(key)); Assert.IsTrue(db.KeyExists(key));
} }
} }
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void GetSetAsync(bool preserveOrder) public void GetSetAsync(bool preserveOrder)
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
RedisKey key = Me(); RedisKey key = Me();
var d0 = conn.KeyDeleteAsync(key); var d0 = conn.KeyDeleteAsync(key);
var d1 = conn.KeyDeleteAsync(key); var d1 = conn.KeyDeleteAsync(key);
var g1 = conn.StringGetAsync(key); var g1 = conn.StringGetAsync(key);
var s1 = conn.StringSetAsync(key, "123"); var s1 = conn.StringSetAsync(key, "123");
var g2 = conn.StringGetAsync(key); var g2 = conn.StringGetAsync(key);
var d2 = conn.KeyDeleteAsync(key); var d2 = conn.KeyDeleteAsync(key);
muxer.Wait(d0); muxer.Wait(d0);
Assert.IsFalse(muxer.Wait(d1)); Assert.IsFalse(muxer.Wait(d1));
Assert.IsNull((string)muxer.Wait(g1)); Assert.IsNull((string)muxer.Wait(g1));
Assert.IsTrue(muxer.Wait(g1).IsNull); Assert.IsTrue(muxer.Wait(g1).IsNull);
muxer.Wait(s1); muxer.Wait(s1);
Assert.AreEqual("123", (string)muxer.Wait(g2)); Assert.AreEqual("123", (string)muxer.Wait(g2));
Assert.AreEqual(123, (int)muxer.Wait(g2)); Assert.AreEqual(123, (int)muxer.Wait(g2));
Assert.IsFalse(muxer.Wait(g2).IsNull); Assert.IsFalse(muxer.Wait(g2).IsNull);
Assert.IsTrue(muxer.Wait(d2)); Assert.IsTrue(muxer.Wait(d2));
} }
} }
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void GetSetSync(bool preserveOrder) public void GetSetSync(bool preserveOrder)
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
RedisKey key = Me(); RedisKey key = Me();
conn.KeyDelete(key); conn.KeyDelete(key);
var d1 = conn.KeyDelete(key); var d1 = conn.KeyDelete(key);
var g1 = conn.StringGet(key); var g1 = conn.StringGet(key);
conn.StringSet(key, "123"); conn.StringSet(key, "123");
var g2 = conn.StringGet(key); var g2 = conn.StringGet(key);
var d2 = conn.KeyDelete(key); var d2 = conn.KeyDelete(key);
Assert.IsFalse(d1); Assert.IsFalse(d1);
Assert.IsNull((string)g1); Assert.IsNull((string)g1);
Assert.IsTrue(g1.IsNull); Assert.IsTrue(g1.IsNull);
Assert.AreEqual("123", (string)g2); Assert.AreEqual("123", (string)g2);
Assert.AreEqual(123, (int)g2); Assert.AreEqual(123, (int)g2);
Assert.IsFalse(g2.IsNull); Assert.IsFalse(g2.IsNull);
Assert.IsTrue(d2); Assert.IsTrue(d2);
} }
} }
[Test] [Test]
[TestCase(true, true)] [TestCase(true, true)]
[TestCase(true, false)] [TestCase(true, false)]
[TestCase(false, true)] [TestCase(false, true)]
[TestCase(false, false)] [TestCase(false, false)]
public void MassiveBulkOpsAsync(bool preserveOrder, bool withContinuation) public void MassiveBulkOpsAsync(bool preserveOrder, bool withContinuation)
{ {
#if DEBUG #if DEBUG
var oldAsyncCompletionCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount(); var oldAsyncCompletionCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
#endif #endif
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
RedisKey key = "MBOA"; RedisKey key = "MBOA";
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
muxer.Wait(conn.PingAsync()); muxer.Wait(conn.PingAsync());
#if DNXCORE50 #if DNXCORE50
int number = 0; int number = 0;
#endif #endif
Action<Task> nonTrivial = delegate Action<Task> nonTrivial = delegate
{ {
#if !DNXCORE50 #if !DNXCORE50
Thread.SpinWait(5); Thread.SpinWait(5);
#else #else
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
number++; number++;
} }
#endif #endif
}; };
var watch = Stopwatch.StartNew(); var watch = Stopwatch.StartNew();
for (int i = 0; i <= AsyncOpsQty; i++) for (int i = 0; i <= AsyncOpsQty; i++)
{ {
var t = conn.StringSetAsync(key, i); var t = conn.StringSetAsync(key, i);
if (withContinuation) t.ContinueWith(nonTrivial); if (withContinuation) t.ContinueWith(nonTrivial);
} }
int val = (int)muxer.Wait(conn.StringGetAsync(key)); int val = (int)muxer.Wait(conn.StringGetAsync(key));
Assert.AreEqual(AsyncOpsQty, val); Assert.AreEqual(AsyncOpsQty, val);
watch.Stop(); watch.Stop();
Console.WriteLine("{2}: Time for {0} ops: {1}ms ({3}, {4}); ops/s: {5}", AsyncOpsQty, watch.ElapsedMilliseconds, Me(), Console.WriteLine("{2}: Time for {0} ops: {1}ms ({3}, {4}); ops/s: {5}", AsyncOpsQty, watch.ElapsedMilliseconds, Me(),
withContinuation ? "with continuation" : "no continuation", preserveOrder ? "preserve order" : "any order", withContinuation ? "with continuation" : "no continuation", preserveOrder ? "preserve order" : "any order",
AsyncOpsQty / watch.Elapsed.TotalSeconds); AsyncOpsQty / watch.Elapsed.TotalSeconds);
#if DEBUG #if DEBUG
Console.WriteLine("Async completion workers: " + (ConnectionMultiplexer.GetAsyncCompletionWorkerCount() - oldAsyncCompletionCount)); Console.WriteLine("Async completion workers: " + (ConnectionMultiplexer.GetAsyncCompletionWorkerCount() - oldAsyncCompletionCount));
#endif #endif
} }
} }
[Test] [Test]
[TestCase(false, false)] [TestCase(false, false)]
[TestCase(true, true)] [TestCase(true, true)]
[TestCase(true, false)] [TestCase(true, false)]
public void GetWithExpiry(bool exists, bool hasExpiry) public void GetWithExpiry(bool exists, bool hasExpiry)
{ {
using(var conn = Create()) using(var conn = Create())
{ {
var db = conn.GetDatabase(); var db = conn.GetDatabase();
RedisKey key = Me(); RedisKey key = Me();
db.KeyDelete(key); db.KeyDelete(key);
if (exists) if (exists)
{ {
if (hasExpiry) if (hasExpiry)
db.StringSet(key, "val", TimeSpan.FromMinutes(5)); db.StringSet(key, "val", TimeSpan.FromMinutes(5));
else else
db.StringSet(key, "val"); db.StringSet(key, "val");
} }
var async = db.StringGetWithExpiryAsync(key); var async = db.StringGetWithExpiryAsync(key);
var syncResult = db.StringGetWithExpiry(key); var syncResult = db.StringGetWithExpiry(key);
var asyncResult = db.Wait(async); var asyncResult = db.Wait(async);
if(exists) if(exists)
{ {
Assert.AreEqual("val", (string)asyncResult.Value); Assert.AreEqual("val", (string)asyncResult.Value);
Assert.AreEqual(hasExpiry, asyncResult.Expiry.HasValue); Assert.AreEqual(hasExpiry, asyncResult.Expiry.HasValue);
if (hasExpiry) Assert.IsTrue(asyncResult.Expiry.Value.TotalMinutes >= 4.9 && asyncResult.Expiry.Value.TotalMinutes <= 5); if (hasExpiry) Assert.IsTrue(asyncResult.Expiry.Value.TotalMinutes >= 4.9 && asyncResult.Expiry.Value.TotalMinutes <= 5);
Assert.AreEqual("val", (string)syncResult.Value); Assert.AreEqual("val", (string)syncResult.Value);
Assert.AreEqual(hasExpiry, syncResult.Expiry.HasValue); Assert.AreEqual(hasExpiry, syncResult.Expiry.HasValue);
if (hasExpiry) Assert.IsTrue(syncResult.Expiry.Value.TotalMinutes >= 4.9 && syncResult.Expiry.Value.TotalMinutes <= 5); if (hasExpiry) Assert.IsTrue(syncResult.Expiry.Value.TotalMinutes >= 4.9 && syncResult.Expiry.Value.TotalMinutes <= 5);
} }
else else
{ {
Assert.IsTrue(asyncResult.Value.IsNull); Assert.IsTrue(asyncResult.Value.IsNull);
Assert.IsFalse(asyncResult.Expiry.HasValue); Assert.IsFalse(asyncResult.Expiry.HasValue);
Assert.IsTrue(syncResult.Value.IsNull); Assert.IsTrue(syncResult.Value.IsNull);
Assert.IsFalse(syncResult.Expiry.HasValue); Assert.IsFalse(syncResult.Expiry.HasValue);
} }
} }
} }
[Test] [Test]
public void GetWithExpiryWrongTypeAsync() public void GetWithExpiryWrongTypeAsync()
{ {
using (var conn = Create()) using (var conn = Create())
{ {
var db = conn.GetDatabase(); var db = conn.GetDatabase();
RedisKey key = Me(); RedisKey key = Me();
db.KeyDelete(key); db.KeyDelete(key);
db.SetAdd(key, "abc"); db.SetAdd(key, "abc");
Assert.Throws<RedisServerException>(() => Assert.Throws<RedisServerException>(() =>
{ {
try try
{ {
var async = db.Wait(db.StringGetWithExpiryAsync(key)); var async = db.Wait(db.StringGetWithExpiryAsync(key));
} }
catch (AggregateException ex) catch (AggregateException ex)
{ {
throw ex.InnerExceptions[0]; throw ex.InnerExceptions[0];
} }
Assert.Fail(); Assert.Fail();
}, },
"A null key is not valid in this context"); "A null key is not valid in this context");
} }
} }
[Test] [Test]
public void GetWithExpiryWrongTypeSync() public void GetWithExpiryWrongTypeSync()
{ {
Assert.Throws<RedisServerException>(() => Assert.Throws<RedisServerException>(() =>
{ {
using (var conn = Create()) using (var conn = Create())
{ {
var db = conn.GetDatabase(); var db = conn.GetDatabase();
RedisKey key = Me(); RedisKey key = Me();
db.KeyDelete(key); db.KeyDelete(key);
db.SetAdd(key, "abc"); db.SetAdd(key, "abc");
db.StringGetWithExpiry(key); db.StringGetWithExpiry(key);
Assert.Fail(); Assert.Fail();
} }
}, },
"WRONGTYPE Operation against a key holding the wrong kind of value"); "WRONGTYPE Operation against a key holding the wrong kind of value");
} }
#if FEATURE_BOOKSLEEVE #if FEATURE_BOOKSLEEVE
[Test] [Test]
[TestCase(true, true, ResultCompletionMode.ConcurrentIfContinuation)] [TestCase(true, true, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(true, false, ResultCompletionMode.ConcurrentIfContinuation)] [TestCase(true, false, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(false, true, ResultCompletionMode.ConcurrentIfContinuation)] [TestCase(false, true, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(false, false, ResultCompletionMode.ConcurrentIfContinuation)] [TestCase(false, false, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(true, true, ResultCompletionMode.Concurrent)] [TestCase(true, true, ResultCompletionMode.Concurrent)]
[TestCase(true, false, ResultCompletionMode.Concurrent)] [TestCase(true, false, ResultCompletionMode.Concurrent)]
[TestCase(false, true, ResultCompletionMode.Concurrent)] [TestCase(false, true, ResultCompletionMode.Concurrent)]
[TestCase(false, false, ResultCompletionMode.Concurrent)] [TestCase(false, false, ResultCompletionMode.Concurrent)]
[TestCase(true, true, ResultCompletionMode.PreserveOrder)] [TestCase(true, true, ResultCompletionMode.PreserveOrder)]
[TestCase(true, false, ResultCompletionMode.PreserveOrder)] [TestCase(true, false, ResultCompletionMode.PreserveOrder)]
[TestCase(false, true, ResultCompletionMode.PreserveOrder)] [TestCase(false, true, ResultCompletionMode.PreserveOrder)]
[TestCase(false, false, ResultCompletionMode.PreserveOrder)] [TestCase(false, false, ResultCompletionMode.PreserveOrder)]
public void MassiveBulkOpsAsyncOldStyle(bool withContinuation, bool suspendFlush, ResultCompletionMode completionMode) public void MassiveBulkOpsAsyncOldStyle(bool withContinuation, bool suspendFlush, ResultCompletionMode completionMode)
{ {
using (var conn = GetOldStyleConnection()) using (var conn = GetOldStyleConnection())
{ {
const int db = 0; const int db = 0;
string key = "MBOQ"; string key = "MBOQ";
conn.CompletionMode = completionMode; conn.CompletionMode = completionMode;
conn.Wait(conn.Server.Ping()); conn.Wait(conn.Server.Ping());
Action<Task> nonTrivial = delegate Action<Task> nonTrivial = delegate
{ {
Thread.SpinWait(5); Thread.SpinWait(5);
}; };
var watch = Stopwatch.StartNew(); var watch = Stopwatch.StartNew();
if (suspendFlush) conn.SuspendFlush(); if (suspendFlush) conn.SuspendFlush();
try try
{ {
for (int i = 0; i <= AsyncOpsQty; i++) for (int i = 0; i <= AsyncOpsQty; i++)
{ {
var t = conn.Strings.Set(db, key, i); var t = conn.Strings.Set(db, key, i);
if (withContinuation) t.ContinueWith(nonTrivial); if (withContinuation) t.ContinueWith(nonTrivial);
} }
} finally } finally
{ {
if (suspendFlush) conn.ResumeFlush(); if (suspendFlush) conn.ResumeFlush();
} }
int val = (int)conn.Wait(conn.Strings.GetInt64(db, key)); int val = (int)conn.Wait(conn.Strings.GetInt64(db, key));
Assert.AreEqual(AsyncOpsQty, val); Assert.AreEqual(AsyncOpsQty, val);
watch.Stop(); watch.Stop();
Console.WriteLine("{2}: Time for {0} ops: {1}ms ({3}, {4}, {5}); ops/s: {6}", AsyncOpsQty, watch.ElapsedMilliseconds, Me(), Console.WriteLine("{2}: Time for {0} ops: {1}ms ({3}, {4}, {5}); ops/s: {6}", AsyncOpsQty, watch.ElapsedMilliseconds, Me(),
withContinuation ? "with continuation" : "no continuation", withContinuation ? "with continuation" : "no continuation",
suspendFlush ? "suspend flush" : "flush at whim", suspendFlush ? "suspend flush" : "flush at whim",
completionMode, AsyncOpsQty / watch.Elapsed.TotalSeconds); completionMode, AsyncOpsQty / watch.Elapsed.TotalSeconds);
} }
} }
#endif #endif
[Test] [Test]
[TestCase(true, 1)] [TestCase(true, 1)]
[TestCase(false, 1)] [TestCase(false, 1)]
[TestCase(true, 5)] [TestCase(true, 5)]
[TestCase(false, 5)] [TestCase(false, 5)]
[TestCase(true, 10)] [TestCase(true, 10)]
[TestCase(false, 10)] [TestCase(false, 10)]
[TestCase(true, 50)] [TestCase(true, 50)]
[TestCase(false, 50)] [TestCase(false, 50)]
public void MassiveBulkOpsSync(bool preserveOrder, int threads) public void MassiveBulkOpsSync(bool preserveOrder, int threads)
{ {
int workPerThread = SyncOpsQty / threads; int workPerThread = SyncOpsQty / threads;
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
RedisKey key = "MBOS"; RedisKey key = "MBOS";
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
conn.KeyDelete(key); conn.KeyDelete(key);
#if DEBUG #if DEBUG
long oldAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount(); long oldAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
long oldWorkerCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount(); long oldWorkerCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
#endif #endif
var timeTaken = RunConcurrent(delegate var timeTaken = RunConcurrent(delegate
{ {
for (int i = 0; i < workPerThread; i++) for (int i = 0; i < workPerThread; i++)
{ {
conn.StringIncrement(key); conn.StringIncrement(key);
} }
}, threads); }, threads);
int val = (int)conn.StringGet(key); int val = (int)conn.StringGet(key);
Assert.AreEqual(workPerThread * threads, val); Assert.AreEqual(workPerThread * threads, val);
Console.WriteLine("{2}: Time for {0} ops on {4} threads: {1}ms ({3}); ops/s: {5}", Console.WriteLine("{2}: Time for {0} ops on {4} threads: {1}ms ({3}); ops/s: {5}",
threads * workPerThread, timeTaken.TotalMilliseconds, Me() threads * workPerThread, timeTaken.TotalMilliseconds, Me()
, preserveOrder ? "preserve order" : "any order", threads, (workPerThread * threads) / timeTaken.TotalSeconds); , preserveOrder ? "preserve order" : "any order", threads, (workPerThread * threads) / timeTaken.TotalSeconds);
#if DEBUG #if DEBUG
long newAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount(); long newAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
long newWorkerCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount(); long newWorkerCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
Console.WriteLine("ResultBox allocations: {0}; workers {1}", newAlloc - oldAlloc, newWorkerCount - oldWorkerCount); Console.WriteLine("ResultBox allocations: {0}; workers {1}", newAlloc - oldAlloc, newWorkerCount - oldWorkerCount);
Assert.IsTrue(newAlloc - oldAlloc <= 2 * threads, "number of box allocations"); Assert.IsTrue(newAlloc - oldAlloc <= 2 * threads, "number of box allocations");
#endif #endif
} }
} }
#if FEATURE_BOOKSLEEVE #if FEATURE_BOOKSLEEVE
[Test] [Test]
[TestCase(ResultCompletionMode.Concurrent, 1)] [TestCase(ResultCompletionMode.Concurrent, 1)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 1)] [TestCase(ResultCompletionMode.ConcurrentIfContinuation, 1)]
[TestCase(ResultCompletionMode.PreserveOrder, 1)] [TestCase(ResultCompletionMode.PreserveOrder, 1)]
[TestCase(ResultCompletionMode.Concurrent, 5)] [TestCase(ResultCompletionMode.Concurrent, 5)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 5)] [TestCase(ResultCompletionMode.ConcurrentIfContinuation, 5)]
[TestCase(ResultCompletionMode.PreserveOrder, 5)] [TestCase(ResultCompletionMode.PreserveOrder, 5)]
[TestCase(ResultCompletionMode.Concurrent, 10)] [TestCase(ResultCompletionMode.Concurrent, 10)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 10)] [TestCase(ResultCompletionMode.ConcurrentIfContinuation, 10)]
[TestCase(ResultCompletionMode.PreserveOrder, 10)] [TestCase(ResultCompletionMode.PreserveOrder, 10)]
[TestCase(ResultCompletionMode.Concurrent, 50)] [TestCase(ResultCompletionMode.Concurrent, 50)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 50)] [TestCase(ResultCompletionMode.ConcurrentIfContinuation, 50)]
[TestCase(ResultCompletionMode.PreserveOrder, 50)] [TestCase(ResultCompletionMode.PreserveOrder, 50)]
public void MassiveBulkOpsSyncOldStyle(ResultCompletionMode completionMode, int threads) public void MassiveBulkOpsSyncOldStyle(ResultCompletionMode completionMode, int threads)
{ {
int workPerThread = SyncOpsQty / threads; int workPerThread = SyncOpsQty / threads;
using (var conn = GetOldStyleConnection()) using (var conn = GetOldStyleConnection())
{ {
const int db = 0; const int db = 0;
string key = "MBOQ"; string key = "MBOQ";
conn.CompletionMode = completionMode; conn.CompletionMode = completionMode;
conn.Wait(conn.Keys.Remove(db, key)); conn.Wait(conn.Keys.Remove(db, key));
var timeTaken = RunConcurrent(delegate var timeTaken = RunConcurrent(delegate
{ {
for (int i = 0; i < workPerThread; i++) for (int i = 0; i < workPerThread; i++)
{ {
conn.Wait(conn.Strings.Increment(db, key)); conn.Wait(conn.Strings.Increment(db, key));
} }
}, threads); }, threads);
int val = (int)conn.Wait(conn.Strings.GetInt64(db, key)); int val = (int)conn.Wait(conn.Strings.GetInt64(db, key));
Assert.AreEqual(workPerThread * threads, val); Assert.AreEqual(workPerThread * threads, val);
Console.WriteLine("{2}: Time for {0} ops on {4} threads: {1}ms ({3}); ops/s: {5}", workPerThread * threads, timeTaken.TotalMilliseconds, Me(), Console.WriteLine("{2}: Time for {0} ops on {4} threads: {1}ms ({3}); ops/s: {5}", workPerThread * threads, timeTaken.TotalMilliseconds, Me(),
completionMode, threads, (workPerThread * threads) / timeTaken.TotalSeconds); completionMode, threads, (workPerThread * threads) / timeTaken.TotalSeconds);
} }
} }
#endif #endif
[Test] [Test]
[TestCase(true, 1)] [TestCase(true, 1)]
[TestCase(false, 1)] [TestCase(false, 1)]
[TestCase(true, 5)] [TestCase(true, 5)]
[TestCase(false, 5)] [TestCase(false, 5)]
public void MassiveBulkOpsFireAndForget(bool preserveOrder, int threads) public void MassiveBulkOpsFireAndForget(bool preserveOrder, int threads)
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
#if DEBUG #if DEBUG
long oldAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount(); long oldAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
#endif #endif
RedisKey key = "MBOF"; RedisKey key = "MBOF";
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
conn.Ping(); conn.Ping();
conn.KeyDelete(key, CommandFlags.FireAndForget); conn.KeyDelete(key, CommandFlags.FireAndForget);
int perThread = AsyncOpsQty / threads; int perThread = AsyncOpsQty / threads;
var elapsed = RunConcurrent(delegate var elapsed = RunConcurrent(delegate
{ {
for (int i = 0; i < perThread; i++) for (int i = 0; i < perThread; i++)
{ {
conn.StringIncrement(key, flags: CommandFlags.FireAndForget); conn.StringIncrement(key, flags: CommandFlags.FireAndForget);
} }
conn.Ping(); conn.Ping();
}, threads); }, threads);
var val = (long)conn.StringGet(key); var val = (long)conn.StringGet(key);
Assert.AreEqual(perThread * threads, val); Assert.AreEqual(perThread * threads, val);
Console.WriteLine("{2}: Time for {0} ops over {5} threads: {1:###,###}ms ({3}); ops/s: {4:###,###,##0}", Console.WriteLine("{2}: Time for {0} ops over {5} threads: {1:###,###}ms ({3}); ops/s: {4:###,###,##0}",
val, elapsed.TotalMilliseconds, Me(), val, elapsed.TotalMilliseconds, Me(),
preserveOrder ? "preserve order" : "any order", preserveOrder ? "preserve order" : "any order",
val / elapsed.TotalSeconds, threads); val / elapsed.TotalSeconds, threads);
#if DEBUG #if DEBUG
long newAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount(); long newAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
Console.WriteLine("ResultBox allocations: {0}", Console.WriteLine("ResultBox allocations: {0}",
newAlloc - oldAlloc); newAlloc - oldAlloc);
Assert.IsTrue(newAlloc - oldAlloc <= 4); Assert.IsTrue(newAlloc - oldAlloc <= 4);
#endif #endif
} }
} }
#if DEBUG #if DEBUG
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void TestQuit(bool preserveOrder) public void TestQuit(bool preserveOrder)
{ {
SetExpectedAmbientFailureCount(1); SetExpectedAmbientFailureCount(1);
using (var muxer = Create(allowAdmin: true)) using (var muxer = Create(allowAdmin: true))
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
var db = muxer.GetDatabase(); var db = muxer.GetDatabase();
string key = Guid.NewGuid().ToString(); string key = Guid.NewGuid().ToString();
db.KeyDelete(key, CommandFlags.FireAndForget); db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, key, flags: CommandFlags.FireAndForget); db.StringSet(key, key, flags: CommandFlags.FireAndForget);
GetServer(muxer).Quit(CommandFlags.FireAndForget); GetServer(muxer).Quit(CommandFlags.FireAndForget);
var watch = Stopwatch.StartNew(); var watch = Stopwatch.StartNew();
try try
{ {
db.Ping(); db.Ping();
Assert.Fail(); Assert.Fail();
} }
catch (RedisConnectionException) { } catch (RedisConnectionException) { }
watch.Stop(); watch.Stop();
Console.WriteLine("Time to notice quit: {0}ms ({1})", watch.ElapsedMilliseconds, Console.WriteLine("Time to notice quit: {0}ms ({1})", watch.ElapsedMilliseconds,
preserveOrder ? "preserve order" : "any order"); preserveOrder ? "preserve order" : "any order");
Thread.Sleep(20); Thread.Sleep(20);
Debug.WriteLine("Pinging..."); Debug.WriteLine("Pinging...");
Assert.AreEqual(key, (string)db.StringGet(key)); Assert.AreEqual(key, (string)db.StringGet(key));
} }
} }
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void TestSevered(bool preserveOrder) public void TestSevered(bool preserveOrder)
{ {
SetExpectedAmbientFailureCount(2); SetExpectedAmbientFailureCount(2);
using (var muxer = Create(allowAdmin: true)) using (var muxer = Create(allowAdmin: true))
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
var db = muxer.GetDatabase(); var db = muxer.GetDatabase();
string key = Guid.NewGuid().ToString(); string key = Guid.NewGuid().ToString();
db.KeyDelete(key, CommandFlags.FireAndForget); db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, key, flags: CommandFlags.FireAndForget); db.StringSet(key, key, flags: CommandFlags.FireAndForget);
GetServer(muxer).SimulateConnectionFailure(); GetServer(muxer).SimulateConnectionFailure();
var watch = Stopwatch.StartNew(); var watch = Stopwatch.StartNew();
db.Ping(); db.Ping();
watch.Stop(); watch.Stop();
Console.WriteLine("Time to re-establish: {0}ms ({1})", watch.ElapsedMilliseconds, Console.WriteLine("Time to re-establish: {0}ms ({1})", watch.ElapsedMilliseconds,
preserveOrder ? "preserve order" : "any order"); preserveOrder ? "preserve order" : "any order");
Thread.Sleep(20); Thread.Sleep(20);
Debug.WriteLine("Pinging..."); Debug.WriteLine("Pinging...");
Assert.AreEqual(key, (string)db.StringGet(key)); Assert.AreEqual(key, (string)db.StringGet(key));
} }
} }
#endif #endif
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void IncrAsync(bool preserveOrder) public void IncrAsync(bool preserveOrder)
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
RedisKey key = Me(); RedisKey key = Me();
conn.KeyDelete(key, CommandFlags.FireAndForget); conn.KeyDelete(key, CommandFlags.FireAndForget);
var nix = conn.KeyExistsAsync(key); var nix = conn.KeyExistsAsync(key);
var a = conn.StringGetAsync(key); var a = conn.StringGetAsync(key);
var b = conn.StringIncrementAsync(key); var b = conn.StringIncrementAsync(key);
var c = conn.StringGetAsync(key); var c = conn.StringGetAsync(key);
var d = conn.StringIncrementAsync(key, 10); var d = conn.StringIncrementAsync(key, 10);
var e = conn.StringGetAsync(key); var e = conn.StringGetAsync(key);
var f = conn.StringDecrementAsync(key, 11); var f = conn.StringDecrementAsync(key, 11);
var g = conn.StringGetAsync(key); var g = conn.StringGetAsync(key);
var h = conn.KeyExistsAsync(key); var h = conn.KeyExistsAsync(key);
Assert.IsFalse(muxer.Wait(nix)); Assert.IsFalse(muxer.Wait(nix));
Assert.IsTrue(muxer.Wait(a).IsNull); Assert.IsTrue(muxer.Wait(a).IsNull);
Assert.AreEqual(0, (long)muxer.Wait(a)); Assert.AreEqual(0, (long)muxer.Wait(a));
Assert.AreEqual(1, muxer.Wait(b)); Assert.AreEqual(1, muxer.Wait(b));
Assert.AreEqual(1, (long)muxer.Wait(c)); Assert.AreEqual(1, (long)muxer.Wait(c));
Assert.AreEqual(11, muxer.Wait(d)); Assert.AreEqual(11, muxer.Wait(d));
Assert.AreEqual(11, (long)muxer.Wait(e)); Assert.AreEqual(11, (long)muxer.Wait(e));
Assert.AreEqual(0, muxer.Wait(f)); Assert.AreEqual(0, muxer.Wait(f));
Assert.AreEqual(0, (long)muxer.Wait(g)); Assert.AreEqual(0, (long)muxer.Wait(g));
Assert.IsTrue(muxer.Wait(h)); Assert.IsTrue(muxer.Wait(h));
} }
} }
[Test] [Test]
[TestCase(true)] [TestCase(true)]
[TestCase(false)] [TestCase(false)]
public void IncrSync(bool preserveOrder) public void IncrSync(bool preserveOrder)
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
muxer.PreserveAsyncOrder = preserveOrder; muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase(); var conn = muxer.GetDatabase();
RedisKey key = Me(); RedisKey key = Me();
conn.KeyDelete(key, CommandFlags.FireAndForget); conn.KeyDelete(key, CommandFlags.FireAndForget);
var nix = conn.KeyExists(key); var nix = conn.KeyExists(key);
var a = conn.StringGet(key); var a = conn.StringGet(key);
var b = conn.StringIncrement(key); var b = conn.StringIncrement(key);
var c = conn.StringGet(key); var c = conn.StringGet(key);
var d = conn.StringIncrement(key, 10); var d = conn.StringIncrement(key, 10);
var e = conn.StringGet(key); var e = conn.StringGet(key);
var f = conn.StringDecrement(key, 11); var f = conn.StringDecrement(key, 11);
var g = conn.StringGet(key); var g = conn.StringGet(key);
var h = conn.KeyExists(key); var h = conn.KeyExists(key);
Assert.IsFalse(nix); Assert.IsFalse(nix);
Assert.IsTrue(a.IsNull); Assert.IsTrue(a.IsNull);
Assert.AreEqual(0, (long)a); Assert.AreEqual(0, (long)a);
Assert.AreEqual(1, b); Assert.AreEqual(1, b);
Assert.AreEqual(1, (long)c); Assert.AreEqual(1, (long)c);
Assert.AreEqual(11, d); Assert.AreEqual(11, d);
Assert.AreEqual(11, (long)e); Assert.AreEqual(11, (long)e);
Assert.AreEqual(0, f); Assert.AreEqual(0, f);
Assert.AreEqual(0, (long)g); Assert.AreEqual(0, (long)g);
Assert.IsTrue(h); Assert.IsTrue(h);
} }
} }
[Test] [Test]
public void IncrDifferentSizes() public void IncrDifferentSizes()
{ {
using (var muxer = Create()) using (var muxer = Create())
{ {
var db = muxer.GetDatabase(); var db = muxer.GetDatabase();
RedisKey key = Me(); RedisKey key = Me();
db.KeyDelete(key, CommandFlags.FireAndForget); db.KeyDelete(key, CommandFlags.FireAndForget);
int expected = 0; int expected = 0;
Incr(db, key, -129019, ref expected); Incr(db, key, -129019, ref expected);
Incr(db, key, -10023, ref expected); Incr(db, key, -10023, ref expected);
Incr(db, key, -9933, ref expected); Incr(db, key, -9933, ref expected);
Incr(db, key, -23, ref expected); Incr(db, key, -23, ref expected);
Incr(db, key, -7, ref expected); Incr(db, key, -7, ref expected);
Incr(db, key, -1, ref expected); Incr(db, key, -1, ref expected);
Incr(db, key, 0, ref expected); Incr(db, key, 0, ref expected);
Incr(db, key, 1, ref expected); Incr(db, key, 1, ref expected);
Incr(db, key, 9, ref expected); Incr(db, key, 9, ref expected);
Incr(db, key, 11, ref expected); Incr(db, key, 11, ref expected);
Incr(db, key, 345, ref expected); Incr(db, key, 345, ref expected);
Incr(db, key, 4982, ref expected); Incr(db, key, 4982, ref expected);
Incr(db, key, 13091, ref expected); Incr(db, key, 13091, ref expected);
Incr(db, key, 324092, ref expected); Incr(db, key, 324092, ref expected);
Assert.AreNotEqual(0, expected); Assert.AreNotEqual(0, expected);
var sum = (long)db.StringGet(key); var sum = (long)db.StringGet(key);
Assert.AreEqual(expected, sum); Assert.AreEqual(expected, sum);
} }
} }
private void Incr(IDatabase database, RedisKey key, int delta, ref int total) private void Incr(IDatabase database, RedisKey key, int delta, ref int total)
{ {
database.StringIncrement(key, delta, CommandFlags.FireAndForget); database.StringIncrement(key, delta, CommandFlags.FireAndForget);
total += delta; total += delta;
} }
[Test] [Test]
public void WrappedDatabasePrefixIntegration() public void WrappedDatabasePrefixIntegration()
{ {
using (var conn = Create()) using (var conn = Create())
{ {
var db = conn.GetDatabase().WithKeyPrefix("abc"); var db = conn.GetDatabase().WithKeyPrefix("abc");
db.KeyDelete("count"); db.KeyDelete("count");
db.StringIncrement("count"); db.StringIncrement("count");
db.StringIncrement("count"); db.StringIncrement("count");
db.StringIncrement("count"); db.StringIncrement("count");
int count = (int)conn.GetDatabase().StringGet("abccount"); int count = (int)conn.GetDatabase().StringGet("abccount");
Assert.AreEqual(3, count); Assert.AreEqual(3, count);
} }
} }
} }
} }
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using StackExchange.Redis.KeyspaceIsolation; using StackExchange.Redis.KeyspaceIsolation;
namespace StackExchange.Redis.Tests namespace StackExchange.Redis.Tests
{ {
[TestFixture] [TestFixture]
public class WithKeyPrefixTests : TestBase public class WithKeyPrefixTests : TestBase
{ {
[Test] [Test]
public void BlankPrefixYieldsSame_Bytes() public void BlankPrefixYieldsSame_Bytes()
{ {
using (var conn = Create()) using (var conn = Create())
{ {
var raw = conn.GetDatabase(1); var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix(new byte[0]); var prefixed = raw.WithKeyPrefix(new byte[0]);
Assert.AreSame(raw, prefixed); Assert.AreSame(raw, prefixed);
} }
} }
[Test] [Test]
public void BlankPrefixYieldsSame_String() public void BlankPrefixYieldsSame_String()
{ {
using (var conn = Create()) using (var conn = Create())
{ {
var raw = conn.GetDatabase(1); var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix(""); var prefixed = raw.WithKeyPrefix("");
Assert.AreSame(raw, prefixed); Assert.AreSame(raw, prefixed);
} }
} }
[Test] [Test]
public void NullPrefixIsError_Bytes() public void NullPrefixIsError_Bytes()
{ {
Assert.Throws<ArgumentNullException>(() => { Assert.Throws<ArgumentNullException>(() => {
using (var conn = Create()) using (var conn = Create())
{ {
var raw = conn.GetDatabase(1); var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix((byte[])null); var prefixed = raw.WithKeyPrefix((byte[])null);
} }
}); });
} }
[Test]
[Test] public void NullPrefixIsError_String()
public void NullPrefixIsError_String() {
{ Assert.Throws<ArgumentNullException>(() => {
Assert.Throws<ArgumentNullException>(() => { using (var conn = Create())
using (var conn = Create()) {
{ var raw = conn.GetDatabase(1);
var raw = conn.GetDatabase(1); var prefixed = raw.WithKeyPrefix((string)null);
var prefixed = raw.WithKeyPrefix((string)null); }
} });
}); }
}
[Test]
[Test] [TestCase("abc")]
[TestCase("abc")] [TestCase("")]
[TestCase("")] [TestCase(null)]
[TestCase(null)] public void NullDatabaseIsError(string prefix)
public void NullDatabaseIsError(string prefix) {
{ Assert.Throws<ArgumentNullException>(() => {
Assert.Throws<ArgumentNullException>(() => { IDatabase raw = null;
IDatabase raw = null; var prefixed = raw.WithKeyPrefix(prefix);
var prefixed = raw.WithKeyPrefix(prefix); });
}); }
} [Test]
public void BasicSmokeTest()
[Test] {
public void BasicSmokeTest() using(var conn = Create())
{ {
using(var conn = Create()) var raw = conn.GetDatabase(1);
{
var raw = conn.GetDatabase(1); var foo = raw.WithKeyPrefix("foo");
var foobar = foo.WithKeyPrefix("bar");
var foo = raw.WithKeyPrefix("foo");
var foobar = foo.WithKeyPrefix("bar"); string key = Me();
string key = Me(); string s = Guid.NewGuid().ToString(), t = Guid.NewGuid().ToString();
string s = Guid.NewGuid().ToString(), t = Guid.NewGuid().ToString(); foo.StringSet(key, s);
var val = (string)foo.StringGet(key);
foo.StringSet(key, s); Assert.AreEqual(s, val); // fooBasicSmokeTest
var val = (string)foo.StringGet(key);
Assert.AreEqual(s, val); // fooBasicSmokeTest foobar.StringSet(key, t);
val = (string)foobar.StringGet(key);
foobar.StringSet(key, t); Assert.AreEqual(t, val); // foobarBasicSmokeTest
val = (string)foobar.StringGet(key);
Assert.AreEqual(t, val); // foobarBasicSmokeTest val = (string)foo.StringGet("bar" + key);
Assert.AreEqual(t, val); // foobarBasicSmokeTest
val = (string)foo.StringGet("bar" + key);
Assert.AreEqual(t, val); // foobarBasicSmokeTest val = (string)raw.StringGet("foo" + key);
Assert.AreEqual(s, val); // fooBasicSmokeTest
val = (string)raw.StringGet("foo" + key);
Assert.AreEqual(s, val); // fooBasicSmokeTest val = (string)raw.StringGet("foobar" + key);
Assert.AreEqual(t, val); // foobarBasicSmokeTest
val = (string)raw.StringGet("foobar" + key); }
Assert.AreEqual(t, val); // foobarBasicSmokeTest }
} [Test]
} public void ConditionTest()
[Test] {
public void ConditionTest() using(var conn = Create())
{ {
using(var conn = Create()) var raw = conn.GetDatabase(2);
{
var raw = conn.GetDatabase(2); var foo = raw.WithKeyPrefix("tran:");
var foo = raw.WithKeyPrefix("tran:"); raw.KeyDelete("tran:abc");
raw.KeyDelete("tran:i");
raw.KeyDelete("tran:abc");
raw.KeyDelete("tran:i"); // execute while key exists
raw.StringSet("tran:abc", "def");
// execute while key exists var tran = foo.CreateTransaction();
raw.StringSet("tran:abc", "def"); tran.AddCondition(Condition.KeyExists("abc"));
var tran = foo.CreateTransaction(); tran.StringIncrementAsync("i");
tran.AddCondition(Condition.KeyExists("abc")); tran.Execute();
tran.StringIncrementAsync("i");
tran.Execute(); int i = (int)raw.StringGet("tran:i");
Assert.AreEqual(1, i);
int i = (int)raw.StringGet("tran:i");
Assert.AreEqual(1, i); // repeat without key
raw.KeyDelete("tran:abc");
// repeat without key tran = foo.CreateTransaction();
raw.KeyDelete("tran:abc"); tran.AddCondition(Condition.KeyExists("abc"));
tran = foo.CreateTransaction(); tran.StringIncrementAsync("i");
tran.AddCondition(Condition.KeyExists("abc")); tran.Execute();
tran.StringIncrementAsync("i");
tran.Execute(); i = (int)raw.StringGet("tran:i");
Assert.AreEqual(1, i);
i = (int)raw.StringGet("tran:i"); }
Assert.AreEqual(1, i); }
} }
} }
}
}
...@@ -16,7 +16,6 @@ public sealed class WrapperBaseTests ...@@ -16,7 +16,6 @@ public sealed class WrapperBaseTests
private Mock<IDatabaseAsync> mock; private Mock<IDatabaseAsync> mock;
private WrapperBase<IDatabaseAsync> wrapper; private WrapperBase<IDatabaseAsync> wrapper;
//[TestFixtureSetUp]
[OneTimeSetUp] [OneTimeSetUp]
public void Initialize() public void Initialize()
{ {
...@@ -891,4 +890,4 @@ public void StringSetRangeAsync() ...@@ -891,4 +890,4 @@ public void StringSetRangeAsync()
} }
} }
} }
#endif #endif
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EBF46088-E318-4D32-9EFB-01EF130A4554}</ProjectGuid> <ProjectGuid>{EBF46088-E318-4D32-9EFB-01EF130A4554}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace> <RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis.StrongName</AssemblyName> <AssemblyName>StackExchange.Redis.StrongName</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath> <OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants> <DefineConstants>TRACE;DEBUG;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Debug\StackExchange.Redis.StrongName.xml</DocumentationFile> <DocumentationFile>bin.snk\Debug\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath> <OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants> <DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile> <DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<OutputPath>bin.snk\Verbose\</OutputPath> <OutputPath>bin.snk\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants> <DefineConstants>TRACE;DEBUG;VERBOSE STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Verbose\StackExchange.Redis.StrongName.xml</DocumentationFile> <DocumentationFile>bin.snk\Verbose\StackExchange.Redis.StrongName.xml</DocumentationFile>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<OutputPath>bin.snk\LogOutput\</OutputPath> <OutputPath>bin.snk\LogOutput\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants> <DefineConstants>TRACE;DEBUG;LOGOUTPUT STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\LogOutput\StackExchange.Redis.StrongName.xml</DocumentationFile> <DocumentationFile>bin.snk\LogOutput\StackExchange.Redis.StrongName.xml</DocumentationFile>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<AssemblyOriginatorKeyFile>StackExchange.Redis.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StackExchange.Redis.snk</AssemblyOriginatorKeyFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath> <OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION</DefineConstants> <DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile> <DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.IO.Compression" /> <Reference Include="System.IO.Compression" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="StackExchange\Redis\Aggregate.cs" /> <Compile Include="StackExchange\Redis\Aggregate.cs" />
<Compile Include="StackExchange\Redis\ClientType.cs" /> <Compile Include="StackExchange\Redis\ClientType.cs" />
<Compile Include="StackExchange\Redis\Compat\ConvertHelper.cs" /> <Compile Include="StackExchange\Redis\Compat\ConvertHelper.cs" />
<Compile Include="StackExchange\Redis\Compat\VolatileWrapper.cs" /> <Compile Include="StackExchange\Redis\Compat\VolatileWrapper.cs" />
<Compile Include="StackExchange\Redis\ConcurrentProfileStorageCollection.cs" /> <Compile Include="StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.Profiling.cs"> <Compile Include="StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon> <DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="StackExchange\Redis\ExtensionMethods.cs" /> <Compile Include="StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="StackExchange\Redis\HashEntry.cs" /> <Compile Include="StackExchange\Redis\HashEntry.cs" />
<Compile Include="StackExchange\Redis\IConnectionMultiplexer.cs" /> <Compile Include="StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="StackExchange\Redis\InternalErrorEventArgs.cs" /> <Compile Include="StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\InternalRegexCompiledOption.cs" /> <Compile Include="StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="StackExchange\Redis\IProfiler.cs" /> <Compile Include="StackExchange\Redis\IProfiler.cs" />
<Compile Include="StackExchange\Redis\MigrateOptions.cs" /> <Compile Include="StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="StackExchange\Redis\ProfileContextTracker.cs" /> <Compile Include="StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="StackExchange\Redis\ProfileStorage.cs" /> <Compile Include="StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="StackExchange\Redis\LuaScript.cs" /> <Compile Include="StackExchange\Redis\LuaScript.cs" />
<Compile Include="StackExchange\Redis\RedisChannel.cs" /> <Compile Include="StackExchange\Redis\RedisChannel.cs" />
<Compile Include="StackExchange\Redis\Bitwise.cs" /> <Compile Include="StackExchange\Redis\Bitwise.cs" />
<Compile Include="StackExchange\Redis\ClientFlags.cs" /> <Compile Include="StackExchange\Redis\ClientFlags.cs" />
<Compile Include="StackExchange\Redis\ClientInfo.cs" /> <Compile Include="StackExchange\Redis\ClientInfo.cs" />
<Compile Include="StackExchange\Redis\ClusterConfiguration.cs" /> <Compile Include="StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="StackExchange\Redis\CommandTrace.cs" /> <Compile Include="StackExchange\Redis\CommandTrace.cs" />
<Compile Include="StackExchange\Redis\Condition.cs" /> <Compile Include="StackExchange\Redis\Condition.cs" />
<Compile Include="StackExchange\Redis\ConfigurationOptions.cs" /> <Compile Include="StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="StackExchange\Redis\ConnectionCounters.cs" /> <Compile Include="StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="StackExchange\Redis\ConnectionFailedEventArgs.cs" /> <Compile Include="StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="StackExchange\Redis\ConnectionFailureType.cs" /> <Compile Include="StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs"> <Compile Include="StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon> <DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="StackExchange\Redis\ConnectionType.cs" /> <Compile Include="StackExchange\Redis\ConnectionType.cs" />
<Compile Include="StackExchange\Redis\DebuggingAids.cs" /> <Compile Include="StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="StackExchange\Redis\EndPointCollection.cs" /> <Compile Include="StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="StackExchange\Redis\EndPointEventArgs.cs" /> <Compile Include="StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="StackExchange\Redis\ExceptionFactory.cs" /> <Compile Include="StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="StackExchange\Redis\Exclude.cs" /> <Compile Include="StackExchange\Redis\Exclude.cs" />
<Compile Include="StackExchange\Redis\ExportOptions.cs" /> <Compile Include="StackExchange\Redis\ExportOptions.cs" />
<Compile Include="StackExchange\Redis\Format.cs" /> <Compile Include="StackExchange\Redis\Format.cs" />
<Compile Include="StackExchange\Redis\IBatch.cs" /> <Compile Include="StackExchange\Redis\IBatch.cs" />
<Compile Include="StackExchange\Redis\IMultiMessage.cs" /> <Compile Include="StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="StackExchange\Redis\Order.cs" /> <Compile Include="StackExchange\Redis\Order.cs" />
<Compile Include="StackExchange\Redis\RedisBatch.cs" /> <Compile Include="StackExchange\Redis\RedisBatch.cs" />
<Compile Include="StackExchange\Redis\RedisCommand.cs" /> <Compile Include="StackExchange\Redis\RedisCommand.cs" />
<Compile Include="StackExchange\Redis\RedisErrorEventArgs.cs" /> <Compile Include="StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\HashSlotMovedEventArgs.cs" /> <Compile Include="StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="StackExchange\Redis\ITransaction.cs" /> <Compile Include="StackExchange\Redis\ITransaction.cs" />
<Compile Include="StackExchange\Redis\IRedis.cs" /> <Compile Include="StackExchange\Redis\IRedis.cs" />
<Compile Include="StackExchange\Redis\IRedisAsync.cs" /> <Compile Include="StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="StackExchange\Redis\IDatabase.cs" /> <Compile Include="StackExchange\Redis\IDatabase.cs" />
<Compile Include="StackExchange\Redis\IDatabaseAsync.cs" /> <Compile Include="StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="StackExchange\Redis\IServer.cs" /> <Compile Include="StackExchange\Redis\IServer.cs" />
<Compile Include="StackExchange\Redis\ISubscriber.cs" /> <Compile Include="StackExchange\Redis\ISubscriber.cs" />
<Compile Include="StackExchange\Redis\MessageCompletable.cs" /> <Compile Include="StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="StackExchange\Redis\RedisBase.cs" /> <Compile Include="StackExchange\Redis\RedisBase.cs" />
<Compile Include="StackExchange\Redis\CommandFlags.cs" /> <Compile Include="StackExchange\Redis\CommandFlags.cs" />
<Compile Include="StackExchange\Redis\CommandMap.cs" /> <Compile Include="StackExchange\Redis\CommandMap.cs" />
<Compile Include="StackExchange\Redis\CompletionManager.cs" /> <Compile Include="StackExchange\Redis\CompletionManager.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.cs" /> <Compile Include="StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="StackExchange\Redis\CompletedDefaultTask.cs" /> <Compile Include="StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="StackExchange\Redis\ICompletable.cs" /> <Compile Include="StackExchange\Redis\ICompletable.cs" />
<Compile Include="StackExchange\Redis\LoggingTextStream.cs" /> <Compile Include="StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="StackExchange\Redis\PhysicalBridge.cs" /> <Compile Include="StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="StackExchange\Redis\Message.cs" /> <Compile Include="StackExchange\Redis\Message.cs" />
<Compile Include="StackExchange\Redis\MessageQueue.cs" /> <Compile Include="StackExchange\Redis\MessageQueue.cs" />
<Compile Include="StackExchange\Redis\PhysicalConnection.cs" /> <Compile Include="StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StackExchange\Redis\RedisResult.cs" /> <Compile Include="StackExchange\Redis\RedisResult.cs" />
<Compile Include="StackExchange\Redis\RedisTransaction.cs" /> <Compile Include="StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="StackExchange\Redis\RedisDatabase.cs" /> <Compile Include="StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="StackExchange\Redis\RedisFeatures.cs" /> <Compile Include="StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="StackExchange\Redis\RedisKey.cs" /> <Compile Include="StackExchange\Redis\RedisKey.cs" />
<Compile Include="StackExchange\Redis\RedisLiterals.cs" /> <Compile Include="StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="StackExchange\Redis\RedisServer.cs" /> <Compile Include="StackExchange\Redis\RedisServer.cs" />
<Compile Include="StackExchange\Redis\RedisType.cs" /> <Compile Include="StackExchange\Redis\RedisType.cs" />
<Compile Include="StackExchange\Redis\RedisValue.cs" /> <Compile Include="StackExchange\Redis\RedisValue.cs" />
<Compile Include="StackExchange\Redis\ReplicationChangeOptions.cs" /> <Compile Include="StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="StackExchange\Redis\RawResult.cs" /> <Compile Include="StackExchange\Redis\RawResult.cs" />
<Compile Include="StackExchange\Redis\ResultBox.cs" /> <Compile Include="StackExchange\Redis\ResultBox.cs" />
<Compile Include="StackExchange\Redis\ResultProcessor.cs" /> <Compile Include="StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="StackExchange\Redis\RedisSubscriber.cs" /> <Compile Include="StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="StackExchange\Redis\ResultType.cs" /> <Compile Include="StackExchange\Redis\ResultType.cs" />
<Compile Include="StackExchange\Redis\ScriptParameterMapper.cs" /> <Compile Include="StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="StackExchange\Redis\ServerCounters.cs" /> <Compile Include="StackExchange\Redis\ServerCounters.cs" />
<Compile Include="StackExchange\Redis\ServerEndPoint.cs" /> <Compile Include="StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="StackExchange\Redis\ServerSelectionStrategy.cs" /> <Compile Include="StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="StackExchange\Redis\ServerType.cs" /> <Compile Include="StackExchange\Redis\ServerType.cs" />
<Compile Include="StackExchange\Redis\SetOperation.cs" /> <Compile Include="StackExchange\Redis\SetOperation.cs" />
<Compile Include="StackExchange\Redis\SocketManager.cs" /> <Compile Include="StackExchange\Redis\SocketManager.cs" />
<Compile Include="StackExchange\Redis\SocketManager.NoPoll.cs"> <Compile Include="StackExchange\Redis\SocketManager.NoPoll.cs">
<DependentUpon>SocketManager.cs</DependentUpon> <DependentUpon>SocketManager.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="StackExchange\Redis\SortedSetEntry.cs" /> <Compile Include="StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="StackExchange\Redis\SortType.cs" /> <Compile Include="StackExchange\Redis\SortType.cs" />
<Compile Include="StackExchange\Redis\StringSplits.cs" /> <Compile Include="StackExchange\Redis\StringSplits.cs" />
<Compile Include="StackExchange\Redis\TaskSource.cs" /> <Compile Include="StackExchange\Redis\TaskSource.cs" />
<Compile Include="StackExchange\Redis\When.cs" /> <Compile Include="StackExchange\Redis\When.cs" />
<Compile Include="StackExchange\Redis\ShutdownMode.cs" /> <Compile Include="StackExchange\Redis\ShutdownMode.cs" />
<Compile Include="StackExchange\Redis\SaveType.cs" /> <Compile Include="StackExchange\Redis\SaveType.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\BatchWrapper.cs" /> <Compile Include="StackExchange\Redis\KeyspaceIsolation\BatchWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\DatabaseExtension.cs" /> <Compile Include="StackExchange\Redis\KeyspaceIsolation\DatabaseExtension.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\DatabaseWrapper.cs" /> <Compile Include="StackExchange\Redis\KeyspaceIsolation\DatabaseWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\TransactionWrapper.cs" /> <Compile Include="StackExchange\Redis\KeyspaceIsolation\TransactionWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\WrapperBase.cs" /> <Compile Include="StackExchange\Redis\KeyspaceIsolation\WrapperBase.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="StackExchange\Redis\SocketManager.Poll.cs"> <Compile Include="StackExchange\Redis\SocketManager.Poll.cs">
<DependentUpon>SocketManager.cs</DependentUpon> <DependentUpon>SocketManager.cs</DependentUpon>
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="StackExchange.Redis.snk" /> <None Include="StackExchange.Redis.snk" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// Represents the commands mapped on a particular configuration /// Represents the commands mapped on a particular configuration
/// </summary> /// </summary>
public sealed class CommandMap public sealed class CommandMap
{ {
private static readonly CommandMap private static readonly CommandMap
@default = CreateImpl(null, null), @default = CreateImpl(null, null),
twemproxy = CreateImpl(null, exclusions: new HashSet<RedisCommand> twemproxy = CreateImpl(null, exclusions: new HashSet<RedisCommand>
{ {
// see https://github.com/twitter/twemproxy/blob/master/notes/redis.md // see https://github.com/twitter/twemproxy/blob/master/notes/redis.md
RedisCommand.KEYS, RedisCommand.MIGRATE, RedisCommand.MOVE, RedisCommand.OBJECT, RedisCommand.RANDOMKEY, RedisCommand.KEYS, RedisCommand.MIGRATE, RedisCommand.MOVE, RedisCommand.OBJECT, RedisCommand.RANDOMKEY,
RedisCommand.RENAME, RedisCommand.RENAMENX, RedisCommand.SORT, RedisCommand.SCAN, RedisCommand.RENAME, RedisCommand.RENAMENX, RedisCommand.SORT, RedisCommand.SCAN,
RedisCommand.BITOP, RedisCommand.MSET, RedisCommand.MSETNX, RedisCommand.BITOP, RedisCommand.MSET, RedisCommand.MSETNX,
RedisCommand.HSCAN, RedisCommand.HSCAN,
RedisCommand.BLPOP, RedisCommand.BRPOP, RedisCommand.BRPOPLPUSH, // yeah, me neither! RedisCommand.BLPOP, RedisCommand.BRPOP, RedisCommand.BRPOPLPUSH, // yeah, me neither!
RedisCommand.SSCAN, RedisCommand.SSCAN,
RedisCommand.ZSCAN, RedisCommand.ZSCAN,
RedisCommand.PSUBSCRIBE, RedisCommand.PUBLISH, RedisCommand.PUNSUBSCRIBE, RedisCommand.SUBSCRIBE, RedisCommand.UNSUBSCRIBE, RedisCommand.PSUBSCRIBE, RedisCommand.PUBLISH, RedisCommand.PUNSUBSCRIBE, RedisCommand.SUBSCRIBE, RedisCommand.UNSUBSCRIBE,
RedisCommand.DISCARD, RedisCommand.EXEC, RedisCommand.MULTI, RedisCommand.UNWATCH, RedisCommand.WATCH, RedisCommand.DISCARD, RedisCommand.EXEC, RedisCommand.MULTI, RedisCommand.UNWATCH, RedisCommand.WATCH,
RedisCommand.SCRIPT, RedisCommand.SCRIPT,
RedisCommand.AUTH, RedisCommand.ECHO, RedisCommand.PING, RedisCommand.QUIT, RedisCommand.SELECT, RedisCommand.AUTH, RedisCommand.ECHO, RedisCommand.PING, RedisCommand.QUIT, RedisCommand.SELECT,
RedisCommand.BGREWRITEAOF, RedisCommand.BGSAVE, RedisCommand.CLIENT, RedisCommand.CLUSTER, RedisCommand.CONFIG, RedisCommand.DBSIZE, RedisCommand.BGREWRITEAOF, RedisCommand.BGSAVE, RedisCommand.CLIENT, RedisCommand.CLUSTER, RedisCommand.CONFIG, RedisCommand.DBSIZE,
RedisCommand.DEBUG, RedisCommand.FLUSHALL, RedisCommand.FLUSHDB, RedisCommand.INFO, RedisCommand.LASTSAVE, RedisCommand.MONITOR, RedisCommand.SAVE, RedisCommand.DEBUG, RedisCommand.FLUSHALL, RedisCommand.FLUSHDB, RedisCommand.INFO, RedisCommand.LASTSAVE, RedisCommand.MONITOR, RedisCommand.SAVE,
RedisCommand.SHUTDOWN, RedisCommand.SLAVEOF, RedisCommand.SLOWLOG, RedisCommand.SYNC, RedisCommand.TIME RedisCommand.SHUTDOWN, RedisCommand.SLAVEOF, RedisCommand.SLOWLOG, RedisCommand.SYNC, RedisCommand.TIME
}), ssdb = Create(new HashSet<string> { }), ssdb = Create(new HashSet<string> {
// see http://www.ideawu.com/ssdb/docs/redis-to-ssdb.html // see http://www.ideawu.com/ssdb/docs/redis-to-ssdb.html
"ping", "ping",
"get", "set", "del", "incr", "incrby", "mget", "mset", "keys", "getset", "setnx", "get", "set", "del", "incr", "incrby", "mget", "mset", "keys", "getset", "setnx",
"hget", "hset", "hdel", "hincrby", "hkeys", "hvals", "hmget", "hmset", "hlen", "hget", "hset", "hdel", "hincrby", "hkeys", "hvals", "hmget", "hmset", "hlen",
"zscore", "zadd", "zrem", "zrange", "zrangebyscore", "zincrby", "zdecrby", "zcard", "zscore", "zadd", "zrem", "zrange", "zrangebyscore", "zincrby", "zdecrby", "zcard",
"llen", "lpush", "rpush", "lpop", "rpop", "lrange", "lindex" "llen", "lpush", "rpush", "lpop", "rpop", "lrange", "lindex"
}, true), }, true),
sentinel = Create(new HashSet<string> { sentinel = Create(new HashSet<string> {
// see http://redis.io/topics/sentinel // see http://redis.io/topics/sentinel
"ping", "info", "sentinel", "subscribe", "psubscribe", "unsubscribe", "punsubscribe" }, true); "ping", "info", "sentinel", "subscribe", "psubscribe", "unsubscribe", "punsubscribe" }, true);
private readonly byte[][] map; private readonly byte[][] map;
internal CommandMap(byte[][] map) internal CommandMap(byte[][] map)
{ {
this.map = map; this.map = map;
} }
/// <summary> /// <summary>
/// The default commands specified by redis /// The default commands specified by redis
/// </summary> /// </summary>
public static CommandMap Default { get { return @default; } } public static CommandMap Default { get { return @default; } }
/// <summary> /// <summary>
/// The commands available to <a href="twemproxy">https://github.com/twitter/twemproxy</a> /// The commands available to <a href="twemproxy">https://github.com/twitter/twemproxy</a>
/// </summary> /// </summary>
/// <remarks>https://github.com/twitter/twemproxy/blob/master/notes/redis.md</remarks> /// <remarks>https://github.com/twitter/twemproxy/blob/master/notes/redis.md</remarks>
public static CommandMap Twemproxy { get { return twemproxy; } } public static CommandMap Twemproxy { get { return twemproxy; } }
/// <summary> /// <summary>
/// The commands available to <a href="ssdb">http://www.ideawu.com/ssdb/</a> /// The commands available to <a href="ssdb">http://www.ideawu.com/ssdb/</a>
/// </summary> /// </summary>
/// <remarks>http://www.ideawu.com/ssdb/docs/redis-to-ssdb.html</remarks> /// <remarks>http://www.ideawu.com/ssdb/docs/redis-to-ssdb.html</remarks>
public static CommandMap SSDB { get { return ssdb; } } public static CommandMap SSDB { get { return ssdb; } }
/// <summary> /// <summary>
/// The commands available to <a href="Sentinel">http://redis.io/topics/sentinel</a> /// The commands available to <a href="Sentinel">http://redis.io/topics/sentinel</a>
/// </summary> /// </summary>
/// <remarks>http://redis.io/topics/sentinel</remarks> /// <remarks>http://redis.io/topics/sentinel</remarks>
public static CommandMap Sentinel { get { return sentinel; } } public static CommandMap Sentinel { get { return sentinel; } }
/// <summary> /// <summary>
/// Create a new CommandMap, customizing some commands /// Create a new CommandMap, customizing some commands
/// </summary> /// </summary>
public static CommandMap Create(Dictionary<string, string> overrides) public static CommandMap Create(Dictionary<string, string> overrides)
{ {
if (overrides == null || overrides.Count == 0) return Default; if (overrides == null || overrides.Count == 0) return Default;
if (ReferenceEquals(overrides.Comparer, StringComparer.OrdinalIgnoreCase)) if (ReferenceEquals(overrides.Comparer, StringComparer.OrdinalIgnoreCase))
{ {
// that's ok; we're happy with ordinal/invariant case-insensitive // that's ok; we're happy with ordinal/invariant case-insensitive
// (but not culture-specific insensitive; completely untested) // (but not culture-specific insensitive; completely untested)
} }
else else
{ {
// need case insensitive // need case insensitive
overrides = new Dictionary<string, string>(overrides, StringComparer.OrdinalIgnoreCase); overrides = new Dictionary<string, string>(overrides, StringComparer.OrdinalIgnoreCase);
} }
return CreateImpl(overrides, null); return CreateImpl(overrides, null);
} }
/// <summary> /// <summary>
/// Creates a CommandMap by specifying which commands are available or unavailable /// Creates a CommandMap by specifying which commands are available or unavailable
/// </summary> /// </summary>
public static CommandMap Create(HashSet<string> commands, bool available = true) public static CommandMap Create(HashSet<string> commands, bool available = true)
{ {
if (available) if (available)
{ {
var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// nix everything // nix everything
foreach (RedisCommand command in Enum.GetValues(typeof(RedisCommand))) foreach (RedisCommand command in Enum.GetValues(typeof(RedisCommand)))
{ {
dictionary[command.ToString()] = null; dictionary[command.ToString()] = null;
} }
if (commands != null) if (commands != null)
{ {
// then include (by removal) the things that are available // then include (by removal) the things that are available
foreach (string command in commands) foreach (string command in commands)
{ {
dictionary.Remove(command); dictionary.Remove(command);
} }
} }
return CreateImpl(dictionary, null); return CreateImpl(dictionary, null);
} }
else else
{ {
HashSet<RedisCommand> exclusions = null; HashSet<RedisCommand> exclusions = null;
if (commands != null) if (commands != null)
{ {
// nix the things that are specified // nix the things that are specified
foreach (var command in commands) foreach (var command in commands)
{ {
RedisCommand parsed; RedisCommand parsed;
if (Enum.TryParse(command, true, out parsed)) if (Enum.TryParse(command, true, out parsed))
{ {
(exclusions ?? (exclusions = new HashSet<RedisCommand>())).Add(parsed); (exclusions ?? (exclusions = new HashSet<RedisCommand>())).Add(parsed);
} }
} }
} }
if (exclusions == null || exclusions.Count == 0) return Default; if (exclusions == null || exclusions.Count == 0) return Default;
return CreateImpl(null, exclusions); return CreateImpl(null, exclusions);
} }
} }
/// <summary> /// <summary>
/// See Object.ToString() /// See Object.ToString()
/// </summary> /// </summary>
public override string ToString() public override string ToString()
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
AppendDeltas(sb); AppendDeltas(sb);
return sb.ToString(); return sb.ToString();
} }
internal void AppendDeltas(StringBuilder sb) internal void AppendDeltas(StringBuilder sb)
{ {
for (int i = 0; i < map.Length; i++) for (int i = 0; i < map.Length; i++)
{ {
var key = ((RedisCommand)i).ToString(); var key = ((RedisCommand)i).ToString();
var value = map[i] == null ? "" : Encoding.UTF8.GetString(map[i]); var value = map[i] == null ? "" : Encoding.UTF8.GetString(map[i]);
if (key != value) if (key != value)
{ {
if (sb.Length != 0) sb.Append(','); if (sb.Length != 0) sb.Append(',');
sb.Append('$').Append(key).Append('=').Append(value); sb.Append('$').Append(key).Append('=').Append(value);
} }
} }
} }
internal void AssertAvailable(RedisCommand command) internal void AssertAvailable(RedisCommand command)
{ {
if (map[(int)command] == null) throw ExceptionFactory.CommandDisabled(false, command, null, null); if (map[(int)command] == null) throw ExceptionFactory.CommandDisabled(false, command, null, null);
} }
internal byte[] GetBytes(RedisCommand command) internal byte[] GetBytes(RedisCommand command)
{ {
return map[(int)command]; return map[(int)command];
} }
internal bool IsAvailable(RedisCommand command) internal bool IsAvailable(RedisCommand command)
{ {
return map[(int)command] != null; return map[(int)command] != null;
} }
private static CommandMap CreateImpl(Dictionary<string, string> caseInsensitiveOverrides, HashSet<RedisCommand> exclusions) private static CommandMap CreateImpl(Dictionary<string, string> caseInsensitiveOverrides, HashSet<RedisCommand> exclusions)
{ {
var commands = (RedisCommand[])Enum.GetValues(typeof(RedisCommand)); var commands = (RedisCommand[])Enum.GetValues(typeof(RedisCommand));
byte[][] map = new byte[commands.Length][]; byte[][] map = new byte[commands.Length][];
bool haveDelta = false; bool haveDelta = false;
for (int i = 0; i < commands.Length; i++) for (int i = 0; i < commands.Length; i++)
{ {
int idx = (int)commands[i]; int idx = (int)commands[i];
string name = commands[i].ToString(), value = name; string name = commands[i].ToString(), value = name;
if (exclusions != null && exclusions.Contains(commands[i])) if (exclusions != null && exclusions.Contains(commands[i]))
{ {
map[idx] = null; map[idx] = null;
} }
else else
{ {
if (caseInsensitiveOverrides != null) if (caseInsensitiveOverrides != null)
{ {
string tmp; string tmp;
if (caseInsensitiveOverrides.TryGetValue(name, out tmp)) if (caseInsensitiveOverrides.TryGetValue(name, out tmp))
{ {
value = tmp; value = tmp;
} }
} }
if (value != name) haveDelta = true; if (value != name) haveDelta = true;
haveDelta = true; haveDelta = true;
byte[] val = string.IsNullOrWhiteSpace(value) ? null : Encoding.UTF8.GetBytes(value); byte[] val = string.IsNullOrWhiteSpace(value) ? null : Encoding.UTF8.GetBytes(value);
map[idx] = val; map[idx] = val;
} }
} }
if (!haveDelta && @default != null) return @default; if (!haveDelta && @default != null) return @default;
return new CommandMap(map); return new CommandMap(map);
} }
} }
} }
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// Utility methods /// Utility methods
/// </summary> /// </summary>
public static class ExtensionMethods public static class ExtensionMethods
{ {
/// <summary> /// <summary>
/// Create a dictionary from an array of HashEntry values /// Create a dictionary from an array of HashEntry values
/// </summary> /// </summary>
public static Dictionary<string,string> ToStringDictionary(this HashEntry[] hash) public static Dictionary<string,string> ToStringDictionary(this HashEntry[] hash)
{ {
if (hash == null) return null; if (hash == null) return null;
var result = new Dictionary<string, string>(hash.Length, StringComparer.Ordinal); var result = new Dictionary<string, string>(hash.Length, StringComparer.Ordinal);
for(int i = 0; i < hash.Length; i++) for(int i = 0; i < hash.Length; i++)
{ {
result.Add(hash[i].name, hash[i].value); result.Add(hash[i].name, hash[i].value);
} }
return result; return result;
} }
/// <summary> /// <summary>
/// Create a dictionary from an array of HashEntry values /// Create a dictionary from an array of HashEntry values
/// </summary> /// </summary>
public static Dictionary<RedisValue, RedisValue> ToDictionary(this HashEntry[] hash) public static Dictionary<RedisValue, RedisValue> ToDictionary(this HashEntry[] hash)
{ {
if (hash == null) return null; if (hash == null) return null;
var result = new Dictionary<RedisValue, RedisValue>(hash.Length); var result = new Dictionary<RedisValue, RedisValue>(hash.Length);
for (int i = 0; i < hash.Length; i++) for (int i = 0; i < hash.Length; i++)
{ {
result.Add(hash[i].name, hash[i].value); result.Add(hash[i].name, hash[i].value);
} }
return result; return result;
} }
/// <summary> /// <summary>
/// Create a dictionary from an array of SortedSetEntry values /// Create a dictionary from an array of SortedSetEntry values
/// </summary> /// </summary>
public static Dictionary<string, double> ToStringDictionary(this SortedSetEntry[] sortedSet) public static Dictionary<string, double> ToStringDictionary(this SortedSetEntry[] sortedSet)
{ {
if (sortedSet == null) return null; if (sortedSet == null) return null;
var result = new Dictionary<string, double>(sortedSet.Length, StringComparer.Ordinal); var result = new Dictionary<string, double>(sortedSet.Length, StringComparer.Ordinal);
for (int i = 0; i < sortedSet.Length; i++) for (int i = 0; i < sortedSet.Length; i++)
{ {
result.Add(sortedSet[i].element, sortedSet[i].score); result.Add(sortedSet[i].element, sortedSet[i].score);
} }
return result; return result;
} }
/// <summary> /// <summary>
/// Create a dictionary from an array of SortedSetEntry values /// Create a dictionary from an array of SortedSetEntry values
/// </summary> /// </summary>
public static Dictionary<RedisValue, double> ToDictionary(this SortedSetEntry[] sortedSet) public static Dictionary<RedisValue, double> ToDictionary(this SortedSetEntry[] sortedSet)
{ {
if (sortedSet == null) return null; if (sortedSet == null) return null;
var result = new Dictionary<RedisValue, double>(sortedSet.Length); var result = new Dictionary<RedisValue, double>(sortedSet.Length);
for (int i = 0; i < sortedSet.Length; i++) for (int i = 0; i < sortedSet.Length; i++)
{ {
result.Add(sortedSet[i].element, sortedSet[i].score); result.Add(sortedSet[i].element, sortedSet[i].score);
} }
return result; return result;
} }
/// <summary> /// <summary>
/// Create a dictionary from an array of key/value pairs /// Create a dictionary from an array of key/value pairs
/// </summary> /// </summary>
public static Dictionary<string, string> ToStringDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs) public static Dictionary<string, string> ToStringDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs)
{ {
if (pairs == null) return null; if (pairs == null) return null;
var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal); var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal);
for (int i = 0; i < pairs.Length; i++) for (int i = 0; i < pairs.Length; i++)
{ {
result.Add(pairs[i].Key, pairs[i].Value); result.Add(pairs[i].Key, pairs[i].Value);
} }
return result; return result;
} }
/// <summary> /// <summary>
/// Create a dictionary from an array of key/value pairs /// Create a dictionary from an array of key/value pairs
/// </summary> /// </summary>
public static Dictionary<RedisKey, RedisValue> ToDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs) public static Dictionary<RedisKey, RedisValue> ToDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs)
{ {
if (pairs == null) return null; if (pairs == null) return null;
var result = new Dictionary<RedisKey, RedisValue>(pairs.Length); var result = new Dictionary<RedisKey, RedisValue>(pairs.Length);
for (int i = 0; i < pairs.Length; i++) for (int i = 0; i < pairs.Length; i++)
{ {
result.Add(pairs[i].Key, pairs[i].Value); result.Add(pairs[i].Key, pairs[i].Value);
} }
return result; return result;
} }
/// <summary> /// <summary>
/// Create a dictionary from an array of string pairs /// Create a dictionary from an array of string pairs
/// </summary> /// </summary>
public static Dictionary<string, string> ToDictionary(this KeyValuePair<string, string>[] pairs) public static Dictionary<string, string> ToDictionary(this KeyValuePair<string, string>[] pairs)
{ {
if (pairs == null) return null; if (pairs == null) return null;
var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal); var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal);
for (int i = 0; i < pairs.Length; i++) for (int i = 0; i < pairs.Length; i++)
{ {
result.Add(pairs[i].Key, pairs[i].Value); result.Add(pairs[i].Key, pairs[i].Value);
} }
return result; return result;
} }
static readonly string[] nix = new string[0]; static readonly string[] nix = new string[0];
/// <summary> /// <summary>
/// Create an array of strings from an array of values /// Create an array of strings from an array of values
/// </summary> /// </summary>
public static string[] ToStringArray(this RedisValue[] values) public static string[] ToStringArray(this RedisValue[] values)
{ {
if (values == null) return null; if (values == null) return null;
if (values.Length == 0) return nix; if (values.Length == 0) return nix;
return ConvertHelper.ConvertAll(values, x => (string)x); return ConvertHelper.ConvertAll(values, x => (string)x);
} }
} }
} }
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// Describes a hash-field (a name/value pair) /// Describes a hash-field (a name/value pair)
/// </summary> /// </summary>
public struct HashEntry : IEquatable<HashEntry> public struct HashEntry : IEquatable<HashEntry>
{ {
internal readonly RedisValue name, value; internal readonly RedisValue name, value;
/// <summary> /// <summary>
/// Initializes a HashEntry value /// Initializes a HashEntry value
/// </summary> /// </summary>
public HashEntry(RedisValue name, RedisValue value) public HashEntry(RedisValue name, RedisValue value)
{ {
this.name = name; this.name = name;
this.value = value; this.value = value;
} }
/// <summary> /// <summary>
/// The name of the hash field /// The name of the hash field
/// </summary> /// </summary>
public RedisValue Name { get { return name; } } public RedisValue Name { get { return name; } }
/// <summary> /// <summary>
/// The value of the hash field /// The value of the hash field
/// </summary> /// </summary>
public RedisValue Value{ get { return value; } } public RedisValue Value{ get { return value; } }
/// <summary> /// <summary>
/// The name of the hash field /// The name of the hash field
/// </summary> /// </summary>
#if !DNXCORE50 #if !DNXCORE50
[Browsable(false)] [Browsable(false)]
#endif #endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Name", false)] [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Name", false)]
public RedisValue Key { get { return name; } } public RedisValue Key { get { return name; } }
/// <summary> /// <summary>
/// Converts to a key/value pair /// Converts to a key/value pair
/// </summary> /// </summary>
public static implicit operator KeyValuePair<RedisValue, RedisValue>(HashEntry value) public static implicit operator KeyValuePair<RedisValue, RedisValue>(HashEntry value)
{ {
return new KeyValuePair<RedisValue, RedisValue>(value.name, value.value); return new KeyValuePair<RedisValue, RedisValue>(value.name, value.value);
} }
/// <summary> /// <summary>
/// Converts from a key/value pair /// Converts from a key/value pair
/// </summary> /// </summary>
public static implicit operator HashEntry(KeyValuePair<RedisValue, RedisValue> value) public static implicit operator HashEntry(KeyValuePair<RedisValue, RedisValue> value)
{ {
return new HashEntry(value.Key, value.Value); return new HashEntry(value.Key, value.Value);
} }
/// <summary> /// <summary>
/// See Object.ToString() /// See Object.ToString()
/// </summary> /// </summary>
public override string ToString() public override string ToString()
{ {
return name + ": " + value; return name + ": " + value;
} }
/// <summary> /// <summary>
/// See Object.GetHashCode() /// See Object.GetHashCode()
/// </summary> /// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return name.GetHashCode() ^ value.GetHashCode(); return name.GetHashCode() ^ value.GetHashCode();
} }
/// <summary> /// <summary>
/// Compares two values for equality /// Compares two values for equality
/// </summary> /// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is HashEntry && Equals((HashEntry)obj); return obj is HashEntry && Equals((HashEntry)obj);
} }
/// <summary> /// <summary>
/// Compares two values for equality /// Compares two values for equality
/// </summary> /// </summary>
public bool Equals(HashEntry value) public bool Equals(HashEntry value)
{ {
return this.name == value.name && this.value == value.value; return this.name == value.name && this.value == value.value;
} }
/// <summary> /// <summary>
/// Compares two values for equality /// Compares two values for equality
/// </summary> /// </summary>
public static bool operator ==(HashEntry x, HashEntry y) public static bool operator ==(HashEntry x, HashEntry y)
{ {
return x.name == y.name && x.value == y.value; return x.name == y.name && x.value == y.value;
} }
/// <summary> /// <summary>
/// Compares two values for non-equality /// Compares two values for non-equality
/// </summary> /// </summary>
public static bool operator !=(HashEntry x, HashEntry y) public static bool operator !=(HashEntry x, HashEntry y)
{ {
return x.name != y.name || x.value != y.value; return x.name != y.name || x.value != y.value;
} }
} }
} }
using System; using System;
using System.Linq;
namespace StackExchange.Redis
namespace StackExchange.Redis {
{ /// <summary>
/// <summary> /// Represents a general-purpose result from redis, that may be cast into various anticipated types
/// Represents a general-purpose result from redis, that may be cast into various anticipated types /// </summary>
/// </summary> public abstract class RedisResult
public abstract class RedisResult {
{
// internally, this is very similar to RawResult, except it is designed to be usable
// 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
// outside of the IO-processing pipeline: the buffers are standalone, etc
internal static RedisResult TryCreate(PhysicalConnection connection, RawResult result)
internal static RedisResult TryCreate(PhysicalConnection connection, RawResult result) {
{ try
try {
{ switch (result.Type)
switch (result.Type) {
{ case ResultType.Integer:
case ResultType.Integer: case ResultType.SimpleString:
case ResultType.SimpleString: case ResultType.BulkString:
case ResultType.BulkString: return new SingleRedisResult(result.AsRedisValue());
return new SingleRedisResult(result.AsRedisValue()); case ResultType.MultiBulk:
case ResultType.MultiBulk: var items = result.GetItems();
var items = result.GetItems(); var arr = new RedisResult[items.Length];
var arr = new RedisResult[items.Length]; for (int i = 0; i < arr.Length; i++)
for (int i = 0; i < arr.Length; i++) {
{ var next = TryCreate(connection, items[i]);
var next = TryCreate(connection, items[i]); if (next == null) return null; // means we didn't understand
if (next == null) return null; // means we didn't understand arr[i] = next;
arr[i] = next; }
} return new ArrayRedisResult(arr);
return new ArrayRedisResult(arr); case ResultType.Error:
case ResultType.Error: return new ErrorRedisResult(result.GetString());
return new ErrorRedisResult(result.GetString()); default:
default: return null;
return null; }
} } catch(Exception ex)
} catch(Exception ex) {
{ if(connection != null) connection.OnInternalError(ex);
if(connection != null) connection.OnInternalError(ex); return null; // will be logged as a protocol fail by the processor
return null; // will be logged as a protocol fail by the processor }
} }
}
/// <summary>
/// <summary> /// Indicates whether this result was a null result
/// Indicates whether this result was a null result /// </summary>
/// </summary> public abstract bool IsNull { get; }
public abstract bool IsNull { get; }
/// <summary>
/// <summary> /// Interprets the result as a String
/// Interprets the result as a String /// </summary>
/// </summary> public static explicit operator string (RedisResult result) { return result.AsString(); }
public static explicit operator string (RedisResult result) { return result.AsString(); } /// <summary>
/// <summary> /// Interprets the result as a Byte[]
/// Interprets the result as a Byte[] /// </summary>
/// </summary> public static explicit operator byte[] (RedisResult result) { return result.AsByteArray(); }
public static explicit operator byte[] (RedisResult result) { return result.AsByteArray(); } /// <summary>
/// <summary> /// Interprets the result as a Double
/// Interprets the result as a Double /// </summary>
/// </summary> public static explicit operator double (RedisResult result) { return result.AsDouble(); }
public static explicit operator double (RedisResult result) { return result.AsDouble(); } /// <summary>
/// <summary> /// Interprets the result as an Int64
/// Interprets the result as an Int64 /// </summary>
/// </summary> public static explicit operator long (RedisResult result) { return result.AsInt64(); }
public static explicit operator long (RedisResult result) { return result.AsInt64(); } /// <summary>
/// <summary> /// Interprets the result as an Int32
/// Interprets the result as an Int32 /// </summary>
/// </summary> public static explicit operator int (RedisResult result) { return result.AsInt32(); }
public static explicit operator int (RedisResult result) { return result.AsInt32(); } /// <summary>
/// <summary> /// Interprets the result as a Boolean
/// Interprets the result as a Boolean /// </summary>
/// </summary> public static explicit operator bool (RedisResult result) { return result.AsBoolean(); }
public static explicit operator bool (RedisResult result) { return result.AsBoolean(); } /// <summary>
/// <summary> /// Interprets the result as a RedisValue
/// Interprets the result as a RedisValue /// </summary>
/// </summary> public static explicit operator RedisValue (RedisResult result) { return result.AsRedisValue(); }
public static explicit operator RedisValue (RedisResult result) { return result.AsRedisValue(); } /// <summary>
/// <summary> /// Interprets the result as a RedisKey
/// Interprets the result as a RedisKey /// </summary>
/// </summary> public static explicit operator RedisKey (RedisResult result) { return result.AsRedisKey(); }
public static explicit operator RedisKey (RedisResult result) { return result.AsRedisKey(); } /// <summary>
/// <summary> /// Interprets the result as a Nullable Double
/// Interprets the result as a Nullable Double /// </summary>
/// </summary> public static explicit operator double? (RedisResult result) { return result.AsNullableDouble(); }
public static explicit operator double? (RedisResult result) { return result.AsNullableDouble(); } /// <summary>
/// <summary> /// Interprets the result as a Nullable Int64
/// Interprets the result as a Nullable Int64 /// </summary>
/// </summary> public static explicit operator long? (RedisResult result) { return result.AsNullableInt64(); }
public static explicit operator long? (RedisResult result) { return result.AsNullableInt64(); } /// <summary>
/// <summary> /// Interprets the result as a Nullable Int32
/// Interprets the result as a Nullable Int32 /// </summary>
/// </summary> public static explicit operator int? (RedisResult result) { return result.AsNullableInt32(); }
public static explicit operator int? (RedisResult result) { return result.AsNullableInt32(); } /// <summary>
/// <summary> /// Interprets the result as a Nullable Boolean
/// Interprets the result as a Nullable Boolean /// </summary>
/// </summary> public static explicit operator bool? (RedisResult result) { return result.AsNullableBoolean(); }
public static explicit operator bool? (RedisResult result) { return result.AsNullableBoolean(); } /// <summary>
/// <summary> /// Interprets the result as an array of String
/// Interprets the result as an array of String /// </summary>
/// </summary> public static explicit operator string[] (RedisResult result) { return result.AsStringArray(); }
public static explicit operator string[] (RedisResult result) { return result.AsStringArray(); } /// <summary>
/// <summary> /// Interprets the result as an array of Byte[]
/// Interprets the result as an array of Byte[] /// </summary>
/// </summary> public static explicit operator byte[][] (RedisResult result) { return result.AsByteArrayArray(); }
public static explicit operator byte[][] (RedisResult result) { return result.AsByteArrayArray(); } /// <summary>
/// <summary> /// Interprets the result as an array of Double
/// Interprets the result as an array of Double /// </summary>
/// </summary> public static explicit operator double[] (RedisResult result) { return result.AsDoubleArray(); }
public static explicit operator double[] (RedisResult result) { return result.AsDoubleArray(); } /// <summary>
/// <summary> /// Interprets the result as an array of Int64
/// Interprets the result as an array of Int64 /// </summary>
/// </summary> public static explicit operator long[] (RedisResult result) { return result.AsInt64Array(); }
public static explicit operator long[] (RedisResult result) { return result.AsInt64Array(); } /// <summary>
/// <summary> /// Interprets the result as an array of Int32
/// Interprets the result as an array of Int32 /// </summary>
/// </summary> public static explicit operator int[] (RedisResult result) { return result.AsInt32Array(); }
public static explicit operator int[] (RedisResult result) { return result.AsInt32Array(); } /// <summary>
/// <summary> /// Interprets the result as an array of Boolean
/// Interprets the result as an array of Boolean /// </summary>
/// </summary> public static explicit operator bool[] (RedisResult result) { return result.AsBooleanArray(); }
public static explicit operator bool[] (RedisResult result) { return result.AsBooleanArray(); } /// <summary>
/// <summary> /// Interprets the result as an array of RedisValue
/// Interprets the result as an array of RedisValue /// </summary>
/// </summary> public static explicit operator RedisValue[] (RedisResult result) { return result.AsRedisValueArray(); }
public static explicit operator RedisValue[] (RedisResult result) { return result.AsRedisValueArray(); } /// <summary>
/// <summary> /// Interprets the result as an array of RedisKey
/// Interprets the result as an array of RedisKey /// </summary>
/// </summary> public static explicit operator RedisKey[] (RedisResult result) { return result.AsRedisKeyArray(); }
public static explicit operator RedisKey[] (RedisResult result) { return result.AsRedisKeyArray(); } /// <summary>
/// <summary> /// Interprets the result as an array of RedisResult
/// Interprets the result as an array of RedisResult /// </summary>
/// </summary> public static explicit operator RedisResult[] (RedisResult result) { return result.AsRedisResultArray(); }
public static explicit operator RedisResult[] (RedisResult result) { return result.AsRedisResultArray(); }
internal abstract bool AsBoolean();
internal abstract bool AsBoolean();
internal abstract bool[] AsBooleanArray();
internal abstract bool[] AsBooleanArray();
internal abstract byte[] AsByteArray();
internal abstract byte[] AsByteArray();
internal abstract byte[][] AsByteArrayArray();
internal abstract byte[][] AsByteArrayArray();
internal abstract double AsDouble();
internal abstract double AsDouble();
internal abstract double[] AsDoubleArray();
internal abstract double[] AsDoubleArray();
internal abstract int AsInt32();
internal abstract int AsInt32();
internal abstract int[] AsInt32Array();
internal abstract int[] AsInt32Array();
internal abstract long AsInt64();
internal abstract long AsInt64();
internal abstract long[] AsInt64Array();
internal abstract long[] AsInt64Array();
internal abstract bool? AsNullableBoolean();
internal abstract bool? AsNullableBoolean();
internal abstract double? AsNullableDouble();
internal abstract double? AsNullableDouble();
internal abstract int? AsNullableInt32();
internal abstract int? AsNullableInt32();
internal abstract long? AsNullableInt64();
internal abstract long? AsNullableInt64();
internal abstract RedisKey AsRedisKey();
internal abstract RedisKey AsRedisKey();
internal abstract RedisKey[] AsRedisKeyArray();
internal abstract RedisKey[] AsRedisKeyArray();
internal abstract RedisResult[] AsRedisResultArray();
internal abstract RedisResult[] AsRedisResultArray();
internal abstract RedisValue AsRedisValue();
internal abstract RedisValue AsRedisValue();
internal abstract RedisValue[] AsRedisValueArray();
internal abstract RedisValue[] AsRedisValueArray(); internal abstract string AsString();
internal abstract string AsString(); internal abstract string[] AsStringArray();
internal abstract string[] AsStringArray(); private sealed class ArrayRedisResult : RedisResult
private sealed class ArrayRedisResult : RedisResult {
{ public override bool IsNull
public override bool IsNull {
{ get { return value == null; }
get { return value == null; } }
} private readonly RedisResult[] value;
private readonly RedisResult[] value; public ArrayRedisResult(RedisResult[] value)
public ArrayRedisResult(RedisResult[] value) {
{ if (value == null) throw new ArgumentNullException("value");
if (value == null) throw new ArgumentNullException("value"); this.value = value;
this.value = value; }
} public override string ToString()
public override string ToString() {
{ return value.Length + " element(s)";
return value.Length + " element(s)"; }
} internal override bool AsBoolean()
internal override bool AsBoolean() {
{ if (value.Length == 1) return value[0].AsBoolean();
if (value.Length == 1) return value[0].AsBoolean(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override bool[] AsBooleanArray() { return ConvertHelper.ConvertAll(value, x => x.AsBoolean()); }
internal override bool[] AsBooleanArray() { return ConvertHelper.ConvertAll(value, x => x.AsBoolean()); }
internal override byte[] AsByteArray()
internal override byte[] AsByteArray() {
{ if (value.Length == 1) return value[0].AsByteArray();
if (value.Length == 1) return value[0].AsByteArray(); throw new InvalidCastException();
throw new InvalidCastException(); }
} internal override byte[][] AsByteArrayArray() { return ConvertHelper.ConvertAll(value, x => x.AsByteArray()); }
internal override byte[][] AsByteArrayArray() { return ConvertHelper.ConvertAll(value, x => x.AsByteArray()); }
internal override double AsDouble()
internal override double AsDouble() {
{ if (value.Length == 1) return value[0].AsDouble();
if (value.Length == 1) return value[0].AsDouble(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override double[] AsDoubleArray() { return ConvertHelper.ConvertAll(value, x => x.AsDouble()); }
internal override double[] AsDoubleArray() { return ConvertHelper.ConvertAll(value, x => x.AsDouble()); }
internal override int AsInt32()
internal override int AsInt32() {
{ if (value.Length == 1) return value[0].AsInt32();
if (value.Length == 1) return value[0].AsInt32(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override int[] AsInt32Array() { return ConvertHelper.ConvertAll(value, x => x.AsInt32()); }
internal override int[] AsInt32Array() { return ConvertHelper.ConvertAll(value, x => x.AsInt32()); }
internal override long AsInt64()
internal override long AsInt64() {
{ if (value.Length == 1) return value[0].AsInt64();
if (value.Length == 1) return value[0].AsInt64(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override long[] AsInt64Array() { return ConvertHelper.ConvertAll(value, x => x.AsInt64()); }
internal override long[] AsInt64Array() { return ConvertHelper.ConvertAll(value, x => x.AsInt64()); }
internal override bool? AsNullableBoolean()
internal override bool? AsNullableBoolean() {
{ if (value.Length == 1) return value[0].AsNullableBoolean();
if (value.Length == 1) return value[0].AsNullableBoolean(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override double? AsNullableDouble()
internal override double? AsNullableDouble() {
{ if (value.Length == 1) return value[0].AsNullableDouble();
if (value.Length == 1) return value[0].AsNullableDouble(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override int? AsNullableInt32()
internal override int? AsNullableInt32() {
{ if (value.Length == 1) return value[0].AsNullableInt32();
if (value.Length == 1) return value[0].AsNullableInt32(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override long? AsNullableInt64()
internal override long? AsNullableInt64() {
{ if (value.Length == 1) return value[0].AsNullableInt64();
if (value.Length == 1) return value[0].AsNullableInt64(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override RedisKey AsRedisKey()
internal override RedisKey AsRedisKey() {
{ if (value.Length == 1) return value[0].AsRedisKey();
if (value.Length == 1) return value[0].AsRedisKey(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override RedisKey[] AsRedisKeyArray() { return ConvertHelper.ConvertAll(value, x => x.AsRedisKey()); }
internal override RedisKey[] AsRedisKeyArray() { return ConvertHelper.ConvertAll(value, x => x.AsRedisKey()); }
internal override RedisResult[] AsRedisResultArray() { return value; }
internal override RedisResult[] AsRedisResultArray() { return value; }
internal override RedisValue AsRedisValue()
internal override RedisValue AsRedisValue() {
{ if (value.Length == 1) return value[0].AsRedisValue();
if (value.Length == 1) return value[0].AsRedisValue(); throw new InvalidCastException();
throw new InvalidCastException(); }
}
internal override RedisValue[] AsRedisValueArray() { return ConvertHelper.ConvertAll(value, x => x.AsRedisValue()); }
internal override RedisValue[] AsRedisValueArray() { return ConvertHelper.ConvertAll(value, x => x.AsRedisValue()); }
internal override string AsString()
internal override string AsString() {
{ if (value.Length == 1) return value[0].AsString();
if (value.Length == 1) return value[0].AsString(); throw new InvalidCastException();
throw new InvalidCastException(); }
} internal override string[] AsStringArray() { return ConvertHelper.ConvertAll(value, x => x.AsString()); }
internal override string[] AsStringArray() { return ConvertHelper.ConvertAll(value, x => x.AsString()); } }
}
private sealed class ErrorRedisResult : RedisResult
private sealed class ErrorRedisResult : RedisResult {
{ private readonly string value;
private readonly string value; public ErrorRedisResult(string value)
public ErrorRedisResult(string value) {
{ if (value == null) throw new ArgumentNullException("value");
if (value == null) throw new ArgumentNullException("value"); this.value = value;
this.value = value; }
} public override bool IsNull
public override bool IsNull {
{ get { return value == null; }
get { return value == null; } }
} public override string ToString() { return value; }
public override string ToString() { return value; } internal override bool AsBoolean() { throw new RedisServerException(value); }
internal override bool AsBoolean() { throw new RedisServerException(value); }
internal override bool[] AsBooleanArray() { throw new RedisServerException(value); }
internal override bool[] AsBooleanArray() { throw new RedisServerException(value); }
internal override byte[] AsByteArray() { throw new RedisServerException(value); }
internal override byte[] AsByteArray() { throw new RedisServerException(value); }
internal override byte[][] AsByteArrayArray() { throw new RedisServerException(value); }
internal override byte[][] AsByteArrayArray() { throw new RedisServerException(value); }
internal override double AsDouble() { throw new RedisServerException(value); }
internal override double AsDouble() { throw new RedisServerException(value); }
internal override double[] AsDoubleArray() { throw new RedisServerException(value); }
internal override double[] AsDoubleArray() { throw new RedisServerException(value); }
internal override int AsInt32() { throw new RedisServerException(value); }
internal override int AsInt32() { throw new RedisServerException(value); }
internal override int[] AsInt32Array() { throw new RedisServerException(value); }
internal override int[] AsInt32Array() { throw new RedisServerException(value); }
internal override long AsInt64() { throw new RedisServerException(value); }
internal override long AsInt64() { throw new RedisServerException(value); }
internal override long[] AsInt64Array() { throw new RedisServerException(value); }
internal override long[] AsInt64Array() { throw new RedisServerException(value); }
internal override bool? AsNullableBoolean() { throw new RedisServerException(value); }
internal override bool? AsNullableBoolean() { throw new RedisServerException(value); }
internal override double? AsNullableDouble() { throw new RedisServerException(value); }
internal override double? AsNullableDouble() { throw new RedisServerException(value); }
internal override int? AsNullableInt32() { throw new RedisServerException(value); }
internal override int? AsNullableInt32() { throw new RedisServerException(value); }
internal override long? AsNullableInt64() { throw new RedisServerException(value); }
internal override long? AsNullableInt64() { throw new RedisServerException(value); }
internal override RedisKey AsRedisKey() { throw new RedisServerException(value); }
internal override RedisKey AsRedisKey() { throw new RedisServerException(value); }
internal override RedisKey[] AsRedisKeyArray() { throw new RedisServerException(value); }
internal override RedisKey[] AsRedisKeyArray() { throw new RedisServerException(value); }
internal override RedisResult[] AsRedisResultArray() { throw new RedisServerException(value); }
internal override RedisResult[] AsRedisResultArray() { throw new RedisServerException(value); }
internal override RedisValue AsRedisValue() { throw new RedisServerException(value); }
internal override RedisValue AsRedisValue() { throw new RedisServerException(value); }
internal override RedisValue[] AsRedisValueArray() { throw new RedisServerException(value); }
internal override RedisValue[] AsRedisValueArray() { throw new RedisServerException(value); }
internal override string AsString() { throw new RedisServerException(value); }
internal override string AsString() { throw new RedisServerException(value); } internal override string[] AsStringArray() { throw new RedisServerException(value); }
internal override string[] AsStringArray() { throw new RedisServerException(value); } }
}
private sealed class SingleRedisResult : RedisResult
private sealed class SingleRedisResult : RedisResult {
{ private readonly RedisValue value;
private readonly RedisValue value; public SingleRedisResult(RedisValue value)
public SingleRedisResult(RedisValue value) {
{ this.value = value;
this.value = value; }
}
public override bool IsNull
public override bool IsNull {
{ get { return value.IsNull; }
get { return value.IsNull; } }
}
public override string ToString() { return value.ToString(); }
public override string ToString() { return value.ToString(); } internal override bool AsBoolean() { return (bool)value; }
internal override bool AsBoolean() { return (bool)value; }
internal override bool[] AsBooleanArray() { return new[] { AsBoolean() }; }
internal override bool[] AsBooleanArray() { return new[] { AsBoolean() }; }
internal override byte[] AsByteArray() { return (byte[])value; }
internal override byte[] AsByteArray() { return (byte[])value; } internal override byte[][] AsByteArrayArray() { return new[] { AsByteArray() }; }
internal override byte[][] AsByteArrayArray() { return new[] { AsByteArray() }; }
internal override double AsDouble() { return (double)value; }
internal override double AsDouble() { return (double)value; }
internal override double[] AsDoubleArray() { return new[] { AsDouble() }; }
internal override double[] AsDoubleArray() { return new[] { AsDouble() }; }
internal override int AsInt32() { return (int)value; }
internal override int AsInt32() { return (int)value; }
internal override int[] AsInt32Array() { return new[] { AsInt32() }; }
internal override int[] AsInt32Array() { return new[] { AsInt32() }; }
internal override long AsInt64() { return (long)value; }
internal override long AsInt64() { return (long)value; }
internal override long[] AsInt64Array() { return new[] { AsInt64() }; }
internal override long[] AsInt64Array() { return new[] { AsInt64() }; }
internal override bool? AsNullableBoolean() { return (bool?)value; }
internal override bool? AsNullableBoolean() { return (bool?)value; }
internal override double? AsNullableDouble() { return (double?)value; }
internal override double? AsNullableDouble() { return (double?)value; }
internal override int? AsNullableInt32() { return (int?)value; }
internal override int? AsNullableInt32() { return (int?)value; }
internal override long? AsNullableInt64() { return (long?)value; }
internal override long? AsNullableInt64() { return (long?)value; }
internal override RedisKey AsRedisKey() { return (byte[])value; }
internal override RedisKey AsRedisKey() { return (byte[])value; }
internal override RedisKey[] AsRedisKeyArray() { return new[] { AsRedisKey() }; }
internal override RedisKey[] AsRedisKeyArray() { return new[] { AsRedisKey() }; }
internal override RedisResult[] AsRedisResultArray() { throw new InvalidCastException(); }
internal override RedisResult[] AsRedisResultArray() { throw new InvalidCastException(); }
internal override RedisValue AsRedisValue() { return value; }
internal override RedisValue AsRedisValue() { return value; }
internal override RedisValue[] AsRedisValueArray() { return new[] { AsRedisValue() }; }
internal override RedisValue[] AsRedisValueArray() { return new[] { AsRedisValue() }; }
internal override string AsString() { return (string)value; }
internal override string AsString() { return (string)value; } internal override string[] AsStringArray() { return new[] { AsString() }; }
internal override string[] AsStringArray() { return new[] { AsString() }; } }
} }
} }
}
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
[Flags] [Flags]
internal enum UnselectableFlags internal enum UnselectableFlags
{ {
None = 0, None = 0,
RedundantMaster = 1, RedundantMaster = 1,
DidNotRespond = 2, DidNotRespond = 2,
ServerType = 4 ServerType = 4
} }
internal sealed partial class ServerEndPoint : IDisposable internal sealed partial class ServerEndPoint : IDisposable
{ {
internal volatile ServerEndPoint Master; internal volatile ServerEndPoint Master;
internal volatile ServerEndPoint[] Slaves = NoSlaves; internal volatile ServerEndPoint[] Slaves = NoSlaves;
private static readonly Regex nameSanitizer = new Regex("[^!-~]", InternalRegexCompiledOption.Default); private static readonly Regex nameSanitizer = new Regex("[^!-~]", InternalRegexCompiledOption.Default);
private static readonly ServerEndPoint[] NoSlaves = new ServerEndPoint[0]; private static readonly ServerEndPoint[] NoSlaves = new ServerEndPoint[0];
private readonly EndPoint endpoint; private readonly EndPoint endpoint;
private readonly Hashtable knownScripts = new Hashtable(StringComparer.Ordinal); private readonly Hashtable knownScripts = new Hashtable(StringComparer.Ordinal);
private readonly ConnectionMultiplexer multiplexer; private readonly ConnectionMultiplexer multiplexer;
private int databases, writeEverySeconds; private int databases, writeEverySeconds;
private PhysicalBridge interactive, subscription; private PhysicalBridge interactive, subscription;
bool isDisposed; bool isDisposed;
ServerType serverType; ServerType serverType;
private bool slaveReadOnly, isSlave; private bool slaveReadOnly, isSlave;
private volatile UnselectableFlags unselectableReasons; private volatile UnselectableFlags unselectableReasons;
private Version version; private Version version;
internal void ResetNonConnected() internal void ResetNonConnected()
{ {
var tmp = interactive; var tmp = interactive;
if (tmp != null) tmp.ResetNonConnected(); if (tmp != null) tmp.ResetNonConnected();
tmp = subscription; tmp = subscription;
if (tmp != null) tmp.ResetNonConnected(); if (tmp != null) tmp.ResetNonConnected();
} }
public ServerEndPoint(ConnectionMultiplexer multiplexer, EndPoint endpoint, TextWriter log) public ServerEndPoint(ConnectionMultiplexer multiplexer, EndPoint endpoint, TextWriter log)
{ {
this.multiplexer = multiplexer; this.multiplexer = multiplexer;
this.endpoint = endpoint; this.endpoint = endpoint;
var config = multiplexer.RawConfig; var config = multiplexer.RawConfig;
version = config.DefaultVersion; version = config.DefaultVersion;
slaveReadOnly = true; slaveReadOnly = true;
isSlave = false; isSlave = false;
databases = 0; databases = 0;
writeEverySeconds = config.KeepAlive > 0 ? config.KeepAlive : 60; writeEverySeconds = config.KeepAlive > 0 ? config.KeepAlive : 60;
interactive = CreateBridge(ConnectionType.Interactive, log); interactive = CreateBridge(ConnectionType.Interactive, log);
serverType = ServerType.Standalone; serverType = ServerType.Standalone;
// overrides for twemproxy // overrides for twemproxy
if (multiplexer.RawConfig.Proxy == Proxy.Twemproxy) if (multiplexer.RawConfig.Proxy == Proxy.Twemproxy)
{ {
databases = 1; databases = 1;
serverType = ServerType.Twemproxy; serverType = ServerType.Twemproxy;
} }
} }
public ClusterConfiguration ClusterConfiguration { get; private set; } public ClusterConfiguration ClusterConfiguration { get; private set; }
public int Databases { get { return databases; } set { SetConfig(ref databases, value); } } public int Databases { get { return databases; } set { SetConfig(ref databases, value); } }
public EndPoint EndPoint { get { return endpoint; } } public EndPoint EndPoint { get { return endpoint; } }
public bool HasDatabases { get { return serverType == ServerType.Standalone; } } public bool HasDatabases { get { return serverType == ServerType.Standalone; } }
public bool IsConnected public bool IsConnected
{ {
get get
{ {
var tmp = interactive; var tmp = interactive;
return tmp != null && tmp.IsConnected; return tmp != null && tmp.IsConnected;
} }
} }
public bool IsSlave { get { return isSlave; } set { SetConfig(ref isSlave, value); } } public bool IsSlave { get { return isSlave; } set { SetConfig(ref isSlave, value); } }
public long OperationCount public long OperationCount
{ {
get get
{ {
long total = 0; long total = 0;
var tmp = interactive; var tmp = interactive;
if (tmp != null) total += tmp.OperationCount; if (tmp != null) total += tmp.OperationCount;
tmp = subscription; tmp = subscription;
if (tmp != null) total += tmp.OperationCount; if (tmp != null) total += tmp.OperationCount;
return total; return total;
} }
} }
public bool RequiresReadMode { get { return serverType == ServerType.Cluster && IsSlave; } } public bool RequiresReadMode { get { return serverType == ServerType.Cluster && IsSlave; } }
public ServerType ServerType { get { return serverType; } set { SetConfig(ref serverType, value); } } public ServerType ServerType { get { return serverType; } set { SetConfig(ref serverType, value); } }
public bool SlaveReadOnly { get { return slaveReadOnly; } set { SetConfig(ref slaveReadOnly, value); } } public bool SlaveReadOnly { get { return slaveReadOnly; } set { SetConfig(ref slaveReadOnly, value); } }
public bool AllowSlaveWrites { get; set; } public bool AllowSlaveWrites { get; set; }
public Version Version { get { return version; } set { SetConfig(ref version, value); } } public Version Version { get { return version; } set { SetConfig(ref version, value); } }
public int WriteEverySeconds { get { return writeEverySeconds; } set { SetConfig(ref writeEverySeconds, value); } } public int WriteEverySeconds { get { return writeEverySeconds; } set { SetConfig(ref writeEverySeconds, value); } }
internal ConnectionMultiplexer Multiplexer { get { return multiplexer; } } internal ConnectionMultiplexer Multiplexer { get { return multiplexer; } }
public void ClearUnselectable(UnselectableFlags flags) public void ClearUnselectable(UnselectableFlags flags)
{ {
var oldFlags = unselectableReasons; var oldFlags = unselectableReasons;
if (oldFlags != 0) if (oldFlags != 0)
{ {
unselectableReasons &= ~flags; unselectableReasons &= ~flags;
if (unselectableReasons != oldFlags) if (unselectableReasons != oldFlags)
{ {
multiplexer.Trace(unselectableReasons == 0 ? "Now usable" : ("Now unusable: " + flags), ToString()); multiplexer.Trace(unselectableReasons == 0 ? "Now usable" : ("Now unusable: " + flags), ToString());
} }
} }
} }
public void Dispose() public void Dispose()
{ {
isDisposed = true; isDisposed = true;
var tmp = interactive; var tmp = interactive;
interactive = null; interactive = null;
if (tmp != null) tmp.Dispose(); if (tmp != null) tmp.Dispose();
tmp = subscription; tmp = subscription;
subscription = null; subscription = null;
if (tmp != null) tmp.Dispose(); if (tmp != null) tmp.Dispose();
} }
public PhysicalBridge GetBridge(ConnectionType type, bool create = true, TextWriter log = null) public PhysicalBridge GetBridge(ConnectionType type, bool create = true, TextWriter log = null)
{ {
if (isDisposed) return null; if (isDisposed) return null;
switch (type) switch (type)
{ {
case ConnectionType.Interactive: case ConnectionType.Interactive:
return interactive ?? (create ? interactive = CreateBridge(ConnectionType.Interactive, log) : null); return interactive ?? (create ? interactive = CreateBridge(ConnectionType.Interactive, log) : null);
case ConnectionType.Subscription: case ConnectionType.Subscription:
return subscription ?? (create ? subscription = CreateBridge(ConnectionType.Subscription, log) : null); return subscription ?? (create ? subscription = CreateBridge(ConnectionType.Subscription, log) : null);
} }
return null; return null;
} }
public PhysicalBridge GetBridge(RedisCommand command, bool create = true) public PhysicalBridge GetBridge(RedisCommand command, bool create = true)
{ {
if (isDisposed) return null; if (isDisposed) return null;
switch (command) switch (command)
{ {
case RedisCommand.SUBSCRIBE: case RedisCommand.SUBSCRIBE:
case RedisCommand.UNSUBSCRIBE: case RedisCommand.UNSUBSCRIBE:
case RedisCommand.PSUBSCRIBE: case RedisCommand.PSUBSCRIBE:
case RedisCommand.PUNSUBSCRIBE: case RedisCommand.PUNSUBSCRIBE:
return subscription ?? (create ? subscription = CreateBridge(ConnectionType.Subscription, null) : null); return subscription ?? (create ? subscription = CreateBridge(ConnectionType.Subscription, null) : null);
default: default:
return interactive; return interactive;
} }
} }
public RedisFeatures GetFeatures() public RedisFeatures GetFeatures()
{ {
return new RedisFeatures(version); return new RedisFeatures(version);
} }
public void SetClusterConfiguration(ClusterConfiguration configuration) public void SetClusterConfiguration(ClusterConfiguration configuration)
{ {
ClusterConfiguration = configuration; ClusterConfiguration = configuration;
if (configuration != null) if (configuration != null)
{ {
multiplexer.Trace("Updating cluster ranges..."); multiplexer.Trace("Updating cluster ranges...");
multiplexer.UpdateClusterRange(configuration); multiplexer.UpdateClusterRange(configuration);
multiplexer.Trace("Resolving genealogy..."); multiplexer.Trace("Resolving genealogy...");
var thisNode = configuration.Nodes.FirstOrDefault(x => x.EndPoint == this.EndPoint); var thisNode = configuration.Nodes.FirstOrDefault(x => x.EndPoint == this.EndPoint);
if (thisNode != null) if (thisNode != null)
{ {
List<ServerEndPoint> slaves = null; List<ServerEndPoint> slaves = null;
ServerEndPoint master = null; ServerEndPoint master = null;
foreach (var node in configuration.Nodes) foreach (var node in configuration.Nodes)
{ {
if (node.NodeId == thisNode.ParentNodeId) if (node.NodeId == thisNode.ParentNodeId)
{ {
master = multiplexer.GetServerEndPoint(node.EndPoint); master = multiplexer.GetServerEndPoint(node.EndPoint);
} }
else if (node.ParentNodeId == thisNode.NodeId) else if (node.ParentNodeId == thisNode.NodeId)
{ {
if (slaves == null) slaves = new List<ServerEndPoint>(); if (slaves == null) slaves = new List<ServerEndPoint>();
slaves.Add(multiplexer.GetServerEndPoint(node.EndPoint)); slaves.Add(multiplexer.GetServerEndPoint(node.EndPoint));
} }
} }
Master = master; Master = master;
Slaves = slaves == null ? NoSlaves : slaves.ToArray(); Slaves = slaves == null ? NoSlaves : slaves.ToArray();
} }
multiplexer.Trace("Cluster configured"); multiplexer.Trace("Cluster configured");
} }
} }
public void SetUnselectable(UnselectableFlags flags) public void SetUnselectable(UnselectableFlags flags)
{ {
if (flags != 0) if (flags != 0)
{ {
var oldFlags = unselectableReasons; var oldFlags = unselectableReasons;
unselectableReasons |= flags; unselectableReasons |= flags;
if (unselectableReasons != oldFlags) if (unselectableReasons != oldFlags)
{ {
multiplexer.Trace(unselectableReasons == 0 ? "Now usable" : ("Now unusable: " + flags), ToString()); multiplexer.Trace(unselectableReasons == 0 ? "Now usable" : ("Now unusable: " + flags), ToString());
} }
} }
} }
public override string ToString() public override string ToString()
{ {
return Format.ToString(EndPoint); return Format.ToString(EndPoint);
} }
public bool TryEnqueue(Message message) public bool TryEnqueue(Message message)
{ {
var bridge = GetBridge(message.Command); var bridge = GetBridge(message.Command);
return bridge != null && bridge.TryEnqueue(message, isSlave); return bridge != null && bridge.TryEnqueue(message, isSlave);
} }
internal void Activate(ConnectionType type, TextWriter log) internal void Activate(ConnectionType type, TextWriter log)
{ {
GetBridge(type, true, log); GetBridge(type, true, log);
} }
internal void AddScript(string script, byte[] hash) internal void AddScript(string script, byte[] hash)
{ {
lock (knownScripts) lock (knownScripts)
{ {
knownScripts[script] = hash; knownScripts[script] = hash;
} }
} }
internal void AutoConfigure(PhysicalConnection connection) internal void AutoConfigure(PhysicalConnection connection)
{ {
if (serverType == ServerType.Twemproxy) if (serverType == ServerType.Twemproxy)
{ {
// don't try to detect configuration; all the config commands are disabled, and // don't try to detect configuration; all the config commands are disabled, and
// the fallback master/slave detection won't help // the fallback master/slave detection won't help
return; return;
} }
var commandMap = multiplexer.CommandMap; var commandMap = multiplexer.CommandMap;
const CommandFlags flags = CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect; const CommandFlags flags = CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect;
var features = GetFeatures(); var features = GetFeatures();
Message msg; Message msg;
if (commandMap.IsAvailable(RedisCommand.CONFIG)) if (commandMap.IsAvailable(RedisCommand.CONFIG))
{ {
if (multiplexer.RawConfig.KeepAlive <= 0) if (multiplexer.RawConfig.KeepAlive <= 0)
{ {
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.timeout); msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.timeout);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
} }
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.slave_read_only); msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.slave_read_only);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.databases); msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.databases);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
} }
if (commandMap.IsAvailable(RedisCommand.INFO)) if (commandMap.IsAvailable(RedisCommand.INFO))
{ {
lastInfoReplicationCheckTicks = Environment.TickCount; lastInfoReplicationCheckTicks = Environment.TickCount;
if (features.InfoSections) if (features.InfoSections)
{ {
msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.replication); msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.replication);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.server); msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.server);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
} }
else else
{ {
msg = Message.Create(-1, flags, RedisCommand.INFO); msg = Message.Create(-1, flags, RedisCommand.INFO);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
} }
} }
else if (commandMap.IsAvailable(RedisCommand.SET)) else if (commandMap.IsAvailable(RedisCommand.SET))
{ {
// this is a nasty way to find if we are a slave, and it will only work on up-level servers, but... // this is a nasty way to find if we are a slave, and it will only work on up-level servers, but...
RedisKey key = Guid.NewGuid().ToByteArray(); RedisKey key = Guid.NewGuid().ToByteArray();
msg = Message.Create(0, flags, RedisCommand.SET, key, RedisLiterals.slave_read_only, RedisLiterals.PX, 1, RedisLiterals.NX); msg = Message.Create(0, flags, RedisCommand.SET, key, RedisLiterals.slave_read_only, RedisLiterals.PX, 1, RedisLiterals.NX);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
} }
if (commandMap.IsAvailable(RedisCommand.CLUSTER)) if (commandMap.IsAvailable(RedisCommand.CLUSTER))
{ {
msg = Message.Create(-1, flags, RedisCommand.CLUSTER, RedisLiterals.NODES); msg = Message.Create(-1, flags, RedisCommand.CLUSTER, RedisLiterals.NODES);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.ClusterNodes); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.ClusterNodes);
} }
} }
internal Task Close() internal Task Close()
{ {
var tmp = interactive; var tmp = interactive;
Task result; Task result;
if (tmp == null || !tmp.IsConnected || !multiplexer.CommandMap.IsAvailable(RedisCommand.QUIT)) if (tmp == null || !tmp.IsConnected || !multiplexer.CommandMap.IsAvailable(RedisCommand.QUIT))
{ {
result = CompletedTask<bool>.Default(null); result = CompletedTask<bool>.Default(null);
} }
else else
{ {
result = QueueDirectAsync(Message.Create(-1, CommandFlags.None, RedisCommand.QUIT), ResultProcessor.DemandOK, bridge: interactive); result = QueueDirectAsync(Message.Create(-1, CommandFlags.None, RedisCommand.QUIT), ResultProcessor.DemandOK, bridge: interactive);
} }
return result; return result;
} }
internal void FlushScriptCache() internal void FlushScriptCache()
{ {
lock (knownScripts) lock (knownScripts)
{ {
knownScripts.Clear(); knownScripts.Clear();
} }
} }
private string runId; private string runId;
internal string RunId internal string RunId
{ {
get { return runId; } get { return runId; }
set set
{ {
if (value != runId) // we only care about changes if (value != runId) // we only care about changes
{ {
// if we had an old run-id, and it has changed, then the // if we had an old run-id, and it has changed, then the
// server has been restarted; which means the script cache // server has been restarted; which means the script cache
// is toast // is toast
if (runId != null) FlushScriptCache(); if (runId != null) FlushScriptCache();
runId = value; runId = value;
} }
} }
} }
internal ServerCounters GetCounters() internal ServerCounters GetCounters()
{ {
var counters = new ServerCounters(endpoint); var counters = new ServerCounters(endpoint);
var tmp = interactive; var tmp = interactive;
if (tmp != null) tmp.GetCounters(counters.Interactive); if (tmp != null) tmp.GetCounters(counters.Interactive);
tmp = subscription; tmp = subscription;
if (tmp != null) tmp.GetCounters(counters.Subscription); if (tmp != null) tmp.GetCounters(counters.Subscription);
return counters; return counters;
} }
internal int GetOutstandingCount(RedisCommand command, out int inst, out int qu, out int qs, out int qc, out int wr, out int wq, out int @in, out int ar) internal int GetOutstandingCount(RedisCommand command, out int inst, out int qu, out int qs, out int qc, out int wr, out int wq, out int @in, out int ar)
{ {
var bridge = GetBridge(command, false); var bridge = GetBridge(command, false);
if (bridge == null) if (bridge == null)
{ {
return inst = qu = qs = qc = wr = wq = @in = ar = 0; return inst = qu = qs = qc = wr = wq = @in = ar = 0;
} }
return bridge.GetOutstandingCount(out inst, out qu, out qs, out qc, out wr, out wq, out @in, out ar); return bridge.GetOutstandingCount(out inst, out qu, out qs, out qc, out wr, out wq, out @in, out ar);
} }
internal string GetProfile() internal string GetProfile()
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.Append("Circular op-count snapshot; int:"); sb.Append("Circular op-count snapshot; int:");
var tmp = interactive; var tmp = interactive;
if (tmp != null) tmp.AppendProfile(sb); if (tmp != null) tmp.AppendProfile(sb);
sb.Append("; sub:"); sb.Append("; sub:");
tmp = subscription; tmp = subscription;
if (tmp != null) tmp.AppendProfile(sb); if (tmp != null) tmp.AppendProfile(sb);
return sb.ToString(); return sb.ToString();
} }
internal byte[] GetScriptHash(string script, RedisCommand command) internal byte[] GetScriptHash(string script, RedisCommand command)
{ {
var found = (byte[])knownScripts[script]; var found = (byte[])knownScripts[script];
if(found == null && command == RedisCommand.EVALSHA) if(found == null && command == RedisCommand.EVALSHA)
{ {
// the script provided is a hex sha; store and re-use the ascii for that // the script provided is a hex sha; store and re-use the ascii for that
found = Encoding.ASCII.GetBytes(script); found = Encoding.ASCII.GetBytes(script);
lock(knownScripts) lock(knownScripts)
{ {
knownScripts[script] = found; knownScripts[script] = found;
} }
} }
return found; return found;
} }
internal string GetStormLog(RedisCommand command) internal string GetStormLog(RedisCommand command)
{ {
var bridge = GetBridge(command); var bridge = GetBridge(command);
return bridge == null ? null : bridge.GetStormLog(); return bridge == null ? null : bridge.GetStormLog();
} }
internal Message GetTracerMessage(bool assertIdentity) internal Message GetTracerMessage(bool assertIdentity)
{ {
// different configurations block certain commands, as can ad-hoc local configurations, so // different configurations block certain commands, as can ad-hoc local configurations, so
// we'll do the best with what we have available. // we'll do the best with what we have available.
// note that the muxer-ctor asserts that one of ECHO, PING, TIME of GET is available // note that the muxer-ctor asserts that one of ECHO, PING, TIME of GET is available
// see also: TracerProcessor // see also: TracerProcessor
var map = multiplexer.CommandMap; var map = multiplexer.CommandMap;
Message msg; Message msg;
const CommandFlags flags = CommandFlags.NoRedirect | CommandFlags.FireAndForget; const CommandFlags flags = CommandFlags.NoRedirect | CommandFlags.FireAndForget;
if (assertIdentity && map.IsAvailable(RedisCommand.ECHO)) if (assertIdentity && map.IsAvailable(RedisCommand.ECHO))
{ {
msg = Message.Create(-1, flags, RedisCommand.ECHO, (RedisValue)multiplexer.UniqueId); msg = Message.Create(-1, flags, RedisCommand.ECHO, (RedisValue)multiplexer.UniqueId);
} }
else if (map.IsAvailable(RedisCommand.PING)) else if (map.IsAvailable(RedisCommand.PING))
{ {
msg = Message.Create(-1, flags, RedisCommand.PING); msg = Message.Create(-1, flags, RedisCommand.PING);
} }
else if (map.IsAvailable(RedisCommand.TIME)) else if (map.IsAvailable(RedisCommand.TIME))
{ {
msg = Message.Create(-1, flags, RedisCommand.TIME); msg = Message.Create(-1, flags, RedisCommand.TIME);
} }
else if (!assertIdentity && map.IsAvailable(RedisCommand.ECHO)) else if (!assertIdentity && map.IsAvailable(RedisCommand.ECHO))
{ {
// we'll use echo as a PING substitute if it is all we have (in preference to EXISTS) // we'll use echo as a PING substitute if it is all we have (in preference to EXISTS)
msg = Message.Create(-1, flags, RedisCommand.ECHO, (RedisValue)multiplexer.UniqueId); msg = Message.Create(-1, flags, RedisCommand.ECHO, (RedisValue)multiplexer.UniqueId);
} }
else else
{ {
map.AssertAvailable(RedisCommand.EXISTS); map.AssertAvailable(RedisCommand.EXISTS);
msg = Message.Create(0, flags, RedisCommand.EXISTS, (RedisValue)multiplexer.UniqueId); msg = Message.Create(0, flags, RedisCommand.EXISTS, (RedisValue)multiplexer.UniqueId);
} }
msg.SetInternalCall(); msg.SetInternalCall();
return msg; return msg;
} }
internal bool IsSelectable(RedisCommand command) internal bool IsSelectable(RedisCommand command)
{ {
var bridge = unselectableReasons == 0 ? GetBridge(command, false) : null; var bridge = unselectableReasons == 0 ? GetBridge(command, false) : null;
return bridge != null && bridge.IsConnected; return bridge != null && bridge.IsConnected;
} }
internal void OnEstablishing(PhysicalConnection connection, TextWriter log) internal void OnEstablishing(PhysicalConnection connection, TextWriter log)
{ {
try try
{ {
if (connection == null) return; if (connection == null) return;
Handshake(connection, log); Handshake(connection, log);
} }
catch (Exception ex) catch (Exception ex)
{ {
connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex); connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
} }
} }
internal void OnFullyEstablished(PhysicalConnection connection) internal void OnFullyEstablished(PhysicalConnection connection)
{ {
try try
{ {
if (connection == null) return; if (connection == null) return;
var bridge = connection.Bridge; var bridge = connection.Bridge;
if (bridge == subscription) if (bridge == subscription)
{ {
multiplexer.ResendSubscriptions(this); multiplexer.ResendSubscriptions(this);
} }
multiplexer.OnConnectionRestored(endpoint, bridge.ConnectionType); multiplexer.OnConnectionRestored(endpoint, bridge.ConnectionType);
} }
catch (Exception ex) catch (Exception ex)
{ {
connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex); connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
} }
} }
internal int LastInfoReplicationCheckSecondsAgo internal int LastInfoReplicationCheckSecondsAgo
{ {
get { return unchecked(Environment.TickCount - VolatileWrapper.Read(ref lastInfoReplicationCheckTicks)) / 1000; } get { return unchecked(Environment.TickCount - VolatileWrapper.Read(ref lastInfoReplicationCheckTicks)) / 1000; }
} }
private EndPoint masterEndPoint; private EndPoint masterEndPoint;
public EndPoint MasterEndPoint public EndPoint MasterEndPoint
{ {
get { return masterEndPoint; } get { return masterEndPoint; }
set { SetConfig(ref masterEndPoint, value); } set { SetConfig(ref masterEndPoint, value); }
} }
internal bool CheckInfoReplication() internal bool CheckInfoReplication()
{ {
lastInfoReplicationCheckTicks = Environment.TickCount; lastInfoReplicationCheckTicks = Environment.TickCount;
PhysicalBridge bridge; PhysicalBridge bridge;
if (version >= RedisFeatures.v2_8_0 && multiplexer.CommandMap.IsAvailable(RedisCommand.INFO) if (version >= RedisFeatures.v2_8_0 && multiplexer.CommandMap.IsAvailable(RedisCommand.INFO)
&& (bridge = GetBridge(ConnectionType.Interactive, false)) != null) && (bridge = GetBridge(ConnectionType.Interactive, false)) != null)
{ {
var msg = Message.Create(-1, CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect, RedisCommand.INFO, RedisLiterals.replication); var msg = Message.Create(-1, CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect, RedisCommand.INFO, RedisLiterals.replication);
msg.SetInternalCall(); msg.SetInternalCall();
QueueDirectFireAndForget(msg, ResultProcessor.AutoConfigure, bridge); QueueDirectFireAndForget(msg, ResultProcessor.AutoConfigure, bridge);
return true; return true;
} }
return false; return false;
} }
private int lastInfoReplicationCheckTicks; private int lastInfoReplicationCheckTicks;
internal void OnHeartbeat() internal void OnHeartbeat()
{ {
try try
{ {
var tmp = interactive; var tmp = interactive;
if (tmp != null) tmp.OnHeartbeat(false); if (tmp != null) tmp.OnHeartbeat(false);
tmp = subscription; tmp = subscription;
if (tmp != null) tmp.OnHeartbeat(false); if (tmp != null) tmp.OnHeartbeat(false);
} catch(Exception ex) } catch(Exception ex)
{ {
multiplexer.OnInternalError(ex, EndPoint); multiplexer.OnInternalError(ex, EndPoint);
} }
} }
internal Task<T> QueueDirectAsync<T>(Message message, ResultProcessor<T> processor, object asyncState = null, PhysicalBridge bridge = null) internal Task<T> QueueDirectAsync<T>(Message message, ResultProcessor<T> processor, object asyncState = null, PhysicalBridge bridge = null)
{ {
var tcs = TaskSource.CreateDenyExecSync<T>(asyncState); var tcs = TaskSource.CreateDenyExecSync<T>(asyncState);
var source = ResultBox<T>.Get(tcs); var source = ResultBox<T>.Get(tcs);
message.SetSource(processor, source); message.SetSource(processor, source);
if (bridge == null) bridge = GetBridge(message.Command); if (bridge == null) bridge = GetBridge(message.Command);
if (!bridge.TryEnqueue(message, isSlave)) if (!bridge.TryEnqueue(message, isSlave))
{ {
ConnectionMultiplexer.ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(multiplexer.IncludeDetailInExceptions, message.Command, message, this)); ConnectionMultiplexer.ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(multiplexer.IncludeDetailInExceptions, message.Command, message, this));
} }
return tcs.Task; return tcs.Task;
} }
internal void QueueDirectFireAndForget<T>(Message message, ResultProcessor<T> processor, PhysicalBridge bridge = null) internal void QueueDirectFireAndForget<T>(Message message, ResultProcessor<T> processor, PhysicalBridge bridge = null)
{ {
if (message != null) if (message != null)
{ {
message.SetSource(processor, null); message.SetSource(processor, null);
multiplexer.Trace("Enqueue: " + message); multiplexer.Trace("Enqueue: " + message);
(bridge ?? GetBridge(message.Command)).TryEnqueue(message, isSlave); (bridge ?? GetBridge(message.Command)).TryEnqueue(message, isSlave);
} }
} }
internal void ReportNextFailure() internal void ReportNextFailure()
{ {
var tmp = interactive; var tmp = interactive;
if (tmp != null) tmp.ReportNextFailure(); if (tmp != null) tmp.ReportNextFailure();
tmp = subscription; tmp = subscription;
if (tmp != null) tmp.ReportNextFailure(); if (tmp != null) tmp.ReportNextFailure();
} }
internal Task<bool> SendTracer(TextWriter log = null) internal Task<bool> SendTracer(TextWriter log = null)
{ {
var msg = GetTracerMessage(false); var msg = GetTracerMessage(false);
msg = LoggingMessage.Create(log, msg); msg = LoggingMessage.Create(log, msg);
return QueueDirectAsync(msg, ResultProcessor.Tracer); return QueueDirectAsync(msg, ResultProcessor.Tracer);
} }
internal string Summary() internal string Summary()
{ {
var sb = new StringBuilder(Format.ToString(endpoint)) var sb = new StringBuilder(Format.ToString(endpoint))
.Append(": ").Append(serverType).Append(" v").Append(version).Append(", ").Append(isSlave ? "slave" : "master"); .Append(": ").Append(serverType).Append(" v").Append(version).Append(", ").Append(isSlave ? "slave" : "master");
if (databases > 0) sb.Append("; ").Append(databases).Append(" databases"); if (databases > 0) sb.Append("; ").Append(databases).Append(" databases");
if (writeEverySeconds > 0) if (writeEverySeconds > 0)
sb.Append("; keep-alive: ").Append(TimeSpan.FromSeconds(writeEverySeconds)); sb.Append("; keep-alive: ").Append(TimeSpan.FromSeconds(writeEverySeconds));
var tmp = interactive; var tmp = interactive;
sb.Append("; int: ").Append(tmp == null ? "n/a" : tmp.ConnectionState.ToString()); sb.Append("; int: ").Append(tmp == null ? "n/a" : tmp.ConnectionState.ToString());
tmp = subscription; tmp = subscription;
if(tmp == null) if(tmp == null)
{ {
sb.Append("; sub: n/a"); sb.Append("; sub: n/a");
} else } else
{ {
var state = tmp.ConnectionState; var state = tmp.ConnectionState;
sb.Append("; sub: ").Append(state); sb.Append("; sub: ").Append(state);
if(state == PhysicalBridge.State.ConnectedEstablished) if(state == PhysicalBridge.State.ConnectedEstablished)
{ {
sb.Append(", ").Append(tmp.SubscriptionCount).Append(" active"); sb.Append(", ").Append(tmp.SubscriptionCount).Append(" active");
} }
} }
var flags = unselectableReasons; var flags = unselectableReasons;
if (flags != 0) if (flags != 0)
{ {
sb.Append("; not in use: ").Append(flags); sb.Append("; not in use: ").Append(flags);
} }
return sb.ToString(); return sb.ToString();
} }
internal void WriteDirectOrQueueFireAndForget<T>(PhysicalConnection connection, Message message, ResultProcessor<T> processor) internal void WriteDirectOrQueueFireAndForget<T>(PhysicalConnection connection, Message message, ResultProcessor<T> processor)
{ {
if (message != null) if (message != null)
{ {
message.SetSource(processor, null); message.SetSource(processor, null);
if (connection == null) if (connection == null)
{ {
multiplexer.Trace("Enqueue: " + message); multiplexer.Trace("Enqueue: " + message);
GetBridge(message.Command).TryEnqueue(message, isSlave); GetBridge(message.Command).TryEnqueue(message, isSlave);
} }
else else
{ {
multiplexer.Trace("Writing direct: " + message); multiplexer.Trace("Writing direct: " + message);
connection.Bridge.WriteMessageDirect(connection, message); connection.Bridge.WriteMessageDirect(connection, message);
} }
} }
} }
private PhysicalBridge CreateBridge(ConnectionType type, TextWriter log) private PhysicalBridge CreateBridge(ConnectionType type, TextWriter log)
{ {
multiplexer.Trace(type.ToString()); multiplexer.Trace(type.ToString());
var bridge = new PhysicalBridge(this, type); var bridge = new PhysicalBridge(this, type);
bridge.TryConnect(log); bridge.TryConnect(log);
return bridge; return bridge;
} }
void Handshake(PhysicalConnection connection, TextWriter log) void Handshake(PhysicalConnection connection, TextWriter log)
{ {
multiplexer.LogLocked(log, "Server handshake"); multiplexer.LogLocked(log, "Server handshake");
if (connection == null) if (connection == null)
{ {
multiplexer.Trace("No connection!?"); multiplexer.Trace("No connection!?");
return; return;
} }
Message msg; Message msg;
string password = multiplexer.RawConfig.Password; string password = multiplexer.RawConfig.Password;
if (!string.IsNullOrWhiteSpace(password)) if (!string.IsNullOrWhiteSpace(password))
{ {
multiplexer.LogLocked(log, "Authenticating (password)"); multiplexer.LogLocked(log, "Authenticating (password)");
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.AUTH, (RedisValue)password); msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.AUTH, (RedisValue)password);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.DemandOK); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.DemandOK);
} }
if (multiplexer.CommandMap.IsAvailable(RedisCommand.CLIENT)) if (multiplexer.CommandMap.IsAvailable(RedisCommand.CLIENT))
{ {
string name = multiplexer.ClientName; string name = multiplexer.ClientName;
if (!string.IsNullOrWhiteSpace(name)) if (!string.IsNullOrWhiteSpace(name))
{ {
name = nameSanitizer.Replace(name, ""); name = nameSanitizer.Replace(name, "");
if (!string.IsNullOrWhiteSpace(name)) if (!string.IsNullOrWhiteSpace(name))
{ {
multiplexer.LogLocked(log, "Setting client name: {0}", name); multiplexer.LogLocked(log, "Setting client name: {0}", name);
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.CLIENT, RedisLiterals.SETNAME, (RedisValue)name); msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.CLIENT, RedisLiterals.SETNAME, (RedisValue)name);
msg.SetInternalCall(); msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.DemandOK); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.DemandOK);
} }
} }
} }
var connType = connection.Bridge.ConnectionType; var connType = connection.Bridge.ConnectionType;
if (connType == ConnectionType.Interactive) if (connType == ConnectionType.Interactive)
{ {
multiplexer.LogLocked(log, "Auto-configure..."); multiplexer.LogLocked(log, "Auto-configure...");
AutoConfigure(connection); AutoConfigure(connection);
} }
multiplexer.LogLocked(log, "Sending critical tracer: {0}", connection.Bridge); multiplexer.LogLocked(log, "Sending critical tracer: {0}", connection.Bridge);
var tracer = GetTracerMessage(true); var tracer = GetTracerMessage(true);
tracer = LoggingMessage.Create(log, tracer); tracer = LoggingMessage.Create(log, tracer);
WriteDirectOrQueueFireAndForget(connection, tracer, ResultProcessor.EstablishConnection); WriteDirectOrQueueFireAndForget(connection, tracer, ResultProcessor.EstablishConnection);
// note: this **must** be the last thing on the subscription handshake, because after this // note: this **must** be the last thing on the subscription handshake, because after this
// we will be in subscriber mode: regular commands cannot be sent // we will be in subscriber mode: regular commands cannot be sent
if (connType == ConnectionType.Subscription) if (connType == ConnectionType.Subscription)
{ {
var configChannel = multiplexer.ConfigurationChangedChannel; var configChannel = multiplexer.ConfigurationChangedChannel;
if(configChannel != null) if(configChannel != null)
{ {
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.SUBSCRIBE, (RedisChannel)configChannel); msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.SUBSCRIBE, (RedisChannel)configChannel);
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.TrackSubscriptions); WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.TrackSubscriptions);
} }
} }
multiplexer.LogLocked(log, "Flushing outbound buffer"); multiplexer.LogLocked(log, "Flushing outbound buffer");
connection.Flush(); connection.Flush();
} }
private void SetConfig<T>(ref T field, T value, [CallerMemberName] string caller = null) private void SetConfig<T>(ref T field, T value, [CallerMemberName] string caller = null)
{ {
if(!EqualityComparer<T>.Default.Equals(field, value)) if(!EqualityComparer<T>.Default.Equals(field, value))
{ {
multiplexer.Trace(caller + " changed from " + field + " to " + value, "Configuration"); multiplexer.Trace(caller + " changed from " + field + " to " + value, "Configuration");
field = value; field = value;
multiplexer.ReconfigureIfNeeded(endpoint, false, caller); multiplexer.ReconfigureIfNeeded(endpoint, false, caller);
} }
} }
} }
} }
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
/// <summary> /// <summary>
/// Describes a sorted-set element with the corresponding value /// Describes a sorted-set element with the corresponding value
/// </summary> /// </summary>
public struct SortedSetEntry : IEquatable<SortedSetEntry>, IComparable, IComparable<SortedSetEntry> public struct SortedSetEntry : IEquatable<SortedSetEntry>, IComparable, IComparable<SortedSetEntry>
{ {
internal readonly RedisValue element; internal readonly RedisValue element;
internal readonly double score; internal readonly double score;
/// <summary> /// <summary>
/// Initializes a SortedSetEntry value /// Initializes a SortedSetEntry value
/// </summary> /// </summary>
public SortedSetEntry(RedisValue element, double score) public SortedSetEntry(RedisValue element, double score)
{ {
this.element = element; this.element = element;
this.score = score; this.score = score;
} }
/// <summary> /// <summary>
/// The unique element stored in the sorted set /// The unique element stored in the sorted set
/// </summary> /// </summary>
public RedisValue Element { get { return element; } } public RedisValue Element { get { return element; } }
/// <summary> /// <summary>
/// The score against the element /// The score against the element
/// </summary> /// </summary>
public double Score { get { return score; } } public double Score { get { return score; } }
/// <summary> /// <summary>
/// The score against the element /// The score against the element
/// </summary> /// </summary>
#if !DNXCORE50 #if !DNXCORE50
[Browsable(false)] [Browsable(false)]
#endif #endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Score", false)] [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Score", false)]
public double Value { get { return score; } } public double Value { get { return score; } }
/// <summary> /// <summary>
/// The unique element stored in the sorted set /// The unique element stored in the sorted set
/// </summary> /// </summary>
#if !DNXCORE50 #if !DNXCORE50
[Browsable(false)] [Browsable(false)]
#endif #endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Element", false)] [EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Element", false)]
public RedisValue Key { get { return element; } } public RedisValue Key { get { return element; } }
/// <summary> /// <summary>
/// Converts to a key/value pair /// Converts to a key/value pair
/// </summary> /// </summary>
public static implicit operator KeyValuePair<RedisValue,double>(SortedSetEntry value) public static implicit operator KeyValuePair<RedisValue,double>(SortedSetEntry value)
{ {
return new KeyValuePair<RedisValue, double>(value.element, value.score); return new KeyValuePair<RedisValue, double>(value.element, value.score);
} }
/// <summary> /// <summary>
/// Converts from a key/value pair /// Converts from a key/value pair
/// </summary> /// </summary>
public static implicit operator SortedSetEntry(KeyValuePair<RedisValue, double> value) public static implicit operator SortedSetEntry(KeyValuePair<RedisValue, double> value)
{ {
return new SortedSetEntry(value.Key, value.Value); return new SortedSetEntry(value.Key, value.Value);
} }
/// <summary> /// <summary>
/// See Object.ToString() /// See Object.ToString()
/// </summary> /// </summary>
public override string ToString() public override string ToString()
{ {
return element + ": " + score; return element + ": " + score;
} }
/// <summary> /// <summary>
/// See Object.GetHashCode() /// See Object.GetHashCode()
/// </summary> /// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return element.GetHashCode() ^ score.GetHashCode(); return element.GetHashCode() ^ score.GetHashCode();
} }
/// <summary> /// <summary>
/// Compares two values for equality /// Compares two values for equality
/// </summary> /// </summary>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is SortedSetEntry && Equals((SortedSetEntry)obj); return obj is SortedSetEntry && Equals((SortedSetEntry)obj);
} }
/// <summary> /// <summary>
/// Compares two values for equality /// Compares two values for equality
/// </summary> /// </summary>
public bool Equals(SortedSetEntry value) public bool Equals(SortedSetEntry value)
{ {
return this.score == value.score && this.element == value.element; return this.score == value.score && this.element == value.element;
} }
/// <summary> /// <summary>
/// Compares two values by score /// Compares two values by score
/// </summary> /// </summary>
public int CompareTo(SortedSetEntry value) public int CompareTo(SortedSetEntry value)
{ {
return this.score.CompareTo(value.score); return this.score.CompareTo(value.score);
} }
/// <summary> /// <summary>
/// Compares two values by score /// Compares two values by score
/// </summary> /// </summary>
public int CompareTo(object value) public int CompareTo(object value)
{ {
return value is SortedSetEntry ? CompareTo((SortedSetEntry)value) : -1; return value is SortedSetEntry ? CompareTo((SortedSetEntry)value) : -1;
} }
/// <summary> /// <summary>
/// Compares two values for equality /// Compares two values for equality
/// </summary> /// </summary>
public static bool operator ==(SortedSetEntry x, SortedSetEntry y) public static bool operator ==(SortedSetEntry x, SortedSetEntry y)
{ {
return x.score == y.score && x.element == y.element; return x.score == y.score && x.element == y.element;
} }
/// <summary> /// <summary>
/// Compares two values for non-equality /// Compares two values for non-equality
/// </summary> /// </summary>
public static bool operator !=(SortedSetEntry x, SortedSetEntry y) public static bool operator !=(SortedSetEntry x, SortedSetEntry y)
{ {
return x.score != y.score || x.element != y.element; return x.score != y.score || x.element != y.element;
} }
} }
} }
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{75CED009-AAC6-4AC1-9C38-A0530619062D}</ProjectGuid> <ProjectGuid>{75CED009-AAC6-4AC1-9C38-A0530619062D}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace> <RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis.StrongName</AssemblyName> <AssemblyName>StackExchange.Redis.StrongName</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath> <OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants> <DefineConstants>TRACE;DEBUG;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<DocumentationFile>bin.snk\Debug\StackExchange.Redis.StrongName.xml</DocumentationFile> <DocumentationFile>bin.snk\Debug\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath> <OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants> <DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile> <DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<AssemblyOriginatorKeyFile>StackExchange.Redis.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StackExchange.Redis.snk</AssemblyOriginatorKeyFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath> <OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION</DefineConstants> <DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile> <DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.Threading.Tasks"> <Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions"> <Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop"> <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.IO"> <Reference Include="System.IO">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Net" /> <Reference Include="System.Net" />
<Reference Include="System.Runtime"> <Reference Include="System.Runtime">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Threading.Tasks"> <Reference Include="System.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\StackExchange.Redis\Properties\AssemblyInfo.cs" /> <Compile Include="..\StackExchange.Redis\Properties\AssemblyInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Aggregate.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Aggregate.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Bitwise.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Bitwise.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientFlags.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientInfo.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientType.cs"> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientType.cs">
<Link>ClientType.cs</Link> <Link>ClientType.cs</Link>
</Compile> </Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\ConvertHelper.cs"> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\ConvertHelper.cs">
<Link>ConvertHelper.cs</Link> <Link>ConvertHelper.cs</Link>
</Compile> </Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\VolatileWrapper.cs"> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\VolatileWrapper.cs">
<Link>VolatileWrapper.cs</Link> <Link>VolatileWrapper.cs</Link>
</Compile> </Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConcurrentProfileStorageCollection.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.Profiling.cs"> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon> <DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClusterConfiguration.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandFlags.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandMap.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandMap.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandTrace.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandTrace.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletedDefaultTask.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletionManager.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletionManager.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Condition.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Condition.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConfigurationOptions.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionCounters.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailedEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailureType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\DebuggingAids.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointCollection.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExceptionFactory.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Exclude.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Exclude.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExportOptions.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExportOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExtensionMethods.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Format.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Format.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashEntry.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashSlotMovedEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IBatch.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ICompletable.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ICompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IConnectionMultiplexer.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabase.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabaseAsync.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IMultiMessage.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalErrorEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalRegexCompiledOption.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IProfiler.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IProfiler.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedis.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedis.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedisAsync.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IServer.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ISubscriber.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ISubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ITransaction.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ITransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LoggingTextStream.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Message.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Message.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageCompletable.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageQueue.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageQueue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MigrateOptions.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileContextTracker.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileStorage.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LuaScript.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\LuaScript.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Order.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Order.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalBridge.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalConnection.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RawResult.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RawResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBase.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBatch.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisChannel.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisChannel.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisCommand.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisCommand.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisErrorEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisFeatures.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisKey.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisKey.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisLiterals.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisResult.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisServer.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisSubscriber.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisTransaction.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisValue.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisValue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ReplicationChangeOptions.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultBox.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultBox.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultProcessor.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ScriptParameterMapper.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SaveType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SaveType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerCounters.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerEndPoint.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerSelectionStrategy.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SetOperation.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SetOperation.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ShutdownMode.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ShutdownMode.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.NoPoll.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.NoPoll.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.Poll.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.Poll.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortedSetEntry.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\StringSplits.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\StringSplits.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\TaskSource.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\TaskSource.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\When.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\When.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\BatchWrapper.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\BatchWrapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\DatabaseExtension.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\DatabaseExtension.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\DatabaseWrapper.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\DatabaseWrapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\TransactionWrapper.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\TransactionWrapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\WrapperBase.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\WrapperBase.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="StackExchange.Redis.snk" /> <None Include="StackExchange.Redis.snk" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" /> <Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''"> <Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" /> <Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" /> <Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target> </Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{36CAC6B6-2B88-447F-AA35-D4DAA5E4F2C7}</ProjectGuid> <ProjectGuid>{36CAC6B6-2B88-447F-AA35-D4DAA5E4F2C7}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace> <RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis</AssemblyName> <AssemblyName>StackExchange.Redis</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants> <DefineConstants>TRACE;DEBUG;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<DocumentationFile>bin\Debug\StackExchange.Redis.XML</DocumentationFile> <DocumentationFile>bin\Debug\StackExchange.Redis.XML</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants> <DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile> <DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath> <OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION</DefineConstants> <DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile> <DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.Threading.Tasks"> <Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions"> <Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop"> <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.IO, Version=2.6.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.IO, Version=2.6.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Net" /> <Reference Include="System.Net" />
<Reference Include="System.Runtime, Version=2.6.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Runtime, Version=2.6.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Threading.Tasks, Version=2.6.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Threading.Tasks, Version=2.6.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll</HintPath> <HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\StackExchange.Redis\Properties\AssemblyInfo.cs" /> <Compile Include="..\StackExchange.Redis\Properties\AssemblyInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Aggregate.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Aggregate.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Bitwise.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Bitwise.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientFlags.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientInfo.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientType.cs"> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientType.cs">
<Link>ClientType.cs</Link> <Link>ClientType.cs</Link>
</Compile> </Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\ConvertHelper.cs"> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\ConvertHelper.cs">
<Link>ConvertHelper.cs</Link> <Link>ConvertHelper.cs</Link>
</Compile> </Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\VolatileWrapper.cs"> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\VolatileWrapper.cs">
<Link>VolatileWrapper.cs</Link> <Link>VolatileWrapper.cs</Link>
</Compile> </Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConcurrentProfileStorageCollection.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.Profiling.cs"> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon> <DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClusterConfiguration.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandFlags.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandMap.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandMap.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandTrace.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandTrace.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletedDefaultTask.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletionManager.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletionManager.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Condition.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Condition.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConfigurationOptions.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionCounters.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailedEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailureType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\DebuggingAids.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointCollection.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExceptionFactory.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Exclude.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Exclude.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExportOptions.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExportOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExtensionMethods.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Format.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Format.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashEntry.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashSlotMovedEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IBatch.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ICompletable.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ICompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IConnectionMultiplexer.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabase.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabaseAsync.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IMultiMessage.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalErrorEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalRegexCompiledOption.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IProfiler.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IProfiler.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedis.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedis.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedisAsync.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IServer.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\IServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ISubscriber.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ISubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ITransaction.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ITransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LoggingTextStream.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Message.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Message.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageCompletable.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageQueue.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageQueue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MigrateOptions.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileContextTracker.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileStorage.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LuaScript.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\LuaScript.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Order.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\Order.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalBridge.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalConnection.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RawResult.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RawResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBase.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBatch.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisChannel.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisChannel.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisCommand.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisCommand.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisErrorEventArgs.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisFeatures.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisKey.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisKey.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisLiterals.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisResult.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisServer.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisSubscriber.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisTransaction.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisValue.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisValue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ReplicationChangeOptions.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultBox.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultBox.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultProcessor.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ScriptParameterMapper.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SaveType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SaveType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerCounters.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerEndPoint.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerSelectionStrategy.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SetOperation.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SetOperation.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ShutdownMode.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\ShutdownMode.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.NoPoll.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.NoPoll.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.Poll.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SocketManager.Poll.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortedSetEntry.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortType.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\StringSplits.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\StringSplits.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\TaskSource.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\TaskSource.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\When.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\When.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\BatchWrapper.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\BatchWrapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\DatabaseExtension.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\DatabaseExtension.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\DatabaseWrapper.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\DatabaseWrapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\TransactionWrapper.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\TransactionWrapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\WrapperBase.cs" /> <Compile Include="..\StackExchange.Redis\StackExchange\Redis\KeyspaceIsolation\WrapperBase.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" /> <Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''"> <Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" /> <Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" /> <Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target> </Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
</Target> </Target>
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>
\ No newline at end of file
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