Commit af605dd6 authored by Marc Gravell's avatar Marc Gravell

Merge branch 'jeremymeng-netcore' of...

Merge branch 'jeremymeng-netcore' of github.com:StackExchange/StackExchange.Redis into jeremymeng-netcore
parents 2712ccf9 42593761
.hg
bin
bin.snk
obj
*.suo
*.user
*.nupkg
packages/NuGet.CommandLine.*
*.sln.docstates
_ReSharper.*
Mono/
*.sln.ide
*.rdb
*.aof
*.orig
redis-cli.exe
Redis Configs/*.dat
RedisQFork*.dat
StackExchange.Redis.*.zip
.vs/
*.lock.json
\ No newline at end of file
.hg
bin
bin.snk
obj
*.suo
*.user
*.nupkg
packages/NuGet.CommandLine.*
*.sln.docstates
_ReSharper.*
Mono/
*.sln.ide
*.rdb
*.aof
*.orig
redis-cli.exe
Redis Configs/*.dat
RedisQFork*.dat
StackExchange.Redis.*.zip
.vs/
*.lock.json
......@@ -48,13 +48,13 @@
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StackExchange.Redis\StackExchange.Redis.csproj">
<Project>{7cec07f2-8c03-4c42-b048-738b215824c1}</Project>
<Name>StackExchange.Redis</Name>
</ProjectReference>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
<ProjectReference Include="..\StackExchange.Redis_Net45\StackExchange.Redis_Net45.csproj">
<Project>{7cec07f2-8c03-4c42-b048-738b215824c1}</Project>
<Name>StackExchange.Redis_Net45</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
......
{
"version": "1.0.0-*",
"description": "StackExchange.Redis.BasicTest dnxcore50",
"authors": [ "jeremymeng" ],
"authors": [ "" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
......@@ -9,11 +9,12 @@
"compile": [
"../BasicTest/Program.cs"
],
"dependencies": {
"StackExchange.Redis": "1.1.0-*"
"StackExchange.Redis": {
"version": "1.1.0-alpha1",
"target": "project"
}
},
"commands": {
"run": "BasicTest_dnxcore50"
},
......@@ -34,7 +35,7 @@
"frameworks": {
"dnxcore50": {
"dependencies": {
"System.Console": "4.0.0-beta-23409"
"System.Console": "4.0.0-beta-23516"
}
}
}
......
......@@ -113,9 +113,9 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StackExchange.Redis\StackExchange.Redis.csproj">
<ProjectReference Include="..\StackExchange.Redis_Net45\StackExchange.Redis_Net45.csproj">
<Project>{7cec07f2-8c03-4c42-b048-738b215824c1}</Project>
<Name>StackExchange.Redis</Name>
<Name>StackExchange.Redis_Net45</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
......
......@@ -87,13 +87,13 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StackExchange.Redis\StackExchange.Redis.csproj">
<Project>{7cec07f2-8c03-4c42-b048-738b215824c1}</Project>
<Name>StackExchange.Redis</Name>
</ProjectReference>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
<ProjectReference Include="..\StackExchange.Redis_Net45\StackExchange.Redis_Net45.csproj">
<Project>{7cec07f2-8c03-4c42-b048-738b215824c1}</Project>
<Name>StackExchange.Redis_Net45</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
......
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>46754d2a-ac16-4686-b113-3db08acf4269</ProjectGuid>
<RootNamespace>StackExchange.Redis.StrongName</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
\ No newline at end of file
{
"version": "1.1.0-alpha1",
"description": "High performance Redis client, incorporating both synchronous and asynchronous usage.",
"authors": [ "Stack Exchange inc., marc.gravell" ],
"owners": [ "marc.gravell" ],
"tags": [ "Async", "Redis", "Cache", "PubSub", "Messaging" ],
"projectUrl": "https://github.com/StackExchange/StackExchange.Redis",
"licenseUrl": "https://raw.github.com/StackExchange/StackExchange.Redis/master/LICENSE",
"copyright": "Stack Exchange inc. 2014-",
"requireLicenseAcceptance": false,
"summary": "Redis client library",
"compile": [
"../StackExchange.Redis/**/*.cs"
],
"dependencies": {
},
"compilationOptions": {
"allowUnsafe": true,
"keyFile": "../StackExchange.Redis.snk",
"define": [ "STRONG_NAME" ]
},
"frameworks": {
"net40": {
"dependencies": {
"Microsoft.Bcl": "1.1.10",
"Microsoft.Bcl.Async": "1.0.168"
},
"compilationOptions": {
"define": [ "FEATURE_SERIALIZATION" ]
}
},
"net45": {
"frameworkAssemblies": {
"System.IO.Compression": "4.0.0.0"
},
"compilationOptions": {
"define": [ "FEATURE_SERIALIZATION" ]
}
},
"net46": {
"frameworkAssemblies": {
"System.IO.Compression": "4.0.0.0"
},
"define": [ "FEATURE_SERIALIZATION", "PLAT_SAFE_CONTINUATIONS" ]
},
"dnxcore50": {
"compilationOptions": {
"define": [ "PLAT_SAFE_CONTINUATIONS", "CORE_CLR" ]
},
"dependencies": {
"System.Collections.Concurrent": "4.0.11-beta-23516",
"System.Collections.NonGeneric": "4.0.1-beta-23516",
"System.Diagnostics.Debug": "4.0.11-beta-23516",
"System.Diagnostics.Tools": "4.0.1-beta-23516",
"System.Diagnostics.TraceSource": "4.0.0-beta-23516",
"System.Globalization": "4.0.11-beta-23516",
"System.IO": "4.0.11-beta-23516",
"System.IO.Compression": "4.1.0-beta-23516",
"System.IO.FileSystem": "4.0.1-beta-23516",
"System.Linq": "4.0.1-beta-23516",
"System.Net.NameResolution": "4.0.0-beta-23516",
"System.Net.Primitives": "4.0.11-beta-23516",
"System.Net.Security": "4.0.0-beta-23516",
"System.Net.Sockets": "4.1.0-beta-23516",
"System.Reflection": "4.1.0-beta-23516",
"System.Reflection.Emit": "4.0.1-beta-23516",
"System.Reflection.Emit.Lightweight": "4.0.1-beta-23516",
"System.Reflection.Primitives": "4.0.1-beta-23516",
"System.Reflection.TypeExtensions": "4.1.0-beta-23516",
"System.Security.Cryptography.Algorithms": "4.0.0-beta-23516",
"System.Security.Cryptography.X509Certificates": "4.0.0-beta-23516",
"System.Text.Encoding": "4.0.11-beta-23516",
"System.Text.RegularExpressions": "4.0.11-beta-23516",
"System.Threading": "4.0.11-beta-23516",
"System.Threading.Tasks": "4.0.11-beta-23516",
"System.Threading.Thread": "4.0.0-beta-23516",
"System.Threading.ThreadPool": "4.0.10-beta-23516",
"System.Threading.Timer": "4.0.1-beta-23516"
}
},
"dotnet5.5": {
"compilationOptions": {
"define": [ "PLAT_SAFE_CONTINUATIONS", "CORE_CLR" ]
},
"dependencies": {
"System.Collections.Concurrent": "4.0.11-beta-23516",
"System.Collections.NonGeneric": "4.0.1-beta-23516",
"System.Diagnostics.Debug": "4.0.11-beta-23516",
"System.Diagnostics.Tools": "4.0.1-beta-23516",
"System.Diagnostics.TraceSource": "4.0.0-beta-23516",
"System.Globalization": "4.0.11-beta-23516",
"System.IO": "4.0.11-beta-23516",
"System.IO.Compression": "4.1.0-beta-23516",
"System.IO.FileSystem": "4.0.1-beta-23516",
"System.Linq": "4.0.1-beta-23516",
"System.Net.NameResolution": "4.0.0-beta-23516",
"System.Net.Primitives": "4.0.11-beta-23516",
"System.Net.Security": "4.0.0-beta-23516",
"System.Net.Sockets": "4.1.0-beta-23516",
"System.Reflection": "4.1.0-beta-23516",
"System.Reflection.Emit": "4.0.1-beta-23516",
"System.Reflection.Emit.Lightweight": "4.0.1-beta-23516",
"System.Reflection.Primitives": "4.0.1-beta-23516",
"System.Reflection.TypeExtensions": "4.1.0-beta-23516",
"System.Security.Cryptography.Algorithms": "4.0.0-beta-23516",
"System.Security.Cryptography.X509Certificates": "4.0.0-beta-23516",
"System.Text.Encoding": "4.0.11-beta-23516",
"System.Text.RegularExpressions": "4.0.11-beta-23516",
"System.Threading": "4.0.11-beta-23516",
"System.Threading.Tasks": "4.0.11-beta-23516",
"System.Threading.Thread": "4.0.0-beta-23516",
"System.Threading.ThreadPool": "4.0.10-beta-23516",
"System.Threading.Timer": "4.0.1-beta-23516"
}
}
}
}
\ No newline at end of file
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
#if FEATURE_BOOKSLEEVE
using BookSleeve;
#endif
using NUnit.Framework;
using StackExchange.Redis.KeyspaceIsolation;
namespace StackExchange.Redis.Tests
{
[TestFixture]
public class BasicOpsTests : TestBase
{
[Test]
[TestCase(true)]
[TestCase(false)]
public void PingOnce(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
var task = conn.PingAsync();
var duration = muxer.Wait(task);
Console.WriteLine("Ping took: " + duration);
Assert.IsTrue(duration.TotalMilliseconds > 0);
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void RapidDispose(bool preserverOrder)
{
RedisKey key = Me();
using (var primary = Create())
{
var conn = primary.GetDatabase();
conn.KeyDelete(key);
for (int i = 0; i < 10; i++)
{
using (var secondary = Create(fail: true))
{
secondary.GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
}
}
Assert.AreEqual(10, (int)conn.StringGet(key));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void PingMany(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
var tasks = new Task<TimeSpan>[10000];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = conn.PingAsync();
}
muxer.WaitAll(tasks);
Assert.IsTrue(tasks[0].Result.TotalMilliseconds > 0);
Assert.IsTrue(tasks[tasks.Length - 1].Result.TotalMilliseconds > 0);
}
}
[Test]
public void GetWithNullKey()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = null;
Assert.Throws<ArgumentException>(
() => db.StringGet(key),
"A null key is not valid in this context");
}
}
[Test]
public void SetWithNullKey()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = null, value = "abc";
Assert.Throws<ArgumentException>(
() => db.StringSet(key, value),
"A null key is not valid in this context");
}
}
[Test]
public void SetWithNullValue()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = Me(), value = null;
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value);
var actual = (string)db.StringGet(key);
Assert.IsNull(actual);
Assert.IsFalse(db.KeyExists(key));
}
}
[Test]
public void SetWithDefaultValue()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = Me();
var value = default(RedisValue); // this is kinda 0... ish
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value);
var actual = (string)db.StringGet(key);
Assert.IsNull(actual);
Assert.IsFalse(db.KeyExists(key));
}
}
[Test]
public void SetWithZeroValue()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = Me();
long value = 0;
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value);
var actual = (string)db.StringGet(key);
Assert.AreEqual("0", actual);
Assert.IsTrue(db.KeyExists(key));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void GetSetAsync(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
RedisKey key = Me();
var d0 = conn.KeyDeleteAsync(key);
var d1 = conn.KeyDeleteAsync(key);
var g1 = conn.StringGetAsync(key);
var s1 = conn.StringSetAsync(key, "123");
var g2 = conn.StringGetAsync(key);
var d2 = conn.KeyDeleteAsync(key);
muxer.Wait(d0);
Assert.IsFalse(muxer.Wait(d1));
Assert.IsNull((string)muxer.Wait(g1));
Assert.IsTrue(muxer.Wait(g1).IsNull);
muxer.Wait(s1);
Assert.AreEqual("123", (string)muxer.Wait(g2));
Assert.AreEqual(123, (int)muxer.Wait(g2));
Assert.IsFalse(muxer.Wait(g2).IsNull);
Assert.IsTrue(muxer.Wait(d2));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void GetSetSync(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
RedisKey key = Me();
conn.KeyDelete(key);
var d1 = conn.KeyDelete(key);
var g1 = conn.StringGet(key);
conn.StringSet(key, "123");
var g2 = conn.StringGet(key);
var d2 = conn.KeyDelete(key);
Assert.IsFalse(d1);
Assert.IsNull((string)g1);
Assert.IsTrue(g1.IsNull);
Assert.AreEqual("123", (string)g2);
Assert.AreEqual(123, (int)g2);
Assert.IsFalse(g2.IsNull);
Assert.IsTrue(d2);
}
}
[Test]
[TestCase(true, true)]
[TestCase(true, false)]
[TestCase(false, true)]
[TestCase(false, false)]
public void MassiveBulkOpsAsync(bool preserveOrder, bool withContinuation)
{
#if DEBUG
var oldAsyncCompletionCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
#endif
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
RedisKey key = "MBOA";
var conn = muxer.GetDatabase();
muxer.Wait(conn.PingAsync());
#if DNXCORE50
int number = 0;
#endif
Action<Task> nonTrivial = delegate
{
#if !DNXCORE50
Thread.SpinWait(5);
#else
for (int i = 0; i < 50; i++)
{
number++;
}
#endif
};
var watch = Stopwatch.StartNew();
for (int i = 0; i <= AsyncOpsQty; i++)
{
var t = conn.StringSetAsync(key, i);
if (withContinuation) t.ContinueWith(nonTrivial);
}
int val = (int)muxer.Wait(conn.StringGetAsync(key));
Assert.AreEqual(AsyncOpsQty, val);
watch.Stop();
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",
AsyncOpsQty / watch.Elapsed.TotalSeconds);
#if DEBUG
Console.WriteLine("Async completion workers: " + (ConnectionMultiplexer.GetAsyncCompletionWorkerCount() - oldAsyncCompletionCount));
#endif
}
}
[Test]
[TestCase(false, false)]
[TestCase(true, true)]
[TestCase(true, false)]
public void GetWithExpiry(bool exists, bool hasExpiry)
{
using(var conn = Create())
{
var db = conn.GetDatabase();
RedisKey key = Me();
db.KeyDelete(key);
if (exists)
{
if (hasExpiry)
db.StringSet(key, "val", TimeSpan.FromMinutes(5));
else
db.StringSet(key, "val");
}
var async = db.StringGetWithExpiryAsync(key);
var syncResult = db.StringGetWithExpiry(key);
var asyncResult = db.Wait(async);
if(exists)
{
Assert.AreEqual("val", (string)asyncResult.Value);
Assert.AreEqual(hasExpiry, asyncResult.Expiry.HasValue);
if (hasExpiry) Assert.IsTrue(asyncResult.Expiry.Value.TotalMinutes >= 4.9 && asyncResult.Expiry.Value.TotalMinutes <= 5);
Assert.AreEqual("val", (string)syncResult.Value);
Assert.AreEqual(hasExpiry, syncResult.Expiry.HasValue);
if (hasExpiry) Assert.IsTrue(syncResult.Expiry.Value.TotalMinutes >= 4.9 && syncResult.Expiry.Value.TotalMinutes <= 5);
}
else
{
Assert.IsTrue(asyncResult.Value.IsNull);
Assert.IsFalse(asyncResult.Expiry.HasValue);
Assert.IsTrue(syncResult.Value.IsNull);
Assert.IsFalse(syncResult.Expiry.HasValue);
}
}
}
[Test]
public void GetWithExpiryWrongTypeAsync()
{
using (var conn = Create())
{
var db = conn.GetDatabase();
RedisKey key = Me();
db.KeyDelete(key);
db.SetAdd(key, "abc");
Assert.Throws<RedisServerException>(() =>
{
try
{
var async = db.Wait(db.StringGetWithExpiryAsync(key));
}
catch (AggregateException ex)
{
throw ex.InnerExceptions[0];
}
Assert.Fail();
},
"A null key is not valid in this context");
}
}
[Test]
public void GetWithExpiryWrongTypeSync()
{
Assert.Throws<RedisServerException>(() =>
{
using (var conn = Create())
{
var db = conn.GetDatabase();
RedisKey key = Me();
db.KeyDelete(key);
db.SetAdd(key, "abc");
db.StringGetWithExpiry(key);
Assert.Fail();
}
},
"WRONGTYPE Operation against a key holding the wrong kind of value");
}
#if FEATURE_BOOKSLEEVE
[Test]
[TestCase(true, true, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(true, false, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(false, true, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(false, false, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(true, true, ResultCompletionMode.Concurrent)]
[TestCase(true, false, ResultCompletionMode.Concurrent)]
[TestCase(false, true, ResultCompletionMode.Concurrent)]
[TestCase(false, false, ResultCompletionMode.Concurrent)]
[TestCase(true, true, ResultCompletionMode.PreserveOrder)]
[TestCase(true, false, ResultCompletionMode.PreserveOrder)]
[TestCase(false, true, ResultCompletionMode.PreserveOrder)]
[TestCase(false, false, ResultCompletionMode.PreserveOrder)]
public void MassiveBulkOpsAsyncOldStyle(bool withContinuation, bool suspendFlush, ResultCompletionMode completionMode)
{
using (var conn = GetOldStyleConnection())
{
const int db = 0;
string key = "MBOQ";
conn.CompletionMode = completionMode;
conn.Wait(conn.Server.Ping());
Action<Task> nonTrivial = delegate
{
Thread.SpinWait(5);
};
var watch = Stopwatch.StartNew();
if (suspendFlush) conn.SuspendFlush();
try
{
for (int i = 0; i <= AsyncOpsQty; i++)
{
var t = conn.Strings.Set(db, key, i);
if (withContinuation) t.ContinueWith(nonTrivial);
}
} finally
{
if (suspendFlush) conn.ResumeFlush();
}
int val = (int)conn.Wait(conn.Strings.GetInt64(db, key));
Assert.AreEqual(AsyncOpsQty, val);
watch.Stop();
Console.WriteLine("{2}: Time for {0} ops: {1}ms ({3}, {4}, {5}); ops/s: {6}", AsyncOpsQty, watch.ElapsedMilliseconds, Me(),
withContinuation ? "with continuation" : "no continuation",
suspendFlush ? "suspend flush" : "flush at whim",
completionMode, AsyncOpsQty / watch.Elapsed.TotalSeconds);
}
}
#endif
[Test]
[TestCase(true, 1)]
[TestCase(false, 1)]
[TestCase(true, 5)]
[TestCase(false, 5)]
[TestCase(true, 10)]
[TestCase(false, 10)]
[TestCase(true, 50)]
[TestCase(false, 50)]
public void MassiveBulkOpsSync(bool preserveOrder, int threads)
{
int workPerThread = SyncOpsQty / threads;
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
RedisKey key = "MBOS";
var conn = muxer.GetDatabase();
conn.KeyDelete(key);
#if DEBUG
long oldAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
long oldWorkerCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
#endif
var timeTaken = RunConcurrent(delegate
{
for (int i = 0; i < workPerThread; i++)
{
conn.StringIncrement(key);
}
}, threads);
int val = (int)conn.StringGet(key);
Assert.AreEqual(workPerThread * threads, val);
Console.WriteLine("{2}: Time for {0} ops on {4} threads: {1}ms ({3}); ops/s: {5}",
threads * workPerThread, timeTaken.TotalMilliseconds, Me()
, preserveOrder ? "preserve order" : "any order", threads, (workPerThread * threads) / timeTaken.TotalSeconds);
#if DEBUG
long newAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
long newWorkerCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
Console.WriteLine("ResultBox allocations: {0}; workers {1}", newAlloc - oldAlloc, newWorkerCount - oldWorkerCount);
Assert.IsTrue(newAlloc - oldAlloc <= 2 * threads, "number of box allocations");
#endif
}
}
#if FEATURE_BOOKSLEEVE
[Test]
[TestCase(ResultCompletionMode.Concurrent, 1)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 1)]
[TestCase(ResultCompletionMode.PreserveOrder, 1)]
[TestCase(ResultCompletionMode.Concurrent, 5)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 5)]
[TestCase(ResultCompletionMode.PreserveOrder, 5)]
[TestCase(ResultCompletionMode.Concurrent, 10)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 10)]
[TestCase(ResultCompletionMode.PreserveOrder, 10)]
[TestCase(ResultCompletionMode.Concurrent, 50)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 50)]
[TestCase(ResultCompletionMode.PreserveOrder, 50)]
public void MassiveBulkOpsSyncOldStyle(ResultCompletionMode completionMode, int threads)
{
int workPerThread = SyncOpsQty / threads;
using (var conn = GetOldStyleConnection())
{
const int db = 0;
string key = "MBOQ";
conn.CompletionMode = completionMode;
conn.Wait(conn.Keys.Remove(db, key));
var timeTaken = RunConcurrent(delegate
{
for (int i = 0; i < workPerThread; i++)
{
conn.Wait(conn.Strings.Increment(db, key));
}
}, threads);
int val = (int)conn.Wait(conn.Strings.GetInt64(db, key));
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(),
completionMode, threads, (workPerThread * threads) / timeTaken.TotalSeconds);
}
}
#endif
[Test]
[TestCase(true, 1)]
[TestCase(false, 1)]
[TestCase(true, 5)]
[TestCase(false, 5)]
public void MassiveBulkOpsFireAndForget(bool preserveOrder, int threads)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
#if DEBUG
long oldAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
#endif
RedisKey key = "MBOF";
var conn = muxer.GetDatabase();
conn.Ping();
conn.KeyDelete(key, CommandFlags.FireAndForget);
int perThread = AsyncOpsQty / threads;
var elapsed = RunConcurrent(delegate
{
for (int i = 0; i < perThread; i++)
{
conn.StringIncrement(key, flags: CommandFlags.FireAndForget);
}
conn.Ping();
}, threads);
var val = (long)conn.StringGet(key);
Assert.AreEqual(perThread * threads, val);
Console.WriteLine("{2}: Time for {0} ops over {5} threads: {1:###,###}ms ({3}); ops/s: {4:###,###,##0}",
val, elapsed.TotalMilliseconds, Me(),
preserveOrder ? "preserve order" : "any order",
val / elapsed.TotalSeconds, threads);
#if DEBUG
long newAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
Console.WriteLine("ResultBox allocations: {0}",
newAlloc - oldAlloc);
Assert.IsTrue(newAlloc - oldAlloc <= 4);
#endif
}
}
#if DEBUG
[Test]
[TestCase(true)]
[TestCase(false)]
public void TestQuit(bool preserveOrder)
{
SetExpectedAmbientFailureCount(1);
using (var muxer = Create(allowAdmin: true))
{
muxer.PreserveAsyncOrder = preserveOrder;
var db = muxer.GetDatabase();
string key = Guid.NewGuid().ToString();
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, key, flags: CommandFlags.FireAndForget);
GetServer(muxer).Quit(CommandFlags.FireAndForget);
var watch = Stopwatch.StartNew();
try
{
db.Ping();
Assert.Fail();
}
catch (RedisConnectionException) { }
watch.Stop();
Console.WriteLine("Time to notice quit: {0}ms ({1})", watch.ElapsedMilliseconds,
preserveOrder ? "preserve order" : "any order");
Thread.Sleep(20);
Debug.WriteLine("Pinging...");
Assert.AreEqual(key, (string)db.StringGet(key));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void TestSevered(bool preserveOrder)
{
SetExpectedAmbientFailureCount(2);
using (var muxer = Create(allowAdmin: true))
{
muxer.PreserveAsyncOrder = preserveOrder;
var db = muxer.GetDatabase();
string key = Guid.NewGuid().ToString();
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, key, flags: CommandFlags.FireAndForget);
GetServer(muxer).SimulateConnectionFailure();
var watch = Stopwatch.StartNew();
db.Ping();
watch.Stop();
Console.WriteLine("Time to re-establish: {0}ms ({1})", watch.ElapsedMilliseconds,
preserveOrder ? "preserve order" : "any order");
Thread.Sleep(20);
Debug.WriteLine("Pinging...");
Assert.AreEqual(key, (string)db.StringGet(key));
}
}
#endif
[Test]
[TestCase(true)]
[TestCase(false)]
public void IncrAsync(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
RedisKey key = Me();
conn.KeyDelete(key, CommandFlags.FireAndForget);
var nix = conn.KeyExistsAsync(key);
var a = conn.StringGetAsync(key);
var b = conn.StringIncrementAsync(key);
var c = conn.StringGetAsync(key);
var d = conn.StringIncrementAsync(key, 10);
var e = conn.StringGetAsync(key);
var f = conn.StringDecrementAsync(key, 11);
var g = conn.StringGetAsync(key);
var h = conn.KeyExistsAsync(key);
Assert.IsFalse(muxer.Wait(nix));
Assert.IsTrue(muxer.Wait(a).IsNull);
Assert.AreEqual(0, (long)muxer.Wait(a));
Assert.AreEqual(1, muxer.Wait(b));
Assert.AreEqual(1, (long)muxer.Wait(c));
Assert.AreEqual(11, muxer.Wait(d));
Assert.AreEqual(11, (long)muxer.Wait(e));
Assert.AreEqual(0, muxer.Wait(f));
Assert.AreEqual(0, (long)muxer.Wait(g));
Assert.IsTrue(muxer.Wait(h));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void IncrSync(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
RedisKey key = Me();
conn.KeyDelete(key, CommandFlags.FireAndForget);
var nix = conn.KeyExists(key);
var a = conn.StringGet(key);
var b = conn.StringIncrement(key);
var c = conn.StringGet(key);
var d = conn.StringIncrement(key, 10);
var e = conn.StringGet(key);
var f = conn.StringDecrement(key, 11);
var g = conn.StringGet(key);
var h = conn.KeyExists(key);
Assert.IsFalse(nix);
Assert.IsTrue(a.IsNull);
Assert.AreEqual(0, (long)a);
Assert.AreEqual(1, b);
Assert.AreEqual(1, (long)c);
Assert.AreEqual(11, d);
Assert.AreEqual(11, (long)e);
Assert.AreEqual(0, f);
Assert.AreEqual(0, (long)g);
Assert.IsTrue(h);
}
}
[Test]
public void IncrDifferentSizes()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
RedisKey key = Me();
db.KeyDelete(key, CommandFlags.FireAndForget);
int expected = 0;
Incr(db, key, -129019, ref expected);
Incr(db, key, -10023, ref expected);
Incr(db, key, -9933, ref expected);
Incr(db, key, -23, ref expected);
Incr(db, key, -7, ref expected);
Incr(db, key, -1, ref expected);
Incr(db, key, 0, ref expected);
Incr(db, key, 1, ref expected);
Incr(db, key, 9, ref expected);
Incr(db, key, 11, ref expected);
Incr(db, key, 345, ref expected);
Incr(db, key, 4982, ref expected);
Incr(db, key, 13091, ref expected);
Incr(db, key, 324092, ref expected);
Assert.AreNotEqual(0, expected);
var sum = (long)db.StringGet(key);
Assert.AreEqual(expected, sum);
}
}
private void Incr(IDatabase database, RedisKey key, int delta, ref int total)
{
database.StringIncrement(key, delta, CommandFlags.FireAndForget);
total += delta;
}
[Test]
public void WrappedDatabasePrefixIntegration()
{
using (var conn = Create())
{
var db = conn.GetDatabase().WithKeyPrefix("abc");
db.KeyDelete("count");
db.StringIncrement("count");
db.StringIncrement("count");
db.StringIncrement("count");
int count = (int)conn.GetDatabase().StringGet("abccount");
Assert.AreEqual(3, count);
}
}
}
}
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
#if FEATURE_BOOKSLEEVE
using BookSleeve;
#endif
using NUnit.Framework;
using StackExchange.Redis.KeyspaceIsolation;
namespace StackExchange.Redis.Tests
{
[TestFixture]
public class BasicOpsTests : TestBase
{
[Test]
[TestCase(true)]
[TestCase(false)]
public void PingOnce(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
var task = conn.PingAsync();
var duration = muxer.Wait(task);
Console.WriteLine("Ping took: " + duration);
Assert.IsTrue(duration.TotalMilliseconds > 0);
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void RapidDispose(bool preserverOrder)
{
RedisKey key = Me();
using (var primary = Create())
{
var conn = primary.GetDatabase();
conn.KeyDelete(key);
for (int i = 0; i < 10; i++)
{
using (var secondary = Create(fail: true))
{
secondary.GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
}
}
Assert.AreEqual(10, (int)conn.StringGet(key));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void PingMany(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
var tasks = new Task<TimeSpan>[10000];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = conn.PingAsync();
}
muxer.WaitAll(tasks);
Assert.IsTrue(tasks[0].Result.TotalMilliseconds > 0);
Assert.IsTrue(tasks[tasks.Length - 1].Result.TotalMilliseconds > 0);
}
}
[Test]
public void GetWithNullKey()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = null;
Assert.Throws<ArgumentException>(
() => db.StringGet(key),
"A null key is not valid in this context");
}
}
[Test]
public void SetWithNullKey()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = null, value = "abc";
Assert.Throws<ArgumentException>(
() => db.StringSet(key, value),
"A null key is not valid in this context");
}
}
[Test]
public void SetWithNullValue()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = Me(), value = null;
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value);
var actual = (string)db.StringGet(key);
Assert.IsNull(actual);
Assert.IsFalse(db.KeyExists(key));
}
}
[Test]
public void SetWithDefaultValue()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = Me();
var value = default(RedisValue); // this is kinda 0... ish
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value);
var actual = (string)db.StringGet(key);
Assert.IsNull(actual);
Assert.IsFalse(db.KeyExists(key));
}
}
[Test]
public void SetWithZeroValue()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = Me();
long value = 0;
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, "abc", flags: CommandFlags.FireAndForget);
Assert.IsTrue(db.KeyExists(key));
db.StringSet(key, value);
var actual = (string)db.StringGet(key);
Assert.AreEqual("0", actual);
Assert.IsTrue(db.KeyExists(key));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void GetSetAsync(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
RedisKey key = Me();
var d0 = conn.KeyDeleteAsync(key);
var d1 = conn.KeyDeleteAsync(key);
var g1 = conn.StringGetAsync(key);
var s1 = conn.StringSetAsync(key, "123");
var g2 = conn.StringGetAsync(key);
var d2 = conn.KeyDeleteAsync(key);
muxer.Wait(d0);
Assert.IsFalse(muxer.Wait(d1));
Assert.IsNull((string)muxer.Wait(g1));
Assert.IsTrue(muxer.Wait(g1).IsNull);
muxer.Wait(s1);
Assert.AreEqual("123", (string)muxer.Wait(g2));
Assert.AreEqual(123, (int)muxer.Wait(g2));
Assert.IsFalse(muxer.Wait(g2).IsNull);
Assert.IsTrue(muxer.Wait(d2));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void GetSetSync(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
RedisKey key = Me();
conn.KeyDelete(key);
var d1 = conn.KeyDelete(key);
var g1 = conn.StringGet(key);
conn.StringSet(key, "123");
var g2 = conn.StringGet(key);
var d2 = conn.KeyDelete(key);
Assert.IsFalse(d1);
Assert.IsNull((string)g1);
Assert.IsTrue(g1.IsNull);
Assert.AreEqual("123", (string)g2);
Assert.AreEqual(123, (int)g2);
Assert.IsFalse(g2.IsNull);
Assert.IsTrue(d2);
}
}
[Test]
[TestCase(true, true)]
[TestCase(true, false)]
[TestCase(false, true)]
[TestCase(false, false)]
public void MassiveBulkOpsAsync(bool preserveOrder, bool withContinuation)
{
#if DEBUG
var oldAsyncCompletionCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
#endif
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
RedisKey key = "MBOA";
var conn = muxer.GetDatabase();
muxer.Wait(conn.PingAsync());
#if CORE_CLR
int number = 0;
#endif
Action<Task> nonTrivial = delegate
{
#if !CORE_CLR
Thread.SpinWait(5);
#else
for (int i = 0; i < 50; i++)
{
number++;
}
#endif
};
var watch = Stopwatch.StartNew();
for (int i = 0; i <= AsyncOpsQty; i++)
{
var t = conn.StringSetAsync(key, i);
if (withContinuation) t.ContinueWith(nonTrivial);
}
int val = (int)muxer.Wait(conn.StringGetAsync(key));
Assert.AreEqual(AsyncOpsQty, val);
watch.Stop();
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",
AsyncOpsQty / watch.Elapsed.TotalSeconds);
#if DEBUG
Console.WriteLine("Async completion workers: " + (ConnectionMultiplexer.GetAsyncCompletionWorkerCount() - oldAsyncCompletionCount));
#endif
}
}
[Test]
[TestCase(false, false)]
[TestCase(true, true)]
[TestCase(true, false)]
public void GetWithExpiry(bool exists, bool hasExpiry)
{
using(var conn = Create())
{
var db = conn.GetDatabase();
RedisKey key = Me();
db.KeyDelete(key);
if (exists)
{
if (hasExpiry)
db.StringSet(key, "val", TimeSpan.FromMinutes(5));
else
db.StringSet(key, "val");
}
var async = db.StringGetWithExpiryAsync(key);
var syncResult = db.StringGetWithExpiry(key);
var asyncResult = db.Wait(async);
if(exists)
{
Assert.AreEqual("val", (string)asyncResult.Value);
Assert.AreEqual(hasExpiry, asyncResult.Expiry.HasValue);
if (hasExpiry) Assert.IsTrue(asyncResult.Expiry.Value.TotalMinutes >= 4.9 && asyncResult.Expiry.Value.TotalMinutes <= 5);
Assert.AreEqual("val", (string)syncResult.Value);
Assert.AreEqual(hasExpiry, syncResult.Expiry.HasValue);
if (hasExpiry) Assert.IsTrue(syncResult.Expiry.Value.TotalMinutes >= 4.9 && syncResult.Expiry.Value.TotalMinutes <= 5);
}
else
{
Assert.IsTrue(asyncResult.Value.IsNull);
Assert.IsFalse(asyncResult.Expiry.HasValue);
Assert.IsTrue(syncResult.Value.IsNull);
Assert.IsFalse(syncResult.Expiry.HasValue);
}
}
}
[Test]
public void GetWithExpiryWrongTypeAsync()
{
using (var conn = Create())
{
var db = conn.GetDatabase();
RedisKey key = Me();
db.KeyDelete(key);
db.SetAdd(key, "abc");
Assert.Throws<RedisServerException>(() =>
{
try
{
var async = db.Wait(db.StringGetWithExpiryAsync(key));
}
catch (AggregateException ex)
{
throw ex.InnerExceptions[0];
}
Assert.Fail();
},
"A null key is not valid in this context");
}
}
[Test]
public void GetWithExpiryWrongTypeSync()
{
Assert.Throws<RedisServerException>(() =>
{
using (var conn = Create())
{
var db = conn.GetDatabase();
RedisKey key = Me();
db.KeyDelete(key);
db.SetAdd(key, "abc");
db.StringGetWithExpiry(key);
Assert.Fail();
}
},
"WRONGTYPE Operation against a key holding the wrong kind of value");
}
#if FEATURE_BOOKSLEEVE
[Test]
[TestCase(true, true, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(true, false, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(false, true, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(false, false, ResultCompletionMode.ConcurrentIfContinuation)]
[TestCase(true, true, ResultCompletionMode.Concurrent)]
[TestCase(true, false, ResultCompletionMode.Concurrent)]
[TestCase(false, true, ResultCompletionMode.Concurrent)]
[TestCase(false, false, ResultCompletionMode.Concurrent)]
[TestCase(true, true, ResultCompletionMode.PreserveOrder)]
[TestCase(true, false, ResultCompletionMode.PreserveOrder)]
[TestCase(false, true, ResultCompletionMode.PreserveOrder)]
[TestCase(false, false, ResultCompletionMode.PreserveOrder)]
public void MassiveBulkOpsAsyncOldStyle(bool withContinuation, bool suspendFlush, ResultCompletionMode completionMode)
{
using (var conn = GetOldStyleConnection())
{
const int db = 0;
string key = "MBOQ";
conn.CompletionMode = completionMode;
conn.Wait(conn.Server.Ping());
Action<Task> nonTrivial = delegate
{
Thread.SpinWait(5);
};
var watch = Stopwatch.StartNew();
if (suspendFlush) conn.SuspendFlush();
try
{
for (int i = 0; i <= AsyncOpsQty; i++)
{
var t = conn.Strings.Set(db, key, i);
if (withContinuation) t.ContinueWith(nonTrivial);
}
} finally
{
if (suspendFlush) conn.ResumeFlush();
}
int val = (int)conn.Wait(conn.Strings.GetInt64(db, key));
Assert.AreEqual(AsyncOpsQty, val);
watch.Stop();
Console.WriteLine("{2}: Time for {0} ops: {1}ms ({3}, {4}, {5}); ops/s: {6}", AsyncOpsQty, watch.ElapsedMilliseconds, Me(),
withContinuation ? "with continuation" : "no continuation",
suspendFlush ? "suspend flush" : "flush at whim",
completionMode, AsyncOpsQty / watch.Elapsed.TotalSeconds);
}
}
#endif
[Test]
[TestCase(true, 1)]
[TestCase(false, 1)]
[TestCase(true, 5)]
[TestCase(false, 5)]
[TestCase(true, 10)]
[TestCase(false, 10)]
[TestCase(true, 50)]
[TestCase(false, 50)]
public void MassiveBulkOpsSync(bool preserveOrder, int threads)
{
int workPerThread = SyncOpsQty / threads;
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
RedisKey key = "MBOS";
var conn = muxer.GetDatabase();
conn.KeyDelete(key);
#if DEBUG
long oldAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
long oldWorkerCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
#endif
var timeTaken = RunConcurrent(delegate
{
for (int i = 0; i < workPerThread; i++)
{
conn.StringIncrement(key);
}
}, threads);
int val = (int)conn.StringGet(key);
Assert.AreEqual(workPerThread * threads, val);
Console.WriteLine("{2}: Time for {0} ops on {4} threads: {1}ms ({3}); ops/s: {5}",
threads * workPerThread, timeTaken.TotalMilliseconds, Me()
, preserveOrder ? "preserve order" : "any order", threads, (workPerThread * threads) / timeTaken.TotalSeconds);
#if DEBUG
long newAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
long newWorkerCount = ConnectionMultiplexer.GetAsyncCompletionWorkerCount();
Console.WriteLine("ResultBox allocations: {0}; workers {1}", newAlloc - oldAlloc, newWorkerCount - oldWorkerCount);
Assert.IsTrue(newAlloc - oldAlloc <= 2 * threads, "number of box allocations");
#endif
}
}
#if FEATURE_BOOKSLEEVE
[Test]
[TestCase(ResultCompletionMode.Concurrent, 1)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 1)]
[TestCase(ResultCompletionMode.PreserveOrder, 1)]
[TestCase(ResultCompletionMode.Concurrent, 5)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 5)]
[TestCase(ResultCompletionMode.PreserveOrder, 5)]
[TestCase(ResultCompletionMode.Concurrent, 10)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 10)]
[TestCase(ResultCompletionMode.PreserveOrder, 10)]
[TestCase(ResultCompletionMode.Concurrent, 50)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 50)]
[TestCase(ResultCompletionMode.PreserveOrder, 50)]
public void MassiveBulkOpsSyncOldStyle(ResultCompletionMode completionMode, int threads)
{
int workPerThread = SyncOpsQty / threads;
using (var conn = GetOldStyleConnection())
{
const int db = 0;
string key = "MBOQ";
conn.CompletionMode = completionMode;
conn.Wait(conn.Keys.Remove(db, key));
var timeTaken = RunConcurrent(delegate
{
for (int i = 0; i < workPerThread; i++)
{
conn.Wait(conn.Strings.Increment(db, key));
}
}, threads);
int val = (int)conn.Wait(conn.Strings.GetInt64(db, key));
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(),
completionMode, threads, (workPerThread * threads) / timeTaken.TotalSeconds);
}
}
#endif
[Test]
[TestCase(true, 1)]
[TestCase(false, 1)]
[TestCase(true, 5)]
[TestCase(false, 5)]
public void MassiveBulkOpsFireAndForget(bool preserveOrder, int threads)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
#if DEBUG
long oldAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
#endif
RedisKey key = "MBOF";
var conn = muxer.GetDatabase();
conn.Ping();
conn.KeyDelete(key, CommandFlags.FireAndForget);
int perThread = AsyncOpsQty / threads;
var elapsed = RunConcurrent(delegate
{
for (int i = 0; i < perThread; i++)
{
conn.StringIncrement(key, flags: CommandFlags.FireAndForget);
}
conn.Ping();
}, threads);
var val = (long)conn.StringGet(key);
Assert.AreEqual(perThread * threads, val);
Console.WriteLine("{2}: Time for {0} ops over {5} threads: {1:###,###}ms ({3}); ops/s: {4:###,###,##0}",
val, elapsed.TotalMilliseconds, Me(),
preserveOrder ? "preserve order" : "any order",
val / elapsed.TotalSeconds, threads);
#if DEBUG
long newAlloc = ConnectionMultiplexer.GetResultBoxAllocationCount();
Console.WriteLine("ResultBox allocations: {0}",
newAlloc - oldAlloc);
Assert.IsTrue(newAlloc - oldAlloc <= 4);
#endif
}
}
#if DEBUG
[Test]
[TestCase(true)]
[TestCase(false)]
public void TestQuit(bool preserveOrder)
{
SetExpectedAmbientFailureCount(1);
using (var muxer = Create(allowAdmin: true))
{
muxer.PreserveAsyncOrder = preserveOrder;
var db = muxer.GetDatabase();
string key = Guid.NewGuid().ToString();
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, key, flags: CommandFlags.FireAndForget);
GetServer(muxer).Quit(CommandFlags.FireAndForget);
var watch = Stopwatch.StartNew();
try
{
db.Ping();
Assert.Fail();
}
catch (RedisConnectionException) { }
watch.Stop();
Console.WriteLine("Time to notice quit: {0}ms ({1})", watch.ElapsedMilliseconds,
preserveOrder ? "preserve order" : "any order");
Thread.Sleep(20);
Debug.WriteLine("Pinging...");
Assert.AreEqual(key, (string)db.StringGet(key));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void TestSevered(bool preserveOrder)
{
SetExpectedAmbientFailureCount(2);
using (var muxer = Create(allowAdmin: true))
{
muxer.PreserveAsyncOrder = preserveOrder;
var db = muxer.GetDatabase();
string key = Guid.NewGuid().ToString();
db.KeyDelete(key, CommandFlags.FireAndForget);
db.StringSet(key, key, flags: CommandFlags.FireAndForget);
GetServer(muxer).SimulateConnectionFailure();
var watch = Stopwatch.StartNew();
db.Ping();
watch.Stop();
Console.WriteLine("Time to re-establish: {0}ms ({1})", watch.ElapsedMilliseconds,
preserveOrder ? "preserve order" : "any order");
Thread.Sleep(20);
Debug.WriteLine("Pinging...");
Assert.AreEqual(key, (string)db.StringGet(key));
}
}
#endif
[Test]
[TestCase(true)]
[TestCase(false)]
public void IncrAsync(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
RedisKey key = Me();
conn.KeyDelete(key, CommandFlags.FireAndForget);
var nix = conn.KeyExistsAsync(key);
var a = conn.StringGetAsync(key);
var b = conn.StringIncrementAsync(key);
var c = conn.StringGetAsync(key);
var d = conn.StringIncrementAsync(key, 10);
var e = conn.StringGetAsync(key);
var f = conn.StringDecrementAsync(key, 11);
var g = conn.StringGetAsync(key);
var h = conn.KeyExistsAsync(key);
Assert.IsFalse(muxer.Wait(nix));
Assert.IsTrue(muxer.Wait(a).IsNull);
Assert.AreEqual(0, (long)muxer.Wait(a));
Assert.AreEqual(1, muxer.Wait(b));
Assert.AreEqual(1, (long)muxer.Wait(c));
Assert.AreEqual(11, muxer.Wait(d));
Assert.AreEqual(11, (long)muxer.Wait(e));
Assert.AreEqual(0, muxer.Wait(f));
Assert.AreEqual(0, (long)muxer.Wait(g));
Assert.IsTrue(muxer.Wait(h));
}
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void IncrSync(bool preserveOrder)
{
using (var muxer = Create())
{
muxer.PreserveAsyncOrder = preserveOrder;
var conn = muxer.GetDatabase();
RedisKey key = Me();
conn.KeyDelete(key, CommandFlags.FireAndForget);
var nix = conn.KeyExists(key);
var a = conn.StringGet(key);
var b = conn.StringIncrement(key);
var c = conn.StringGet(key);
var d = conn.StringIncrement(key, 10);
var e = conn.StringGet(key);
var f = conn.StringDecrement(key, 11);
var g = conn.StringGet(key);
var h = conn.KeyExists(key);
Assert.IsFalse(nix);
Assert.IsTrue(a.IsNull);
Assert.AreEqual(0, (long)a);
Assert.AreEqual(1, b);
Assert.AreEqual(1, (long)c);
Assert.AreEqual(11, d);
Assert.AreEqual(11, (long)e);
Assert.AreEqual(0, f);
Assert.AreEqual(0, (long)g);
Assert.IsTrue(h);
}
}
[Test]
public void IncrDifferentSizes()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
RedisKey key = Me();
db.KeyDelete(key, CommandFlags.FireAndForget);
int expected = 0;
Incr(db, key, -129019, ref expected);
Incr(db, key, -10023, ref expected);
Incr(db, key, -9933, ref expected);
Incr(db, key, -23, ref expected);
Incr(db, key, -7, ref expected);
Incr(db, key, -1, ref expected);
Incr(db, key, 0, ref expected);
Incr(db, key, 1, ref expected);
Incr(db, key, 9, ref expected);
Incr(db, key, 11, ref expected);
Incr(db, key, 345, ref expected);
Incr(db, key, 4982, ref expected);
Incr(db, key, 13091, ref expected);
Incr(db, key, 324092, ref expected);
Assert.AreNotEqual(0, expected);
var sum = (long)db.StringGet(key);
Assert.AreEqual(expected, sum);
}
}
private void Incr(IDatabase database, RedisKey key, int delta, ref int total)
{
database.StringIncrement(key, delta, CommandFlags.FireAndForget);
total += delta;
}
[Test]
public void WrappedDatabasePrefixIntegration()
{
using (var conn = Create())
{
var db = conn.GetDatabase().WithKeyPrefix("abc");
db.KeyDelete("count");
db.StringIncrement("count");
db.StringIncrement("count");
db.StringIncrement("count");
int count = (int)conn.GetDatabase().StringGet("abccount");
Assert.AreEqual(3, count);
}
}
}
}
......@@ -20,7 +20,7 @@ public class Cluster : TestBase
protected override string GetConfiguration()
{
var server = ClusterIp;
#if !DNXCORE50
#if !CORE_CLR
if (string.Equals(Environment.MachineName, "MARC-LAPTOP", StringComparison.InvariantCultureIgnoreCase))
#else
if (string.Equals(Environment.GetEnvironmentVariable("COMPUTERNAME"), "MARC-LAPTOP", StringComparison.OrdinalIgnoreCase))
......
......@@ -147,7 +147,7 @@ public void ReadConfig()
var all = conn.ConfigGet();
Assert.IsTrue(all.Length > 0, "any");
#if !DNXCORE50
#if !CORE_CLR
var pairs = all.ToDictionary(x => (string)x.Key, x => (string)x.Value, StringComparer.InvariantCultureIgnoreCase);
#else
var pairs = all.ToDictionary(x => (string)x.Key, x => (string)x.Value, StringComparer.OrdinalIgnoreCase);
......
......@@ -150,7 +150,7 @@ public void CheckSyncAsyncMethodsMatch(Type from, Type to)
var pFrom = method.GetParameters();
Type[] args = pFrom.Select(x => x.ParameterType).ToArray();
Assert.AreEqual(typeof(CommandFlags), args.Last());
#if !DNXCORE50
#if !CORE_CLR
var found = to.GetMethod(huntName, flags, null, method.CallingConvention, args, null);
#else
var found = to.GetMethods(flags)
......@@ -176,14 +176,14 @@ void CheckMethod(MethodInfo method, bool isAsync)
{
#if DEBUG
#if !DNXCORE50
#if !CORE_CLR
bool ignorePrefix = ignoreType != null && Attribute.IsDefined(method, ignoreType);
#else
bool ignorePrefix = ignoreType != null && method.IsDefined(ignoreType);
#endif
if (ignorePrefix)
{
#if !DNXCORE50
#if !CORE_CLR
Attribute attrib = Attribute.GetCustomAttribute(method, ignoreType);
#else
Attribute attrib = method.GetCustomAttribute(ignoreType);
......@@ -228,7 +228,7 @@ void CheckName(MemberInfo member, bool isAsync)
public static class ReflectionExtensions
{
#if !DNXCORE50
#if !CORE_CLR
public static Type GetTypeInfo(this Type type)
{
return type;
......
......@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
#if DNXCORE50
#if CORE_CLR
using System.Reflection;
#endif
using System.Threading.Tasks;
......
#if NUNITLITE
using System;
using System.Reflection;
using NUnitLite;
......@@ -11,4 +12,5 @@ public int Main(string[] args)
return new AutoRun().Execute(typeof(TestBase).GetTypeInfo().Assembly, Console.Out, Console.In, args);
}
}
}
\ No newline at end of file
}
#endif
\ No newline at end of file
......@@ -417,7 +417,7 @@ internal static class VolatileWrapper
{
public static int Read(ref int location)
{
#if !DNXCORE50
#if !CORE_CLR
return Thread.VolatileRead(ref location);
#else
return Volatile.Read(ref location);
......
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>a51dca17-e8f1-44e1-9a37-328fab14d2ce</ProjectGuid>
<ProjectGuid>3b8bd8f1-8bfc-4d8c-b4da-25ffaf3d1dbe</ProjectGuid>
<RootNamespace>StackExchange.Redis.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\StackExchange.Redis_dnxcore50\StackExchange.Redis\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\StackExchange.Redis_dnxcore50\StackExchange.Redis\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
......
......@@ -246,7 +246,7 @@ private static RedisConnection GetOldStyleConnection(string host, int port, bool
protected static TimeSpan RunConcurrent(Action work, int threads, int timeout = 10000, [CallerMemberName] string caller = null)
{
if (work == null) throw new ArgumentNullException("work");
if (threads < 1) throw new ArgumentOutOfRangeException("theads");
if (threads < 1) throw new ArgumentOutOfRangeException("threads");
if(string.IsNullOrWhiteSpace(caller)) caller = Me();
Stopwatch watch = null;
ManualResetEvent allDone = new ManualResetEvent(false);
......@@ -285,7 +285,7 @@ protected static TimeSpan RunConcurrent(Action work, int threads, int timeout =
}
if (!allDone.WaitOne(timeout))
{
#if !DNXCORE50
#if !CORE_CLR
for (int i = 0; i < threads; i++)
{
var thd = threadArr[i];
......
using System;
using NUnit.Framework;
using StackExchange.Redis.KeyspaceIsolation;
namespace StackExchange.Redis.Tests
{
[TestFixture]
public class WithKeyPrefixTests : TestBase
{
[Test]
public void BlankPrefixYieldsSame_Bytes()
{
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix(new byte[0]);
Assert.AreSame(raw, prefixed);
}
}
[Test]
public void BlankPrefixYieldsSame_String()
{
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix("");
Assert.AreSame(raw, prefixed);
}
}
[Test]
public void NullPrefixIsError_Bytes()
{
Assert.Throws<ArgumentNullException>(() => {
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix((byte[])null);
}
});
}
[Test]
public void NullPrefixIsError_String()
{
Assert.Throws<ArgumentNullException>(() => {
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix((string)null);
}
});
}
[Test]
[TestCase("abc")]
[TestCase("")]
[TestCase(null)]
public void NullDatabaseIsError(string prefix)
{
Assert.Throws<ArgumentNullException>(() => {
IDatabase raw = null;
var prefixed = raw.WithKeyPrefix(prefix);
});
}
[Test]
public void BasicSmokeTest()
{
using(var conn = Create())
{
var raw = conn.GetDatabase(1);
var foo = raw.WithKeyPrefix("foo");
var foobar = foo.WithKeyPrefix("bar");
string key = Me();
string s = Guid.NewGuid().ToString(), t = Guid.NewGuid().ToString();
foo.StringSet(key, s);
var val = (string)foo.StringGet(key);
Assert.AreEqual(s, val); // fooBasicSmokeTest
foobar.StringSet(key, t);
val = (string)foobar.StringGet(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("foobar" + key);
Assert.AreEqual(t, val); // foobarBasicSmokeTest
}
}
[Test]
public void ConditionTest()
{
using(var conn = Create())
{
var raw = conn.GetDatabase(2);
var foo = raw.WithKeyPrefix("tran:");
raw.KeyDelete("tran:abc");
raw.KeyDelete("tran:i");
// execute while key exists
raw.StringSet("tran:abc", "def");
var tran = foo.CreateTransaction();
tran.AddCondition(Condition.KeyExists("abc"));
tran.StringIncrementAsync("i");
tran.Execute();
int i = (int)raw.StringGet("tran:i");
Assert.AreEqual(1, i);
// repeat without key
raw.KeyDelete("tran:abc");
tran = foo.CreateTransaction();
tran.AddCondition(Condition.KeyExists("abc"));
tran.StringIncrementAsync("i");
tran.Execute();
i = (int)raw.StringGet("tran:i");
Assert.AreEqual(1, i);
}
}
}
}
using System;
using NUnit.Framework;
using StackExchange.Redis.KeyspaceIsolation;
namespace StackExchange.Redis.Tests
{
[TestFixture]
public class WithKeyPrefixTests : TestBase
{
[Test]
public void BlankPrefixYieldsSame_Bytes()
{
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix(new byte[0]);
Assert.AreSame(raw, prefixed);
}
}
[Test]
public void BlankPrefixYieldsSame_String()
{
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix("");
Assert.AreSame(raw, prefixed);
}
}
[Test]
public void NullPrefixIsError_Bytes()
{
Assert.Throws<ArgumentNullException>(() => {
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix((byte[])null);
}
});
}
[Test]
public void NullPrefixIsError_String()
{
Assert.Throws<ArgumentNullException>(() => {
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix((string)null);
}
});
}
[Test]
[TestCase("abc")]
[TestCase("")]
[TestCase(null)]
public void NullDatabaseIsError(string prefix)
{
Assert.Throws<ArgumentNullException>(() => {
IDatabase raw = null;
var prefixed = raw.WithKeyPrefix(prefix);
});
}
[Test]
public void BasicSmokeTest()
{
using(var conn = Create())
{
var raw = conn.GetDatabase(1);
var foo = raw.WithKeyPrefix("foo");
var foobar = foo.WithKeyPrefix("bar");
string key = Me();
string s = Guid.NewGuid().ToString(), t = Guid.NewGuid().ToString();
foo.StringSet(key, s);
var val = (string)foo.StringGet(key);
Assert.AreEqual(s, val); // fooBasicSmokeTest
foobar.StringSet(key, t);
val = (string)foobar.StringGet(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("foobar" + key);
Assert.AreEqual(t, val); // foobarBasicSmokeTest
}
}
[Test]
public void ConditionTest()
{
using(var conn = Create())
{
var raw = conn.GetDatabase(2);
var foo = raw.WithKeyPrefix("tran:");
raw.KeyDelete("tran:abc");
raw.KeyDelete("tran:i");
// execute while key exists
raw.StringSet("tran:abc", "def");
var tran = foo.CreateTransaction();
tran.AddCondition(Condition.KeyExists("abc"));
tran.StringIncrementAsync("i");
tran.Execute();
int i = (int)raw.StringGet("tran:i");
Assert.AreEqual(1, i);
// repeat without key
raw.KeyDelete("tran:abc");
tran = foo.CreateTransaction();
tran.AddCondition(Condition.KeyExists("abc"));
tran.StringIncrementAsync("i");
tran.Execute();
i = (int)raw.StringGet("tran:i");
Assert.AreEqual(1, i);
}
}
}
}
......@@ -16,7 +16,6 @@ public sealed class WrapperBaseTests
private Mock<IDatabaseAsync> mock;
private WrapperBase<IDatabaseAsync> wrapper;
//[TestFixtureSetUp]
[OneTimeSetUp]
public void Initialize()
{
......@@ -891,4 +890,4 @@ public void StringSetRangeAsync()
}
}
}
#endif
\ No newline at end of file
#endif
{
"version": "1.0.0-*",
"description": "StackExchange.Redis.Tests",
"authors": [ "jeremymeng" ],
"authors": [ "" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"compile": [
"../../StackExchange.Redis.Tests/**/*.cs"
],
"dependencies": {
"StackExchange.Redis": "1.1.0-*"
"StackExchange.Redis": {
"version": "1.1.0-alpha1",
"target": "project"
}
},
"commands": {
"run": "StackExchange.Redis.Tests"
},
"configurations": {
"Debug": {
"compilationOptions": {
"define": [ "DEBUG", "TRACE", "PLAT_SAFE_CONTINUATIONS" ]
}
},
"Release": {
"compilationOptions": {
"define": [ "TRACE", "PLAT_SAFE_CONTINUATIONS" ]
}
}
},
"compilationOptions": { "define": [ "NUNITLITE" ] },
"frameworks": {
"dnxcore50": {
"compilationOptions": { "define": [ "PLAT_SAFE_CONTINUATIONS", "CORE_CLR" ] },
"dependencies": {
"System.Console": "4.0.0-beta-*",
"System.Linq.Expressions": "4.0.11-beta-23409",
"System.Reflection.Extensions": "4.0.1-beta-23409",
"System.Threading.Tasks.Parallel": "4.0.1-beta-23409",
"Microsoft.CSharp": "4.0.1-beta-23409",
"System.Console": "4.0.0-beta-23516",
"System.Linq.Expressions": "4.0.11-beta-23516",
"System.Reflection.Extensions": "4.0.1-beta-23516",
"System.Threading.Tasks.Parallel": "4.0.1-beta-23516",
"Microsoft.CSharp": "4.0.1-beta-23516",
"nunitlite": "3.0.0"
}
}
......
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{19C00111-1328-4089-8565-94920B5B47F2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis.Tests</RootNamespace>
<AssemblyName>StackExchange.Redis.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;PLAT_SAFE_CONTINUATIONS;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;PLAT_SAFE_CONTINUATIONS;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Log Output\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="BookSleeve">
<HintPath>..\packages\BookSleeve.1.3.41\lib\BookSleeve.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.2.1502.911, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.2.1502.0911\lib\net40\Moq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=3.0.5797.27534, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.0.0\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="AsyncTests.cs" />
<Compile Include="BasicOps.cs" />
<Compile Include="ConnectingFailDetection.cs" />
<Compile Include="ConnectToUnexistingHost.cs" />
<Compile Include="HyperLogLog.cs" />
<Compile Include="Issues\DefaultDatabase.cs" />
<Compile Include="Profiling.cs" />
<Compile Include="Issues\Issue182.cs" />
<Compile Include="WrapperBaseTests.cs" />
<Compile Include="TransactionWrapperTests.cs" />
<Compile Include="Bits.cs" />
<Compile Include="Cluster.cs" />
<Compile Include="Commands.cs" />
<Compile Include="ConnectFailTimeout.cs" />
<Compile Include="ConnectionShutdown.cs" />
<Compile Include="Databases.cs" />
<Compile Include="BatchWrapperTests.cs" />
<Compile Include="DatabaseWrapperTests.cs" />
<Compile Include="DefaultPorts.cs" />
<Compile Include="Expiry.cs" />
<Compile Include="Config.cs" />
<Compile Include="FloatingPoint.cs" />
<Compile Include="Issues\BGSAVEResponse.cs" />
<Compile Include="Issues\Issue25.cs" />
<Compile Include="Issues\Issue6.cs" />
<Compile Include="Issues\SO22786599.cs" />
<Compile Include="Issues\SO23949477.cs" />
<Compile Include="Issues\SO24807536.cs" />
<Compile Include="Issues\SO25567566.cs" />
<Compile Include="Keys.cs" />
<Compile Include="KeysAndValues.cs" />
<Compile Include="Lex.cs" />
<Compile Include="Lists.cs" />
<Compile Include="Locking.cs" />
<Compile Include="Migrate.cs" />
<Compile Include="MultiAdd.cs" />
<Compile Include="MultiMaster.cs" />
<Compile Include="Naming.cs" />
<Compile Include="PreserveOrder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PubSub.cs" />
<Compile Include="PubSubCommand.cs" />
<Compile Include="RealWorld.cs" />
<Compile Include="Scans.cs" />
<Compile Include="Scripting.cs" />
<Compile Include="Secure.cs" />
<Compile Include="Sentinel.cs" />
<Compile Include="Sets.cs" />
<Compile Include="Issues\SO25113323.cs" />
<Compile Include="SSDB.cs" />
<Compile Include="SSL.cs" />
<Compile Include="TaskTests.cs" />
<Compile Include="TestBase.cs" />
<Compile Include="TestInfoReplicationChecks.cs" />
<Compile Include="Transactions.cs" />
<Compile Include="VPNTest.cs" />
<Compile Include="WithKeyPrefixTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StackExchange.Redis_Net46\StackExchange.Redis_Net46.csproj">
<Project>{8c473a6f-b0de-4add-88f8-c41b441e407c}</Project>
<Name>StackExchange.Redis_Net46</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{19C00111-1328-4089-8565-94920B5B47F2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis.Tests</RootNamespace>
<AssemblyName>StackExchange.Redis.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;PLAT_SAFE_CONTINUATIONS;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;PLAT_SAFE_CONTINUATIONS;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Log Output\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="BookSleeve">
<HintPath>..\packages\BookSleeve.1.3.41\lib\BookSleeve.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.2.1502.911, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.2.1502.0911\lib\net40\Moq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=3.0.5797.27534, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
<HintPath>..\packages\NUnit.3.0.0\lib\net45\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis.Tests\**\*.cs"/>
</ItemGroup>
<ItemGroup>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StackExchange.Redis_Net46\StackExchange.Redis_Net46.csproj">
<Project>{8c473a6f-b0de-4add-88f8-c41b441e407c}</Project>
<Name>StackExchange.Redis_Net46</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24709.0
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "StackExchange.Redis", "StackExchange.Redis_dnxcore50\StackExchange.Redis\StackExchange.Redis.xproj", "{86526B5C-1163-4481-A5E2-A303A0BB1535}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "BasicTest_dnxcore50", "BasicTest_dnxcore50\BasicTest_dnxcore50.xproj", "{9D83BABA-A92E-495F-BF63-DEB4F6B09355}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "StackExchange.Redis.Tests", "StackExchange.Redis.Tests_dnxcore50\StackExchange.Redis.Tests\StackExchange.Redis.Tests.xproj", "{A51DCA17-E8F1-44E1-9A37-328FAB14D2CE}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "StackExchange.Redis", "StackExchange.Redis\StackExchange.Redis.xproj", "{EF84877F-59BE-41BE-9013-E765AF0BB72E}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "BasicTest_dnxcore50", "BasicTest_dnxcore50\BasicTest_dnxcore50.xproj", "{9D83BABA-A92E-495F-BF63-DEB4F6B09355}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "StackExchange.Redis.StrongName", "StackExchange.Redis.StrongName\StackExchange.Redis.StrongName.xproj", "{46754D2A-AC16-4686-B113-3DB08ACF4269}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "StackExchange.Redis.Tests", "StackExchange.Redis.Tests\StackExchange.Redis.Tests.xproj", "{3B8BD8F1-8BFC-4D8C-B4DA-25FFAF3D1DBE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
......@@ -15,18 +17,22 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{86526B5C-1163-4481-A5E2-A303A0BB1535}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{86526B5C-1163-4481-A5E2-A303A0BB1535}.Debug|Any CPU.Build.0 = Debug|Any CPU
{86526B5C-1163-4481-A5E2-A303A0BB1535}.Release|Any CPU.ActiveCfg = Release|Any CPU
{86526B5C-1163-4481-A5E2-A303A0BB1535}.Release|Any CPU.Build.0 = Release|Any CPU
{A51DCA17-E8F1-44E1-9A37-328FAB14D2CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A51DCA17-E8F1-44E1-9A37-328FAB14D2CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A51DCA17-E8F1-44E1-9A37-328FAB14D2CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A51DCA17-E8F1-44E1-9A37-328FAB14D2CE}.Release|Any CPU.Build.0 = Release|Any CPU
{9D83BABA-A92E-495F-BF63-DEB4F6B09355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D83BABA-A92E-495F-BF63-DEB4F6B09355}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D83BABA-A92E-495F-BF63-DEB4F6B09355}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D83BABA-A92E-495F-BF63-DEB4F6B09355}.Release|Any CPU.Build.0 = Release|Any CPU
{EF84877F-59BE-41BE-9013-E765AF0BB72E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF84877F-59BE-41BE-9013-E765AF0BB72E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF84877F-59BE-41BE-9013-E765AF0BB72E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF84877F-59BE-41BE-9013-E765AF0BB72E}.Release|Any CPU.Build.0 = Release|Any CPU
{46754D2A-AC16-4686-B113-3DB08ACF4269}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46754D2A-AC16-4686-B113-3DB08ACF4269}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46754D2A-AC16-4686-B113-3DB08ACF4269}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46754D2A-AC16-4686-B113-3DB08ACF4269}.Release|Any CPU.Build.0 = Release|Any CPU
{3B8BD8F1-8BFC-4D8C-B4DA-25FFAF3D1DBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B8BD8F1-8BFC-4D8C-B4DA-25FFAF3D1DBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B8BD8F1-8BFC-4D8C-B4DA-25FFAF3D1DBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B8BD8F1-8BFC-4D8C-B4DA-25FFAF3D1DBE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis.md", "StackExchange.Redis\StackExchange.Redis.md.csproj", "{8EA21FC8-9CF7-438B-94F2-42E3810C3641}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8EA21FC8-9CF7-438B-94F2-42E3810C3641}.Debug|x86.ActiveCfg = Debug|x86
{8EA21FC8-9CF7-438B-94F2-42E3810C3641}.Debug|x86.Build.0 = Debug|x86
{8EA21FC8-9CF7-438B-94F2-42E3810C3641}.Release|x86.ActiveCfg = Release|x86
{8EA21FC8-9CF7-438B-94F2-42E3810C3641}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = StackExchange.Redis.md\StackExchange.Redis.md.csproj
EndGlobalSection
EndGlobal
......@@ -6,7 +6,7 @@
<authors>Stack Exchange inc., marc.gravell</authors>
<owners>Stack Exchange inc., marc.gravell</owners>
<summary>Redis client library</summary>
<description>High performance Redis client, incorporating both synchronous and asynchronous usage; the notional successor to BookSleeve. If you require a strong-named version, try StackExchange.Redis.StrongName</description>
<description></description>
<tags>Async Redis NoSQL Client Distributed Cache PubSub Messaging</tags>
<language>en-US</language>
<projectUrl>https://github.com/StackExchange/StackExchange.Redis</projectUrl>
......

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24606.1
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis", "StackExchange.Redis\StackExchange.Redis.csproj", "{7CEC07F2-8C03-4C42-B048-738B215824C1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis.Tests", "StackExchange.Redis.Tests\StackExchange.Redis.Tests.csproj", "{19C00111-1328-4089-8565-94920B5B47F2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{D3090DF1-8760-4FE2-A595-4C8AC12854ED}"
ProjectSection(SolutionItems) = preProject
.nuget\packages.config = .nuget\packages.config
......@@ -52,14 +48,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MigratedBookSleeveTestSuite
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net40", "StackExchange.Redis_Net40\StackExchange.Redis_Net40.csproj", "{36CAC6B6-2B88-447F-AA35-D4DAA5E4F2C7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis.StrongName", "StackExchange.Redis\StackExchange.Redis.StrongName.csproj", "{EBF46088-E318-4D32-9EFB-01EF130A4554}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net40.StrongName", "StackExchange.Redis_Net40\StackExchange.Redis_Net40.StrongName.csproj", "{75CED009-AAC6-4AC1-9C38-A0530619062D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net46", "StackExchange.Redis_Net46\StackExchange.Redis_Net46.csproj", "{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net46.StrongName", "StackExchange.Redis_Net46\StackExchange.Redis_Net46.StrongName.csproj", "{8CE5D027-E332-42DD-BA54-16310DCD529C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net45", "StackExchange.Redis_Net45\StackExchange.Redis_Net45.csproj", "{7CEC07F2-8C03-4C42-B048-738B215824C1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net45.StrongName", "StackExchange.Redis_Net45\StackExchange.Redis_Net45.StrongName.csproj", "{EBF46088-E318-4D32-9EFB-01EF130A4554}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis.Tests_Net46", "StackExchange.Redis.Tests_Net46\StackExchange.Redis.Tests_Net46.csproj", "{19C00111-1328-4089-8565-94920B5B47F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -69,26 +69,6 @@ Global
Verbose|Any CPU = Verbose|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Log Output|Any CPU.ActiveCfg = Log Output|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Log Output|Any CPU.Build.0 = Log Output|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Mono|Any CPU.ActiveCfg = Mono|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Mono|Any CPU.Build.0 = Mono|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Release|Any CPU.Build.0 = Release|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Verbose|Any CPU.ActiveCfg = Verbose|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Verbose|Any CPU.Build.0 = Verbose|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Log Output|Any CPU.ActiveCfg = Log Output|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Log Output|Any CPU.Build.0 = Log Output|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Mono|Any CPU.ActiveCfg = Mono|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Mono|Any CPU.Build.0 = Mono|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Release|Any CPU.Build.0 = Release|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Verbose|Any CPU.ActiveCfg = Verbose|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Verbose|Any CPU.Build.0 = Verbose|Any CPU
{6756F911-BD09-4226-B597-67871DEB8ED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6756F911-BD09-4226-B597-67871DEB8ED5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6756F911-BD09-4226-B597-67871DEB8ED5}.Log Output|Any CPU.ActiveCfg = Log Output|Any CPU
......@@ -139,16 +119,6 @@ Global
{36CAC6B6-2B88-447F-AA35-D4DAA5E4F2C7}.Release|Any CPU.Build.0 = Release|Any CPU
{36CAC6B6-2B88-447F-AA35-D4DAA5E4F2C7}.Verbose|Any CPU.ActiveCfg = Release|Any CPU
{36CAC6B6-2B88-447F-AA35-D4DAA5E4F2C7}.Verbose|Any CPU.Build.0 = Release|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Log Output|Any CPU.ActiveCfg = Log Output|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Log Output|Any CPU.Build.0 = Log Output|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Mono|Any CPU.ActiveCfg = Mono|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Mono|Any CPU.Build.0 = Mono|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Release|Any CPU.Build.0 = Release|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Verbose|Any CPU.ActiveCfg = Verbose|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Verbose|Any CPU.Build.0 = Verbose|Any CPU
{75CED009-AAC6-4AC1-9C38-A0530619062D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75CED009-AAC6-4AC1-9C38-A0530619062D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75CED009-AAC6-4AC1-9C38-A0530619062D}.Log Output|Any CPU.ActiveCfg = Release|Any CPU
......@@ -179,6 +149,36 @@ Global
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Release|Any CPU.Build.0 = Release|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Verbose|Any CPU.ActiveCfg = Mono|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Verbose|Any CPU.Build.0 = Mono|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Log Output|Any CPU.ActiveCfg = Log Output|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Log Output|Any CPU.Build.0 = Log Output|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Mono|Any CPU.ActiveCfg = Mono|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Mono|Any CPU.Build.0 = Mono|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Release|Any CPU.Build.0 = Release|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Verbose|Any CPU.ActiveCfg = Verbose|Any CPU
{7CEC07F2-8C03-4C42-B048-738B215824C1}.Verbose|Any CPU.Build.0 = Verbose|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Log Output|Any CPU.ActiveCfg = Log Output|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Log Output|Any CPU.Build.0 = Log Output|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Mono|Any CPU.ActiveCfg = Mono|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Mono|Any CPU.Build.0 = Mono|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Release|Any CPU.Build.0 = Release|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Verbose|Any CPU.ActiveCfg = Verbose|Any CPU
{EBF46088-E318-4D32-9EFB-01EF130A4554}.Verbose|Any CPU.Build.0 = Verbose|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Log Output|Any CPU.ActiveCfg = Log Output|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Log Output|Any CPU.Build.0 = Log Output|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Mono|Any CPU.ActiveCfg = Mono|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Mono|Any CPU.Build.0 = Mono|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Release|Any CPU.Build.0 = Release|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Verbose|Any CPU.ActiveCfg = Verbose|Any CPU
{19C00111-1328-4089-8565-94920B5B47F2}.Verbose|Any CPU.Build.0 = Verbose|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8EA21FC8-9CF7-438B-94F2-42E3810C3641}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>StackExchange.Redis.md</RootNamespace>
<AssemblyName>StackExchange.Redis.md</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;MONO</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<ConsolePause>false</ConsolePause>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<ConsolePause>false</ConsolePause>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>MONO</DefineConstants>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StackExchange\Redis\Aggregate.cs" />
<Compile Include="StackExchange\Redis\Bitwise.cs" />
<Compile Include="StackExchange\Redis\ClientFlags.cs" />
<Compile Include="StackExchange\Redis\ClientInfo.cs" />
<Compile Include="StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="StackExchange\Redis\CommandFlags.cs" />
<Compile Include="StackExchange\Redis\CommandMap.cs" />
<Compile Include="StackExchange\Redis\CommandTrace.cs" />
<Compile Include="StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="StackExchange\Redis\CompletionManager.cs" />
<Compile Include="StackExchange\Redis\Condition.cs" />
<Compile Include="StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" />
<Compile Include="StackExchange\Redis\ConnectionType.cs" />
<Compile Include="StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="StackExchange\Redis\Exclude.cs" />
<Compile Include="StackExchange\Redis\ExportOptions.cs" />
<Compile Include="StackExchange\Redis\Format.cs" />
<Compile Include="StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="StackExchange\Redis\IBatch.cs" />
<Compile Include="StackExchange\Redis\ICompletable.cs" />
<Compile Include="StackExchange\Redis\IDatabase.cs" />
<Compile Include="StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\IRedis.cs" />
<Compile Include="StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="StackExchange\Redis\IServer.cs" />
<Compile Include="StackExchange\Redis\ISubscriber.cs" />
<Compile Include="StackExchange\Redis\ITransaction.cs" />
<Compile Include="StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="StackExchange\Redis\Message.cs" />
<Compile Include="StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="StackExchange\Redis\MessageQueue.cs" />
<Compile Include="StackExchange\Redis\Order.cs" />
<Compile Include="StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="StackExchange\Redis\RawResult.cs" />
<Compile Include="StackExchange\Redis\RedisBase.cs" />
<Compile Include="StackExchange\Redis\RedisBatch.cs" />
<Compile Include="StackExchange\Redis\RedisChannel.cs" />
<Compile Include="StackExchange\Redis\RedisCommand.cs" />
<Compile Include="StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="StackExchange\Redis\RedisKey.cs" />
<Compile Include="StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="StackExchange\Redis\RedisResult.cs" />
<Compile Include="StackExchange\Redis\RedisServer.cs" />
<Compile Include="StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="StackExchange\Redis\RedisType.cs" />
<Compile Include="StackExchange\Redis\RedisValue.cs" />
<Compile Include="StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="StackExchange\Redis\ResultBox.cs" />
<Compile Include="StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="StackExchange\Redis\ResultType.cs" />
<Compile Include="StackExchange\Redis\SaveType.cs" />
<Compile Include="StackExchange\Redis\ServerCounters.cs" />
<Compile Include="StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="StackExchange\Redis\ServerType.cs" />
<Compile Include="StackExchange\Redis\SetOperation.cs" />
<Compile Include="StackExchange\Redis\ShutdownMode.cs" />
<Compile Include="StackExchange\Redis\SocketManager.cs" />
<Compile Include="StackExchange\Redis\SortType.cs" />
<Compile Include="StackExchange\Redis\StringSplits.cs" />
<Compile Include="StackExchange\Redis\TaskSource.cs" />
<Compile Include="StackExchange\Redis\When.cs" />
<Compile Include="StackExchange\Redis\HashEntry.cs" />
<Compile Include="StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="StackExchange\Redis\SocketManager.NoPoll.cs" />
<Compile Include="StackExchange\Redis\SocketManager.Poll.cs" />
<Compile Include="StackExchange\Redis\SortedSetEntry.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.IO.Compression" />
</ItemGroup>
<ItemGroup>
<Folder Include="StackExchange\Redis\" />
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>86526b5c-1163-4481-a5e2-a303a0bb1535</ProjectGuid>
<RootNamespace>StackExchange.Redis</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>ef84877f-59be-41be-9013-e765af0bb72e</ProjectGuid>
<RootNamespace>StackExchange.Redis</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
\ No newline at end of file
......@@ -172,6 +172,7 @@ public sealed class ClusterConfiguration
private readonly ServerSelectionStrategy serverSelectionStrategy;
internal ClusterConfiguration(ServerSelectionStrategy serverSelectionStrategy, string nodes, EndPoint origin)
{
// Beware: Any exception thrown here will wreak silent havoc like inability to connect to cluster nodes or non returning calls
this.serverSelectionStrategy = serverSelectionStrategy;
this.origin = origin;
using (var reader = new StringReader(nodes))
......@@ -180,9 +181,36 @@ internal ClusterConfiguration(ServerSelectionStrategy serverSelectionStrategy, s
while ((line = reader.ReadLine()) != null)
{
if (string.IsNullOrWhiteSpace(line)) continue;
var node = new ClusterNode(this, line, origin);
nodeLookup.Add(node.EndPoint, node);
// Be resilient to ":0 {master,slave},fail,noaddr" nodes
if (node.IsNoAddr)
continue;
if (nodeLookup.ContainsKey(node.EndPoint))
{
// Deal with conflicting node entries for the same endpoint
// This can happen in dynamic environments when a node goes down and a new one is created
// to replace it.
if (!node.IsConnected)
{
// The node we're trying to add is probably about to become stale. Ignore it.
continue;
}
else if (!nodeLookup[node.EndPoint].IsConnected)
{
// The node we registered previously is probably stale. Replace it with a known good node.
nodeLookup[node.EndPoint] = node;
}
else
{
// We have conflicting connected nodes. There's nothing much we can do other than
// wait for the cluster state to converge and refresh on the next pass.
// The same is true if we have multiple disconnected nodes.
}
}
else
{
nodeLookup.Add(node.EndPoint, node);
}
}
}
}
......@@ -262,6 +290,10 @@ public sealed class ClusterNode : IEquatable<ClusterNode>, IComparable<ClusterN
private readonly bool isSlave;
private readonly bool isNoAddr;
private readonly bool isConnected;
private readonly string nodeId, parentNodeId, raw;
private readonly IList<SlotRange> slots;
......@@ -275,22 +307,18 @@ public sealed class ClusterNode : IEquatable<ClusterNode>, IComparable<ClusterN
internal ClusterNode() { }
internal ClusterNode(ClusterConfiguration configuration, string raw, EndPoint origin)
{
// http://redis.io/commands/cluster-nodes
this.configuration = configuration;
this.raw = raw;
var parts = raw.Split(StringSplits.Space);
var flags = parts[2].Split(StringSplits.Comma);
if (flags.Contains("myself"))
{
endpoint = origin;
}
else
{
endpoint = Format.TryParseEndPoint(parts[1]);
}
endpoint = Format.TryParseEndPoint(parts[1]);
nodeId = parts[0];
isSlave = flags.Contains("slave");
isNoAddr = flags.Contains("noaddr");
parentNodeId = string.IsNullOrWhiteSpace(parts[3]) ? null : parts[3];
List<SlotRange> slots = null;
......@@ -305,6 +333,7 @@ internal ClusterNode(ClusterConfiguration configuration, string raw, EndPoint or
}
}
this.slots = slots == null ? NoSlots : slots.AsReadOnly();
this.isConnected = parts[7] == "connected"; // Can be "connected" or "disconnected"
}
/// <summary>
/// Gets all child nodes of the current node
......@@ -339,6 +368,16 @@ public IList<ClusterNode> Children
/// </summary>
public bool IsSlave { get { return isSlave; } }
/// <summary>
/// Gets whether this node is flagged as noaddr
/// </summary>
public bool IsNoAddr { get { return isNoAddr; } }
/// <summary>
/// Gets the node's connection status
/// </summary>
public bool IsConnected { get { return isConnected; } }
/// <summary>
/// Gets the unique node-id of the current node
/// </summary>
......
using System;
using System.Collections.Generic;
using System.Text;
namespace StackExchange.Redis
{
/// <summary>
/// Represents the commands mapped on a particular configuration
/// </summary>
public sealed class CommandMap
{
private static readonly CommandMap
@default = CreateImpl(null, null),
twemproxy = CreateImpl(null, exclusions: new HashSet<RedisCommand>
{
// see https://github.com/twitter/twemproxy/blob/master/notes/redis.md
RedisCommand.KEYS, RedisCommand.MIGRATE, RedisCommand.MOVE, RedisCommand.OBJECT, RedisCommand.RANDOMKEY,
RedisCommand.RENAME, RedisCommand.RENAMENX, RedisCommand.SORT, RedisCommand.SCAN,
RedisCommand.BITOP, RedisCommand.MSET, RedisCommand.MSETNX,
RedisCommand.HSCAN,
RedisCommand.BLPOP, RedisCommand.BRPOP, RedisCommand.BRPOPLPUSH, // yeah, me neither!
RedisCommand.SSCAN,
RedisCommand.ZSCAN,
RedisCommand.PSUBSCRIBE, RedisCommand.PUBLISH, RedisCommand.PUNSUBSCRIBE, RedisCommand.SUBSCRIBE, RedisCommand.UNSUBSCRIBE,
RedisCommand.DISCARD, RedisCommand.EXEC, RedisCommand.MULTI, RedisCommand.UNWATCH, RedisCommand.WATCH,
RedisCommand.SCRIPT,
RedisCommand.AUTH, RedisCommand.ECHO, RedisCommand.PING, RedisCommand.QUIT, RedisCommand.SELECT,
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.SHUTDOWN, RedisCommand.SLAVEOF, RedisCommand.SLOWLOG, RedisCommand.SYNC, RedisCommand.TIME
}), ssdb = Create(new HashSet<string> {
// see http://www.ideawu.com/ssdb/docs/redis-to-ssdb.html
"ping",
"get", "set", "del", "incr", "incrby", "mget", "mset", "keys", "getset", "setnx",
"hget", "hset", "hdel", "hincrby", "hkeys", "hvals", "hmget", "hmset", "hlen",
"zscore", "zadd", "zrem", "zrange", "zrangebyscore", "zincrby", "zdecrby", "zcard",
"llen", "lpush", "rpush", "lpop", "rpop", "lrange", "lindex"
}, true),
sentinel = Create(new HashSet<string> {
// see http://redis.io/topics/sentinel
"ping", "info", "sentinel", "subscribe", "psubscribe", "unsubscribe", "punsubscribe" }, true);
private readonly byte[][] map;
internal CommandMap(byte[][] map)
{
this.map = map;
}
/// <summary>
/// The default commands specified by redis
/// </summary>
public static CommandMap Default { get { return @default; } }
/// <summary>
/// The commands available to <a href="twemproxy">https://github.com/twitter/twemproxy</a>
/// </summary>
/// <remarks>https://github.com/twitter/twemproxy/blob/master/notes/redis.md</remarks>
public static CommandMap Twemproxy { get { return twemproxy; } }
/// <summary>
/// The commands available to <a href="ssdb">http://www.ideawu.com/ssdb/</a>
/// </summary>
/// <remarks>http://www.ideawu.com/ssdb/docs/redis-to-ssdb.html</remarks>
public static CommandMap SSDB { get { return ssdb; } }
/// <summary>
/// The commands available to <a href="Sentinel">http://redis.io/topics/sentinel</a>
/// </summary>
/// <remarks>http://redis.io/topics/sentinel</remarks>
public static CommandMap Sentinel { get { return sentinel; } }
/// <summary>
/// Create a new CommandMap, customizing some commands
/// </summary>
public static CommandMap Create(Dictionary<string, string> overrides)
{
if (overrides == null || overrides.Count == 0) return Default;
if (ReferenceEquals(overrides.Comparer, StringComparer.OrdinalIgnoreCase))
{
// that's ok; we're happy with ordinal/invariant case-insensitive
// (but not culture-specific insensitive; completely untested)
}
else
{
// need case insensitive
overrides = new Dictionary<string, string>(overrides, StringComparer.OrdinalIgnoreCase);
}
return CreateImpl(overrides, null);
}
/// <summary>
/// Creates a CommandMap by specifying which commands are available or unavailable
/// </summary>
public static CommandMap Create(HashSet<string> commands, bool available = true)
{
if (available)
{
var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// nix everything
foreach (RedisCommand command in Enum.GetValues(typeof(RedisCommand)))
{
dictionary[command.ToString()] = null;
}
if (commands != null)
{
// then include (by removal) the things that are available
foreach (string command in commands)
{
dictionary.Remove(command);
}
}
return CreateImpl(dictionary, null);
}
else
{
HashSet<RedisCommand> exclusions = null;
if (commands != null)
{
// nix the things that are specified
foreach (var command in commands)
{
RedisCommand parsed;
if (Enum.TryParse(command, true, out parsed))
{
(exclusions ?? (exclusions = new HashSet<RedisCommand>())).Add(parsed);
}
}
}
if (exclusions == null || exclusions.Count == 0) return Default;
return CreateImpl(null, exclusions);
}
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
var sb = new StringBuilder();
AppendDeltas(sb);
return sb.ToString();
}
internal void AppendDeltas(StringBuilder sb)
{
for (int i = 0; i < map.Length; i++)
{
var key = ((RedisCommand)i).ToString();
var value = map[i] == null ? "" : Encoding.UTF8.GetString(map[i]);
if (key != value)
{
if (sb.Length != 0) sb.Append(',');
sb.Append('$').Append(key).Append('=').Append(value);
}
}
}
internal void AssertAvailable(RedisCommand command)
{
if (map[(int)command] == null) throw ExceptionFactory.CommandDisabled(false, command, null, null);
}
internal byte[] GetBytes(RedisCommand command)
{
return map[(int)command];
}
internal bool IsAvailable(RedisCommand command)
{
return map[(int)command] != null;
}
private static CommandMap CreateImpl(Dictionary<string, string> caseInsensitiveOverrides, HashSet<RedisCommand> exclusions)
{
var commands = (RedisCommand[])Enum.GetValues(typeof(RedisCommand));
byte[][] map = new byte[commands.Length][];
bool haveDelta = false;
for (int i = 0; i < commands.Length; i++)
{
int idx = (int)commands[i];
string name = commands[i].ToString(), value = name;
if (exclusions != null && exclusions.Contains(commands[i]))
{
map[idx] = null;
}
else
{
if (caseInsensitiveOverrides != null)
{
string tmp;
if (caseInsensitiveOverrides.TryGetValue(name, out tmp))
{
value = tmp;
}
}
if (value != name) haveDelta = true;
haveDelta = true;
byte[] val = string.IsNullOrWhiteSpace(value) ? null : Encoding.UTF8.GetBytes(value);
map[idx] = val;
}
}
if (!haveDelta && @default != null) return @default;
return new CommandMap(map);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace StackExchange.Redis
{
/// <summary>
/// Represents the commands mapped on a particular configuration
/// </summary>
public sealed class CommandMap
{
private static readonly CommandMap
@default = CreateImpl(null, null),
twemproxy = CreateImpl(null, exclusions: new HashSet<RedisCommand>
{
// see https://github.com/twitter/twemproxy/blob/master/notes/redis.md
RedisCommand.KEYS, RedisCommand.MIGRATE, RedisCommand.MOVE, RedisCommand.OBJECT, RedisCommand.RANDOMKEY,
RedisCommand.RENAME, RedisCommand.RENAMENX, RedisCommand.SORT, RedisCommand.SCAN,
RedisCommand.BITOP, RedisCommand.MSET, RedisCommand.MSETNX,
RedisCommand.HSCAN,
RedisCommand.BLPOP, RedisCommand.BRPOP, RedisCommand.BRPOPLPUSH, // yeah, me neither!
RedisCommand.SSCAN,
RedisCommand.ZSCAN,
RedisCommand.PSUBSCRIBE, RedisCommand.PUBLISH, RedisCommand.PUNSUBSCRIBE, RedisCommand.SUBSCRIBE, RedisCommand.UNSUBSCRIBE,
RedisCommand.DISCARD, RedisCommand.EXEC, RedisCommand.MULTI, RedisCommand.UNWATCH, RedisCommand.WATCH,
RedisCommand.SCRIPT,
RedisCommand.ECHO, RedisCommand.PING, RedisCommand.QUIT, RedisCommand.SELECT,
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.SHUTDOWN, RedisCommand.SLAVEOF, RedisCommand.SLOWLOG, RedisCommand.SYNC, RedisCommand.TIME
}), ssdb = Create(new HashSet<string> {
// see http://www.ideawu.com/ssdb/docs/redis-to-ssdb.html
"ping",
"get", "set", "del", "incr", "incrby", "mget", "mset", "keys", "getset", "setnx",
"hget", "hset", "hdel", "hincrby", "hkeys", "hvals", "hmget", "hmset", "hlen",
"zscore", "zadd", "zrem", "zrange", "zrangebyscore", "zincrby", "zdecrby", "zcard",
"llen", "lpush", "rpush", "lpop", "rpop", "lrange", "lindex"
}, true),
sentinel = Create(new HashSet<string> {
// see http://redis.io/topics/sentinel
"ping", "info", "sentinel", "subscribe", "psubscribe", "unsubscribe", "punsubscribe" }, true);
private readonly byte[][] map;
internal CommandMap(byte[][] map)
{
this.map = map;
}
/// <summary>
/// The default commands specified by redis
/// </summary>
public static CommandMap Default { get { return @default; } }
/// <summary>
/// The commands available to <a href="twemproxy">https://github.com/twitter/twemproxy</a>
/// </summary>
/// <remarks>https://github.com/twitter/twemproxy/blob/master/notes/redis.md</remarks>
public static CommandMap Twemproxy { get { return twemproxy; } }
/// <summary>
/// The commands available to <a href="ssdb">http://www.ideawu.com/ssdb/</a>
/// </summary>
/// <remarks>http://www.ideawu.com/ssdb/docs/redis-to-ssdb.html</remarks>
public static CommandMap SSDB { get { return ssdb; } }
/// <summary>
/// The commands available to <a href="Sentinel">http://redis.io/topics/sentinel</a>
/// </summary>
/// <remarks>http://redis.io/topics/sentinel</remarks>
public static CommandMap Sentinel { get { return sentinel; } }
/// <summary>
/// Create a new CommandMap, customizing some commands
/// </summary>
public static CommandMap Create(Dictionary<string, string> overrides)
{
if (overrides == null || overrides.Count == 0) return Default;
if (ReferenceEquals(overrides.Comparer, StringComparer.OrdinalIgnoreCase))
{
// that's ok; we're happy with ordinal/invariant case-insensitive
// (but not culture-specific insensitive; completely untested)
}
else
{
// need case insensitive
overrides = new Dictionary<string, string>(overrides, StringComparer.OrdinalIgnoreCase);
}
return CreateImpl(overrides, null);
}
/// <summary>
/// Creates a CommandMap by specifying which commands are available or unavailable
/// </summary>
public static CommandMap Create(HashSet<string> commands, bool available = true)
{
if (available)
{
var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// nix everything
foreach (RedisCommand command in Enum.GetValues(typeof(RedisCommand)))
{
dictionary[command.ToString()] = null;
}
if (commands != null)
{
// then include (by removal) the things that are available
foreach (string command in commands)
{
dictionary.Remove(command);
}
}
return CreateImpl(dictionary, null);
}
else
{
HashSet<RedisCommand> exclusions = null;
if (commands != null)
{
// nix the things that are specified
foreach (var command in commands)
{
RedisCommand parsed;
if (Enum.TryParse(command, true, out parsed))
{
(exclusions ?? (exclusions = new HashSet<RedisCommand>())).Add(parsed);
}
}
}
if (exclusions == null || exclusions.Count == 0) return Default;
return CreateImpl(null, exclusions);
}
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
var sb = new StringBuilder();
AppendDeltas(sb);
return sb.ToString();
}
internal void AppendDeltas(StringBuilder sb)
{
for (int i = 0; i < map.Length; i++)
{
var key = ((RedisCommand)i).ToString();
var value = map[i] == null ? "" : Encoding.UTF8.GetString(map[i]);
if (key != value)
{
if (sb.Length != 0) sb.Append(',');
sb.Append('$').Append(key).Append('=').Append(value);
}
}
}
internal void AssertAvailable(RedisCommand command)
{
if (map[(int)command] == null) throw ExceptionFactory.CommandDisabled(false, command, null, null);
}
internal byte[] GetBytes(RedisCommand command)
{
return map[(int)command];
}
internal bool IsAvailable(RedisCommand command)
{
return map[(int)command] != null;
}
private static CommandMap CreateImpl(Dictionary<string, string> caseInsensitiveOverrides, HashSet<RedisCommand> exclusions)
{
var commands = (RedisCommand[])Enum.GetValues(typeof(RedisCommand));
byte[][] map = new byte[commands.Length][];
bool haveDelta = false;
for (int i = 0; i < commands.Length; i++)
{
int idx = (int)commands[i];
string name = commands[i].ToString(), value = name;
if (exclusions != null && exclusions.Contains(commands[i]))
{
map[idx] = null;
}
else
{
if (caseInsensitiveOverrides != null)
{
string tmp;
if (caseInsensitiveOverrides.TryGetValue(name, out tmp))
{
value = tmp;
}
}
if (value != name) haveDelta = true;
haveDelta = true;
byte[] val = string.IsNullOrWhiteSpace(value) ? null : Encoding.UTF8.GetBytes(value);
map[idx] = val;
}
}
if (!haveDelta && @default != null) return @default;
return new CommandMap(map);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StackExchange.Redis
{
/// <summary>
/// Helper for Array.ConvertAll() as it's missing on .Net Core.
/// </summary>
public static class ConvertHelper
{
/// <summary>
/// Converts array of one type to an array of another type.
/// </summary>
/// <typeparam name="TInput">Input type</typeparam>
/// <typeparam name="TOutput">Output type</typeparam>
/// <param name="source">source</param>
/// <param name="selector">selector</param>
/// <returns></returns>
public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] source, Func<TInput, TOutput> selector)
{
#if CORE_CLR
TOutput[] arr = new TOutput[source.Length];
for(int i = 0 ; i < arr.Length ; i++)
arr[i] = selector(source[i]);
return arr;
#else
return Array.ConvertAll(source, item => selector(item));
#endif
}
}
}
......@@ -10,7 +10,7 @@ internal static class VolatileWrapper
{
public static int Read(ref int location)
{
#if !DNXCORE50
#if !CORE_CLR
return System.Threading.Thread.VolatileRead(ref location);
#else
return System.Threading.Volatile.Read(ref location);
......@@ -19,7 +19,7 @@ public static int Read(ref int location)
public static void Write(ref int address, int value)
{
#if !DNXCORE50
#if !CORE_CLR
System.Threading.Thread.VolatileWrite(ref address, value);
#else
System.Threading.Volatile.Write(ref address, value);
......
......@@ -30,7 +30,7 @@ public enum Proxy
/// The options relevant to a set of redis connections
/// </summary>
public sealed class ConfigurationOptions
#if !DNXCORE50
#if !CORE_CLR
: ICloneable
#endif
{
......@@ -143,7 +143,7 @@ public static string TryNormalize(string value)
/// Indicates whether the connection should be encrypted
/// </summary>
[Obsolete("Please use .Ssl instead of .UseSsl"),
#if !DNXCORE50
#if !CORE_CLR
Browsable(false),
#endif
EditorBrowsable(EditorBrowsableState.Never)]
......@@ -470,7 +470,7 @@ static void Append(StringBuilder sb, string prefix, object value)
}
}
#if !DNXCORE50
#if !CORE_CLR
static bool IsOption(string option, string prefix)
{
return option.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase);
......@@ -492,7 +492,7 @@ void Clear()
SocketManager = null;
}
#if !DNXCORE50
#if !CORE_CLR
object ICloneable.Clone() { return Clone(); }
#endif
......
......@@ -482,7 +482,7 @@ public EndPoint[] GetEndPoints(bool configuredOnly = false)
{
if (configuredOnly) return configuration.EndPoints.ToArray();
return serverSnapshot.Select(x => x.EndPoint).ToArray();
return ConvertHelper.ConvertAll(serverSnapshot, x => x.EndPoint);
}
private readonly int timeoutMilliseconds;
......@@ -561,7 +561,7 @@ private static bool WaitAllIgnoreErrors(Task[] tasks, int timeout)
return false;
}
#if !DNXCORE50
#if !CORE_CLR
private void LogLockedWithThreadPoolStats(TextWriter log, string message, out int busyWorkerCount)
{
busyWorkerCount = 0;
......@@ -603,7 +603,7 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
}
var watch = Stopwatch.StartNew();
#if !DNXCORE50
#if !CORE_CLR
int busyWorkerCount;
LogLockedWithThreadPoolStats(log, "Awaiting task completion", out busyWorkerCount);
#endif
......@@ -613,7 +613,7 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
var remaining = timeoutMilliseconds - checked((int)watch.ElapsedMilliseconds);
if (remaining <= 0)
{
#if !DNXCORE50
#if !CORE_CLR
LogLockedWithThreadPoolStats(log, "Timeout before awaiting for tasks", out busyWorkerCount);
#endif
return false;
......@@ -627,7 +627,7 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
var any = Task.WhenAny(allTasks, Task.Delay(remaining)).ObserveErrors();
#endif
bool all = await any.ForAwait() == allTasks;
#if !DNXCORE50
#if !CORE_CLR
LogLockedWithThreadPoolStats(log, all ? "All tasks completed cleanly" : "Not all tasks completed cleanly", out busyWorkerCount);
#endif
return all;
......@@ -645,7 +645,7 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
var remaining = timeoutMilliseconds - checked((int)watch.ElapsedMilliseconds);
if (remaining <= 0)
{
#if !DNXCORE50
#if !CORE_CLR
LogLockedWithThreadPoolStats(log, "Timeout awaiting tasks", out busyWorkerCount);
#endif
return false;
......@@ -663,7 +663,7 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
{ }
}
}
#if !DNXCORE50
#if !CORE_CLR
LogLockedWithThreadPoolStats(log, "Finished awaiting tasks", out busyWorkerCount);
#endif
return false;
......@@ -1216,114 +1216,155 @@ internal async Task<bool> ReconfigureAsync(bool first, bool reconfigureAll, Text
}
const CommandFlags flags = CommandFlags.NoRedirect | CommandFlags.HighPriority;
var available = new Task<bool>[endpoints.Count];
var servers = new ServerEndPoint[available.Length];
List<ServerEndPoint> masters = new List<ServerEndPoint>(endpoints.Count);
bool useTieBreakers = !string.IsNullOrWhiteSpace(configuration.TieBreaker);
var tieBreakers = useTieBreakers ? new Task<string>[endpoints.Count] : null;
RedisKey tieBreakerKey = useTieBreakers ? (RedisKey)configuration.TieBreaker : default(RedisKey);
for (int i = 0; i < available.Length; i++)
ServerEndPoint[] servers = null;
Task<string>[] tieBreakers = null;
bool encounteredConnectedClusterServer = false;
Stopwatch watch = null;
int iterCount = first ? 2 : 1;
// this is fix for https://github.com/StackExchange/StackExchange.Redis/issues/300
// auto discoverability of cluster nodes is made synchronous.
// we try to connect to endpoints specified inside the user provided configuration
// and when we encounter one such endpoint to which we are able to successfully connect,
// we get the list of cluster nodes from this endpoint and try to proactively connect
// to these nodes instead of relying on auto configure
for (int iter = 0; iter < iterCount; ++iter)
{
Trace("Testing: " + Format.ToString(endpoints[i]));
var server = GetServerEndPoint(endpoints[i]);
//server.ReportNextFailure();
servers[i] = server;
if (reconfigureAll && server.IsConnected)
if (endpoints == null) break;
var available = new Task<bool>[endpoints.Count];
tieBreakers = useTieBreakers ? new Task<string>[endpoints.Count] : null;
servers = new ServerEndPoint[available.Length];
RedisKey tieBreakerKey = useTieBreakers ? (RedisKey)configuration.TieBreaker : default(RedisKey);
for (int i = 0; i < available.Length; i++)
{
LogLocked(log, "Refreshing {0}...", Format.ToString(server.EndPoint));
// note that these will be processed synchronously *BEFORE* the tracer is processed,
// so we know that the configuration will be up to date if we see the tracer
server.AutoConfigure(null);
}
available[i] = server.SendTracer(log);
if (useTieBreakers)
{
LogLocked(log, "Requesting tie-break from {0} > {1}...", Format.ToString(server.EndPoint), configuration.TieBreaker);
Message msg = Message.Create(0, flags, RedisCommand.GET, tieBreakerKey);
msg.SetInternalCall();
msg = LoggingMessage.Create(log, msg);
tieBreakers[i] = server.QueueDirectAsync(msg, ResultProcessor.String);
Trace("Testing: " + Format.ToString(endpoints[i]));
var server = GetServerEndPoint(endpoints[i]);
//server.ReportNextFailure();
servers[i] = server;
if (reconfigureAll && server.IsConnected)
{
LogLocked(log, "Refreshing {0}...", Format.ToString(server.EndPoint));
// note that these will be processed synchronously *BEFORE* the tracer is processed,
// so we know that the configuration will be up to date if we see the tracer
server.AutoConfigure(null);
}
available[i] = server.SendTracer(log);
if (useTieBreakers)
{
LogLocked(log, "Requesting tie-break from {0} > {1}...", Format.ToString(server.EndPoint), configuration.TieBreaker);
Message msg = Message.Create(0, flags, RedisCommand.GET, tieBreakerKey);
msg.SetInternalCall();
msg = LoggingMessage.Create(log, msg);
tieBreakers[i] = server.QueueDirectAsync(msg, ResultProcessor.String);
}
}
}
LogLocked(log, "Allowing endpoints {0} to respond...", TimeSpan.FromMilliseconds(configuration.ConnectTimeout));
Trace("Allowing endpoints " + TimeSpan.FromMilliseconds(configuration.ConnectTimeout) + " to respond...");
await WaitAllIgnoreErrorsAsync(available, configuration.ConnectTimeout, log).ForAwait();
List<ServerEndPoint> masters = new List<ServerEndPoint>(available.Length);
watch = watch ?? Stopwatch.StartNew();
var remaining = configuration.ConnectTimeout - checked((int)watch.ElapsedMilliseconds);
LogLocked(log, "Allowing endpoints {0} to respond...", TimeSpan.FromMilliseconds(remaining));
Trace("Allowing endpoints " + TimeSpan.FromMilliseconds(remaining) + " to respond...");
await WaitAllIgnoreErrorsAsync(available, remaining, log).ForAwait();
for (int i = 0; i < available.Length; i++)
{
var task = available[i];
Trace(Format.ToString(endpoints[i]) + ": " + task.Status);
if (task.IsFaulted)
EndPointCollection updatedClusterEndpointCollection = null;
for (int i = 0; i < available.Length; i++)
{
servers[i].SetUnselectable(UnselectableFlags.DidNotRespond);
var aex = task.Exception;
foreach (var ex in aex.InnerExceptions)
var task = available[i];
Trace(Format.ToString(endpoints[i]) + ": " + task.Status);
if (task.IsFaulted)
{
servers[i].SetUnselectable(UnselectableFlags.DidNotRespond);
var aex = task.Exception;
foreach (var ex in aex.InnerExceptions)
{
LogLocked(log, "{0} faulted: {1}", Format.ToString(endpoints[i]), ex.Message);
failureMessage = ex.Message;
}
}
else if (task.IsCanceled)
{
LogLocked(log, "{0} faulted: {1}", Format.ToString(endpoints[i]), ex.Message);
failureMessage = ex.Message;
servers[i].SetUnselectable(UnselectableFlags.DidNotRespond);
LogLocked(log, "{0} was canceled", Format.ToString(endpoints[i]));
}
}
else if (task.IsCanceled)
{
servers[i].SetUnselectable(UnselectableFlags.DidNotRespond);
LogLocked(log, "{0} was canceled", Format.ToString(endpoints[i]));
}
else if (task.IsCompleted)
{
var server = servers[i];
if (task.Result)
else if (task.IsCompleted)
{
servers[i].ClearUnselectable(UnselectableFlags.DidNotRespond);
LogLocked(log, "{0} returned with success", Format.ToString(endpoints[i]));
// count the server types
switch (server.ServerType)
var server = servers[i];
if (task.Result)
{
case ServerType.Twemproxy:
case ServerType.Standalone:
standaloneCount++;
break;
case ServerType.Sentinel:
sentinelCount++;
break;
case ServerType.Cluster:
clusterCount++;
break;
}
servers[i].ClearUnselectable(UnselectableFlags.DidNotRespond);
LogLocked(log, "{0} returned with success", Format.ToString(endpoints[i]));
// count the server types
switch (server.ServerType)
{
case ServerType.Twemproxy:
case ServerType.Standalone:
standaloneCount++;
break;
case ServerType.Sentinel:
sentinelCount++;
break;
case ServerType.Cluster:
clusterCount++;
break;
}
// set the server UnselectableFlags and update masters list
switch (server.ServerType)
if (clusterCount > 0 && !encounteredConnectedClusterServer)
{
// we have encountered a connected server with clustertype for the first time.
// so we will get list of other nodes from this server using "CLUSTER NODES" command
// and try to connect to these other nodes in the next iteration
encounteredConnectedClusterServer = true;
updatedClusterEndpointCollection = GetEndpointsFromClusterNodes(server, log);
}
// set the server UnselectableFlags and update masters list
switch (server.ServerType)
{
case ServerType.Twemproxy:
case ServerType.Sentinel:
case ServerType.Standalone:
case ServerType.Cluster:
servers[i].ClearUnselectable(UnselectableFlags.ServerType);
if (server.IsSlave)
{
servers[i].ClearUnselectable(UnselectableFlags.RedundantMaster);
}
else
{
masters.Add(server);
}
break;
default:
servers[i].SetUnselectable(UnselectableFlags.ServerType);
break;
}
}
else
{
case ServerType.Twemproxy:
case ServerType.Sentinel:
case ServerType.Standalone:
case ServerType.Cluster:
servers[i].ClearUnselectable(UnselectableFlags.ServerType);
if (server.IsSlave)
{
servers[i].ClearUnselectable(UnselectableFlags.RedundantMaster);
}
else
{
masters.Add(server);
}
break;
default:
servers[i].SetUnselectable(UnselectableFlags.ServerType);
break;
servers[i].SetUnselectable(UnselectableFlags.DidNotRespond);
LogLocked(log, "{0} returned, but incorrectly", Format.ToString(endpoints[i]));
}
}
else
{
servers[i].SetUnselectable(UnselectableFlags.DidNotRespond);
LogLocked(log, "{0} returned, but incorrectly", Format.ToString(endpoints[i]));
LogLocked(log, "{0} did not respond", Format.ToString(endpoints[i]));
}
}
if (encounteredConnectedClusterServer)
{
endpoints = updatedClusterEndpointCollection;
}
else
{
servers[i].SetUnselectable(UnselectableFlags.DidNotRespond);
LogLocked(log, "{0} did not respond", Format.ToString(endpoints[i]));
break; // we do not want to repeat the second iteration
}
}
......@@ -1432,6 +1473,23 @@ internal async Task<bool> ReconfigureAsync(bool first, bool reconfigureAll, Text
}
}
private EndPointCollection GetEndpointsFromClusterNodes(ServerEndPoint server, TextWriter log)
{
var message = Message.Create(-1, CommandFlags.None, RedisCommand.CLUSTER, RedisLiterals.NODES);
ClusterConfiguration clusterConfig = null;
try
{
clusterConfig = this.ExecuteSyncImpl(message, ResultProcessor.ClusterNodes, server);
return new EndPointCollection(clusterConfig.Nodes.Select(node => node.EndPoint).ToList());
}
catch (Exception ex)
{
LogLocked(log, "Encountered error while updating cluster config: " + ex.Message);
return null;
}
}
private void ResetAllNonConnected()
{
var snapshot = serverSnapshot;
......@@ -1916,7 +1974,7 @@ internal T ExecuteSyncImpl<T>(Message message, ResultProcessor<T> processor, Ser
add("Active-Readers", "ar", ar.ToString());
add("Client-Name", "clientName", ClientName);
#if !DNXCORE50
#if !CORE_CLR
string iocp, worker;
int busyWorkerCount = GetThreadPoolStats(out iocp, out worker);
add("ThreadPool-IO-Completion", "IOCP", iocp);
......@@ -1953,7 +2011,7 @@ internal T ExecuteSyncImpl<T>(Message message, ResultProcessor<T> processor, Ser
}
}
#if !DNXCORE50
#if !CORE_CLR
private static int GetThreadPoolStats(out string iocp, out string worker)
{
//BusyThreads = TP.GetMaxThreads() –TP.GetAVailable();
......
......@@ -299,9 +299,10 @@ public enum CompletionType
/// </summary>
Async = 2
}
#if !CORE_CLR
internal class CompletionTypeHelper
{
public static void RunWithCompletionType(Func<AsyncCallback, IAsyncResult> beginAsync, AsyncCallback callback, CompletionType completionType)
{
AsyncCallback proxyCallback;
......@@ -343,6 +344,7 @@ public static void RunWithCompletionType(Func<AsyncCallback, IAsyncResult> begin
return;
}
}
#endif
#if VERBOSE
......
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
......@@ -9,6 +10,14 @@ namespace StackExchange.Redis
/// </summary>
public sealed class EndPointCollection : Collection<EndPoint>
{
public EndPointCollection() : base()
{
}
public EndPointCollection(IList<EndPoint> endpoints) : base(endpoints)
{
}
/// <summary>
/// Format an endpoint
/// </summary>
......
using System;
using System.Collections.Generic;
using System.Linq;
namespace StackExchange.Redis
{
/// <summary>
/// Utility methods
/// </summary>
public static class ExtensionMethods
{
/// <summary>
/// Create a dictionary from an array of HashEntry values
/// </summary>
public static Dictionary<string,string> ToStringDictionary(this HashEntry[] hash)
{
if (hash == null) return null;
var result = new Dictionary<string, string>(hash.Length, StringComparer.Ordinal);
for(int i = 0; i < hash.Length; i++)
{
result.Add(hash[i].name, hash[i].value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of HashEntry values
/// </summary>
public static Dictionary<RedisValue, RedisValue> ToDictionary(this HashEntry[] hash)
{
if (hash == null) return null;
var result = new Dictionary<RedisValue, RedisValue>(hash.Length);
for (int i = 0; i < hash.Length; i++)
{
result.Add(hash[i].name, hash[i].value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of SortedSetEntry values
/// </summary>
public static Dictionary<string, double> ToStringDictionary(this SortedSetEntry[] sortedSet)
{
if (sortedSet == null) return null;
var result = new Dictionary<string, double>(sortedSet.Length, StringComparer.Ordinal);
for (int i = 0; i < sortedSet.Length; i++)
{
result.Add(sortedSet[i].element, sortedSet[i].score);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of SortedSetEntry values
/// </summary>
public static Dictionary<RedisValue, double> ToDictionary(this SortedSetEntry[] sortedSet)
{
if (sortedSet == null) return null;
var result = new Dictionary<RedisValue, double>(sortedSet.Length);
for (int i = 0; i < sortedSet.Length; i++)
{
result.Add(sortedSet[i].element, sortedSet[i].score);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of key/value pairs
/// </summary>
public static Dictionary<string, string> ToStringDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of key/value pairs
/// </summary>
public static Dictionary<RedisKey, RedisValue> ToDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<RedisKey, RedisValue>(pairs.Length);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of string pairs
/// </summary>
public static Dictionary<string, string> ToDictionary(this KeyValuePair<string, string>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
static readonly string[] nix = new string[0];
/// <summary>
/// Create an array of strings from an array of values
/// </summary>
public static string[] ToStringArray(this RedisValue[] values)
{
if (values == null) return null;
if (values.Length == 0) return nix;
return values.Select(x => (string)x).ToArray();
}
}
}
using System;
using System.Collections.Generic;
namespace StackExchange.Redis
{
/// <summary>
/// Utility methods
/// </summary>
public static class ExtensionMethods
{
/// <summary>
/// Create a dictionary from an array of HashEntry values
/// </summary>
public static Dictionary<string,string> ToStringDictionary(this HashEntry[] hash)
{
if (hash == null) return null;
var result = new Dictionary<string, string>(hash.Length, StringComparer.Ordinal);
for(int i = 0; i < hash.Length; i++)
{
result.Add(hash[i].name, hash[i].value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of HashEntry values
/// </summary>
public static Dictionary<RedisValue, RedisValue> ToDictionary(this HashEntry[] hash)
{
if (hash == null) return null;
var result = new Dictionary<RedisValue, RedisValue>(hash.Length);
for (int i = 0; i < hash.Length; i++)
{
result.Add(hash[i].name, hash[i].value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of SortedSetEntry values
/// </summary>
public static Dictionary<string, double> ToStringDictionary(this SortedSetEntry[] sortedSet)
{
if (sortedSet == null) return null;
var result = new Dictionary<string, double>(sortedSet.Length, StringComparer.Ordinal);
for (int i = 0; i < sortedSet.Length; i++)
{
result.Add(sortedSet[i].element, sortedSet[i].score);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of SortedSetEntry values
/// </summary>
public static Dictionary<RedisValue, double> ToDictionary(this SortedSetEntry[] sortedSet)
{
if (sortedSet == null) return null;
var result = new Dictionary<RedisValue, double>(sortedSet.Length);
for (int i = 0; i < sortedSet.Length; i++)
{
result.Add(sortedSet[i].element, sortedSet[i].score);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of key/value pairs
/// </summary>
public static Dictionary<string, string> ToStringDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of key/value pairs
/// </summary>
public static Dictionary<RedisKey, RedisValue> ToDictionary(this KeyValuePair<RedisKey, RedisValue>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<RedisKey, RedisValue>(pairs.Length);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
/// <summary>
/// Create a dictionary from an array of string pairs
/// </summary>
public static Dictionary<string, string> ToDictionary(this KeyValuePair<string, string>[] pairs)
{
if (pairs == null) return null;
var result = new Dictionary<string, string>(pairs.Length, StringComparer.Ordinal);
for (int i = 0; i < pairs.Length; i++)
{
result.Add(pairs[i].Key, pairs[i].Value);
}
return result;
}
static readonly string[] nix = new string[0];
/// <summary>
/// Create an array of strings from an array of values
/// </summary>
public static string[] ToStringArray(this RedisValue[] values)
{
if (values == null) return null;
if (values.Length == 0) return nix;
return ConvertHelper.ConvertAll(values, x => (string)x);
}
}
}
......@@ -133,7 +133,7 @@ internal static bool TryGetHostPort(EndPoint endpoint, out string host, out int
internal static bool TryParseDouble(string s, out double value)
{
if(s == null || s.Length == 0)
if(string.IsNullOrEmpty(s))
{
value = 0;
return false;
......
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace StackExchange.Redis
{
/// <summary>
/// Describes a hash-field (a name/value pair)
/// </summary>
public struct HashEntry : IEquatable<HashEntry>
{
internal readonly RedisValue name, value;
/// <summary>
/// Initializes a HashEntry value
/// </summary>
public HashEntry(RedisValue name, RedisValue value)
{
this.name = name;
this.value = value;
}
/// <summary>
/// The name of the hash field
/// </summary>
public RedisValue Name { get { return name; } }
/// <summary>
/// The value of the hash field
/// </summary>
public RedisValue Value{ get { return value; } }
/// <summary>
/// The name of the hash field
/// </summary>
#if !DNXCORE50
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Name", false)]
public RedisValue Key { get { return name; } }
/// <summary>
/// Converts to a key/value pair
/// </summary>
public static implicit operator KeyValuePair<RedisValue, RedisValue>(HashEntry value)
{
return new KeyValuePair<RedisValue, RedisValue>(value.name, value.value);
}
/// <summary>
/// Converts from a key/value pair
/// </summary>
public static implicit operator HashEntry(KeyValuePair<RedisValue, RedisValue> value)
{
return new HashEntry(value.Key, value.Value);
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
return name + ": " + value;
}
/// <summary>
/// See Object.GetHashCode()
/// </summary>
public override int GetHashCode()
{
return name.GetHashCode() ^ value.GetHashCode();
}
/// <summary>
/// Compares two values for equality
/// </summary>
public override bool Equals(object obj)
{
return obj is HashEntry && Equals((HashEntry)obj);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public bool Equals(HashEntry value)
{
return this.name == value.name && this.value == value.value;
}
/// <summary>
/// Compares two values for equality
/// </summary>
public static bool operator ==(HashEntry x, HashEntry y)
{
return x.name == y.name && x.value == y.value;
}
/// <summary>
/// Compares two values for non-equality
/// </summary>
public static bool operator !=(HashEntry x, HashEntry y)
{
return x.name != y.name || x.value != y.value;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace StackExchange.Redis
{
/// <summary>
/// Describes a hash-field (a name/value pair)
/// </summary>
public struct HashEntry : IEquatable<HashEntry>
{
internal readonly RedisValue name, value;
/// <summary>
/// Initializes a HashEntry value
/// </summary>
public HashEntry(RedisValue name, RedisValue value)
{
this.name = name;
this.value = value;
}
/// <summary>
/// The name of the hash field
/// </summary>
public RedisValue Name { get { return name; } }
/// <summary>
/// The value of the hash field
/// </summary>
public RedisValue Value{ get { return value; } }
/// <summary>
/// The name of the hash field
/// </summary>
#if !CORE_CLR
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Name", false)]
public RedisValue Key { get { return name; } }
/// <summary>
/// Converts to a key/value pair
/// </summary>
public static implicit operator KeyValuePair<RedisValue, RedisValue>(HashEntry value)
{
return new KeyValuePair<RedisValue, RedisValue>(value.name, value.value);
}
/// <summary>
/// Converts from a key/value pair
/// </summary>
public static implicit operator HashEntry(KeyValuePair<RedisValue, RedisValue> value)
{
return new HashEntry(value.Key, value.Value);
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
return name + ": " + value;
}
/// <summary>
/// See Object.GetHashCode()
/// </summary>
public override int GetHashCode()
{
return name.GetHashCode() ^ value.GetHashCode();
}
/// <summary>
/// Compares two values for equality
/// </summary>
public override bool Equals(object obj)
{
return obj is HashEntry && Equals((HashEntry)obj);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public bool Equals(HashEntry value)
{
return this.name == value.name && this.value == value.value;
}
/// <summary>
/// Compares two values for equality
/// </summary>
public static bool operator ==(HashEntry x, HashEntry y)
{
return x.name == y.name && x.value == y.value;
}
/// <summary>
/// Compares two values for non-equality
/// </summary>
public static bool operator !=(HashEntry x, HashEntry y)
{
return x.name != y.name || x.value != y.value;
}
}
}
#if DNXCORE50
using System;
#endif
using System;
using System.Text.RegularExpressions;
namespace StackExchange.Redis
{
/// <summary>
/// Credits to Sam Harwell https://github.com/dotnet/corefx/issues/340#issuecomment-120749951
/// </summary>
internal static class InternalRegexCompiledOption
{
private static readonly RegexOptions RegexCompiledOption;
static InternalRegexCompiledOption()
{
#if DNXCORE50
#if CORE_CLR
if (!Enum.TryParse("Compiled", out RegexCompiledOption))
RegexCompiledOption = RegexOptions.None;
#else
......
......@@ -335,12 +335,12 @@ public Task<RedisResult> ScriptEvaluateAsync(string script, RedisKey[] keys = nu
public Task<RedisResult> ScriptEvaluateAsync(LuaScript script, object parameters = null, CommandFlags flags = CommandFlags.None)
{
throw new NotImplementedException();
return this.Inner.ScriptEvaluateAsync(script, parameters, flags);
}
public Task<RedisResult> ScriptEvaluateAsync(LoadedLuaScript script, object parameters = null, CommandFlags flags = CommandFlags.None)
{
throw new NotImplementedException();
return this.Inner.ScriptEvaluateAsync(script, parameters, flags);
}
public Task<long> SetAddAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None)
......
......@@ -10,7 +10,7 @@
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
#if DNXCORE50
#if CORE_CLR
using System.Threading.Tasks;
#endif
......@@ -131,7 +131,7 @@ public void Dispose()
if (outStream != null)
{
multiplexer.Trace("Disconnecting...", physicalName);
#if !DNXCORE50
#if !CORE_CLR
try { outStream.Close(); } catch { }
#endif
try { outStream.Dispose(); } catch { }
......@@ -139,7 +139,7 @@ public void Dispose()
}
if (netStream != null)
{
#if !DNXCORE50
#if !CORE_CLR
try { netStream.Close(); } catch { }
#endif
try { netStream.Dispose(); } catch { }
......@@ -603,6 +603,22 @@ unsafe void WriteRaw(Stream stream, string value, int encodedLength)
}
else
{
#if !CORE_CLR
fixed (char* c = value)
fixed (byte* b = outScratch)
{
int charsRemaining = value.Length, charOffset = 0, bytesWritten;
while (charsRemaining > Scratch_CharsPerBlock)
{
bytesWritten = outEncoder.GetBytes(c + charOffset, Scratch_CharsPerBlock, b, ScratchSize, false);
stream.Write(outScratch, 0, bytesWritten);
charOffset += Scratch_CharsPerBlock;
charsRemaining -= Scratch_CharsPerBlock;
}
bytesWritten = outEncoder.GetBytes(c + charOffset, charsRemaining, b, ScratchSize, true);
if (bytesWritten != 0) stream.Write(outScratch, 0, bytesWritten);
}
#else
int charsRemaining = value.Length, charOffset = 0, bytesWritten;
var valueCharArray = value.ToCharArray();
while (charsRemaining > Scratch_CharsPerBlock)
......@@ -614,6 +630,7 @@ unsafe void WriteRaw(Stream stream, string value, int encodedLength)
}
bytesWritten = outEncoder.GetBytes(valueCharArray, charOffset, charsRemaining, outScratch, 0, true);
if (bytesWritten != 0) stream.Write(outScratch, 0, bytesWritten);
#endif
}
}
const int ScratchSize = 512;
......@@ -661,7 +678,7 @@ void BeginReading()
int space = EnsureSpaceAndComputeBytesToRead();
multiplexer.Trace("Beginning async read...", physicalName);
var result = netStream.BeginRead(ioBuffer, ioBufferBytes, space, endRead, this);
#if DNXCORE50
#if CORE_CLR
Task<int> t = (Task<int>)result;
if (t.Status == TaskStatus.RanToCompletion && t.Result == -1)
{
......@@ -676,7 +693,7 @@ void BeginReading()
}
} while (keepReading);
}
#if DNXCORE50
#if CORE_CLR
catch (AggregateException ex)
{
throw ex.InnerException;
......@@ -759,7 +776,7 @@ SocketMode ISocketCallback.Connected(Stream stream, TextWriter log)
int bufferSize = config.WriteBuffer;
this.netStream = stream;
#if !DNXCORE50
#if !CORE_CLR
this.outStream = bufferSize <= 0 ? stream : new BufferedStream(stream, bufferSize);
#else
this.outStream = stream;
......@@ -1096,7 +1113,7 @@ public void CheckForStaleConnection(ref SocketManager.ManagerState managerState)
}
}
#if DNXCORE50
#if CORE_CLR
internal static class StreamExtensions
{
internal static IAsyncResult BeginRead(this Stream stream, byte[] buffer, int offset, int count, AsyncCallback ac, object state)
......
......@@ -484,7 +484,7 @@ sealed class KeyMigrateCommandMessage : Message.CommandKeyBase // MIGRATE is aty
public KeyMigrateCommandMessage(int db, RedisKey key, EndPoint toServer, int toDatabase, int timeoutMilliseconds, MigrateOptions migrateOptions, CommandFlags flags)
: base(db, flags, RedisCommand.MIGRATE, key)
{
if (toServer == null) throw new ArgumentNullException("server");
if (toServer == null) throw new ArgumentNullException("toServer");
string toHost;
int toPort;
if (!Format.TryGetHostPort(toServer, out toHost, out toPort)) throw new ArgumentException("toServer");
......
using System;
using System.Linq;
namespace StackExchange.Redis
{
/// <summary>
/// Represents a general-purpose result from redis, that may be cast into various anticipated types
/// </summary>
public abstract class RedisResult
{
// internally, this is very similar to RawResult, except it is designed to be usable
// outside of the IO-processing pipeline: the buffers are standalone, etc
internal static RedisResult TryCreate(PhysicalConnection connection, RawResult result)
{
try
{
switch (result.Type)
{
case ResultType.Integer:
case ResultType.SimpleString:
case ResultType.BulkString:
return new SingleRedisResult(result.AsRedisValue());
case ResultType.MultiBulk:
var items = result.GetItems();
var arr = new RedisResult[items.Length];
for (int i = 0; i < arr.Length; i++)
{
var next = TryCreate(connection, items[i]);
if (next == null) return null; // means we didn't understand
arr[i] = next;
}
return new ArrayRedisResult(arr);
case ResultType.Error:
return new ErrorRedisResult(result.GetString());
default:
return null;
}
} catch(Exception ex)
{
if(connection != null) connection.OnInternalError(ex);
return null; // will be logged as a protocol fail by the processor
}
}
/// <summary>
/// Indicates whether this result was a null result
/// </summary>
public abstract bool IsNull { get; }
/// <summary>
/// Interprets the result as a String
/// </summary>
public static explicit operator string (RedisResult result) { return result.AsString(); }
/// <summary>
/// Interprets the result as a Byte[]
/// </summary>
public static explicit operator byte[] (RedisResult result) { return result.AsByteArray(); }
/// <summary>
/// Interprets the result as a Double
/// </summary>
public static explicit operator double (RedisResult result) { return result.AsDouble(); }
/// <summary>
/// Interprets the result as an Int64
/// </summary>
public static explicit operator long (RedisResult result) { return result.AsInt64(); }
/// <summary>
/// Interprets the result as an Int32
/// </summary>
public static explicit operator int (RedisResult result) { return result.AsInt32(); }
/// <summary>
/// Interprets the result as a Boolean
/// </summary>
public static explicit operator bool (RedisResult result) { return result.AsBoolean(); }
/// <summary>
/// Interprets the result as a RedisValue
/// </summary>
public static explicit operator RedisValue (RedisResult result) { return result.AsRedisValue(); }
/// <summary>
/// Interprets the result as a RedisKey
/// </summary>
public static explicit operator RedisKey (RedisResult result) { return result.AsRedisKey(); }
/// <summary>
/// Interprets the result as a Nullable Double
/// </summary>
public static explicit operator double? (RedisResult result) { return result.AsNullableDouble(); }
/// <summary>
/// Interprets the result as a Nullable Int64
/// </summary>
public static explicit operator long? (RedisResult result) { return result.AsNullableInt64(); }
/// <summary>
/// Interprets the result as a Nullable Int32
/// </summary>
public static explicit operator int? (RedisResult result) { return result.AsNullableInt32(); }
/// <summary>
/// Interprets the result as a Nullable Boolean
/// </summary>
public static explicit operator bool? (RedisResult result) { return result.AsNullableBoolean(); }
/// <summary>
/// Interprets the result as an array of String
/// </summary>
public static explicit operator string[] (RedisResult result) { return result.AsStringArray(); }
/// <summary>
/// Interprets the result as an array of Byte[]
/// </summary>
public static explicit operator byte[][] (RedisResult result) { return result.AsByteArrayArray(); }
/// <summary>
/// Interprets the result as an array of Double
/// </summary>
public static explicit operator double[] (RedisResult result) { return result.AsDoubleArray(); }
/// <summary>
/// Interprets the result as an array of Int64
/// </summary>
public static explicit operator long[] (RedisResult result) { return result.AsInt64Array(); }
/// <summary>
/// Interprets the result as an array of Int32
/// </summary>
public static explicit operator int[] (RedisResult result) { return result.AsInt32Array(); }
/// <summary>
/// Interprets the result as an array of Boolean
/// </summary>
public static explicit operator bool[] (RedisResult result) { return result.AsBooleanArray(); }
/// <summary>
/// Interprets the result as an array of RedisValue
/// </summary>
public static explicit operator RedisValue[] (RedisResult result) { return result.AsRedisValueArray(); }
/// <summary>
/// Interprets the result as an array of RedisKey
/// </summary>
public static explicit operator RedisKey[] (RedisResult result) { return result.AsRedisKeyArray(); }
/// <summary>
/// Interprets the result as an array of RedisResult
/// </summary>
public static explicit operator RedisResult[] (RedisResult result) { return result.AsRedisResultArray(); }
internal abstract bool AsBoolean();
internal abstract bool[] AsBooleanArray();
internal abstract byte[] AsByteArray();
internal abstract byte[][] AsByteArrayArray();
internal abstract double AsDouble();
internal abstract double[] AsDoubleArray();
internal abstract int AsInt32();
internal abstract int[] AsInt32Array();
internal abstract long AsInt64();
internal abstract long[] AsInt64Array();
internal abstract bool? AsNullableBoolean();
internal abstract double? AsNullableDouble();
internal abstract int? AsNullableInt32();
internal abstract long? AsNullableInt64();
internal abstract RedisKey AsRedisKey();
internal abstract RedisKey[] AsRedisKeyArray();
internal abstract RedisResult[] AsRedisResultArray();
internal abstract RedisValue AsRedisValue();
internal abstract RedisValue[] AsRedisValueArray();
internal abstract string AsString();
internal abstract string[] AsStringArray();
private sealed class ArrayRedisResult : RedisResult
{
public override bool IsNull
{
get { return value == null; }
}
private readonly RedisResult[] value;
public ArrayRedisResult(RedisResult[] value)
{
if (value == null) throw new ArgumentNullException("value");
this.value = value;
}
public override string ToString()
{
return value.Length + " element(s)";
}
internal override bool AsBoolean()
{
if (value.Length == 1) return value[0].AsBoolean();
throw new InvalidCastException();
}
internal override bool[] AsBooleanArray() { return value.Select(x => x.AsBoolean()).ToArray(); }
internal override byte[] AsByteArray()
{
if (value.Length == 1) return value[0].AsByteArray();
throw new InvalidCastException();
}
internal override byte[][] AsByteArrayArray() { return value.Select(x => x.AsByteArray()).ToArray(); }
internal override double AsDouble()
{
if (value.Length == 1) return value[0].AsDouble();
throw new InvalidCastException();
}
internal override double[] AsDoubleArray() { return value.Select(x => x.AsDouble()).ToArray(); }
internal override int AsInt32()
{
if (value.Length == 1) return value[0].AsInt32();
throw new InvalidCastException();
}
internal override int[] AsInt32Array() { return value.Select(x => x.AsInt32()).ToArray(); }
internal override long AsInt64()
{
if (value.Length == 1) return value[0].AsInt64();
throw new InvalidCastException();
}
internal override long[] AsInt64Array() { return value.Select(x => x.AsInt64()).ToArray(); }
internal override bool? AsNullableBoolean()
{
if (value.Length == 1) return value[0].AsNullableBoolean();
throw new InvalidCastException();
}
internal override double? AsNullableDouble()
{
if (value.Length == 1) return value[0].AsNullableDouble();
throw new InvalidCastException();
}
internal override int? AsNullableInt32()
{
if (value.Length == 1) return value[0].AsNullableInt32();
throw new InvalidCastException();
}
internal override long? AsNullableInt64()
{
if (value.Length == 1) return value[0].AsNullableInt64();
throw new InvalidCastException();
}
internal override RedisKey AsRedisKey()
{
if (value.Length == 1) return value[0].AsRedisKey();
throw new InvalidCastException();
}
internal override RedisKey[] AsRedisKeyArray() { return value.Select(x => x.AsRedisKey()).ToArray(); }
internal override RedisResult[] AsRedisResultArray() { return value; }
internal override RedisValue AsRedisValue()
{
if (value.Length == 1) return value[0].AsRedisValue();
throw new InvalidCastException();
}
internal override RedisValue[] AsRedisValueArray() { return value.Select(x => x.AsRedisValue()).ToArray(); }
internal override string AsString()
{
if (value.Length == 1) return value[0].AsString();
throw new InvalidCastException();
}
internal override string[] AsStringArray() { return value.Select(x => x.AsString()).ToArray(); }
}
private sealed class ErrorRedisResult : RedisResult
{
private readonly string value;
public ErrorRedisResult(string value)
{
if (value == null) throw new ArgumentNullException("value");
this.value = value;
}
public override bool IsNull
{
get { return value == null; }
}
public override string ToString() { return value; }
internal override bool AsBoolean() { throw new RedisServerException(value); }
internal override bool[] AsBooleanArray() { throw new RedisServerException(value); }
internal override byte[] AsByteArray() { throw new RedisServerException(value); }
internal override byte[][] AsByteArrayArray() { throw new RedisServerException(value); }
internal override double AsDouble() { throw new RedisServerException(value); }
internal override double[] AsDoubleArray() { throw new RedisServerException(value); }
internal override int AsInt32() { throw new RedisServerException(value); }
internal override int[] AsInt32Array() { throw new RedisServerException(value); }
internal override long AsInt64() { throw new RedisServerException(value); }
internal override long[] AsInt64Array() { throw new RedisServerException(value); }
internal override bool? AsNullableBoolean() { throw new RedisServerException(value); }
internal override double? AsNullableDouble() { throw new RedisServerException(value); }
internal override int? AsNullableInt32() { throw new RedisServerException(value); }
internal override long? AsNullableInt64() { throw new RedisServerException(value); }
internal override RedisKey AsRedisKey() { throw new RedisServerException(value); }
internal override RedisKey[] AsRedisKeyArray() { throw new RedisServerException(value); }
internal override RedisResult[] AsRedisResultArray() { throw new RedisServerException(value); }
internal override RedisValue AsRedisValue() { throw new RedisServerException(value); }
internal override RedisValue[] AsRedisValueArray() { throw new RedisServerException(value); }
internal override string AsString() { throw new RedisServerException(value); }
internal override string[] AsStringArray() { throw new RedisServerException(value); }
}
private sealed class SingleRedisResult : RedisResult
{
private readonly RedisValue value;
public SingleRedisResult(RedisValue value)
{
this.value = value;
}
public override bool IsNull
{
get { return value.IsNull; }
}
public override string ToString() { return value.ToString(); }
internal override bool AsBoolean() { return (bool)value; }
internal override bool[] AsBooleanArray() { return new[] { AsBoolean() }; }
internal override byte[] AsByteArray() { return (byte[])value; }
internal override byte[][] AsByteArrayArray() { return new[] { AsByteArray() }; }
internal override double AsDouble() { return (double)value; }
internal override double[] AsDoubleArray() { return new[] { AsDouble() }; }
internal override int AsInt32() { return (int)value; }
internal override int[] AsInt32Array() { return new[] { AsInt32() }; }
internal override long AsInt64() { return (long)value; }
internal override long[] AsInt64Array() { return new[] { AsInt64() }; }
internal override bool? AsNullableBoolean() { return (bool?)value; }
internal override double? AsNullableDouble() { return (double?)value; }
internal override int? AsNullableInt32() { return (int?)value; }
internal override long? AsNullableInt64() { return (long?)value; }
internal override RedisKey AsRedisKey() { return (byte[])value; }
internal override RedisKey[] AsRedisKeyArray() { return new[] { AsRedisKey() }; }
internal override RedisResult[] AsRedisResultArray() { throw new InvalidCastException(); }
internal override RedisValue AsRedisValue() { return value; }
internal override RedisValue[] AsRedisValueArray() { return new[] { AsRedisValue() }; }
internal override string AsString() { return (string)value; }
internal override string[] AsStringArray() { return new[] { AsString() }; }
}
}
}
using System;
namespace StackExchange.Redis
{
/// <summary>
/// Represents a general-purpose result from redis, that may be cast into various anticipated types
/// </summary>
public abstract class RedisResult
{
// internally, this is very similar to RawResult, except it is designed to be usable
// outside of the IO-processing pipeline: the buffers are standalone, etc
internal static RedisResult TryCreate(PhysicalConnection connection, RawResult result)
{
try
{
switch (result.Type)
{
case ResultType.Integer:
case ResultType.SimpleString:
case ResultType.BulkString:
return new SingleRedisResult(result.AsRedisValue());
case ResultType.MultiBulk:
var items = result.GetItems();
var arr = new RedisResult[items.Length];
for (int i = 0; i < arr.Length; i++)
{
var next = TryCreate(connection, items[i]);
if (next == null) return null; // means we didn't understand
arr[i] = next;
}
return new ArrayRedisResult(arr);
case ResultType.Error:
return new ErrorRedisResult(result.GetString());
default:
return null;
}
} catch(Exception ex)
{
if(connection != null) connection.OnInternalError(ex);
return null; // will be logged as a protocol fail by the processor
}
}
/// <summary>
/// Indicates whether this result was a null result
/// </summary>
public abstract bool IsNull { get; }
/// <summary>
/// Interprets the result as a String
/// </summary>
public static explicit operator string (RedisResult result) { return result.AsString(); }
/// <summary>
/// Interprets the result as a Byte[]
/// </summary>
public static explicit operator byte[] (RedisResult result) { return result.AsByteArray(); }
/// <summary>
/// Interprets the result as a Double
/// </summary>
public static explicit operator double (RedisResult result) { return result.AsDouble(); }
/// <summary>
/// Interprets the result as an Int64
/// </summary>
public static explicit operator long (RedisResult result) { return result.AsInt64(); }
/// <summary>
/// Interprets the result as an Int32
/// </summary>
public static explicit operator int (RedisResult result) { return result.AsInt32(); }
/// <summary>
/// Interprets the result as a Boolean
/// </summary>
public static explicit operator bool (RedisResult result) { return result.AsBoolean(); }
/// <summary>
/// Interprets the result as a RedisValue
/// </summary>
public static explicit operator RedisValue (RedisResult result) { return result.AsRedisValue(); }
/// <summary>
/// Interprets the result as a RedisKey
/// </summary>
public static explicit operator RedisKey (RedisResult result) { return result.AsRedisKey(); }
/// <summary>
/// Interprets the result as a Nullable Double
/// </summary>
public static explicit operator double? (RedisResult result) { return result.AsNullableDouble(); }
/// <summary>
/// Interprets the result as a Nullable Int64
/// </summary>
public static explicit operator long? (RedisResult result) { return result.AsNullableInt64(); }
/// <summary>
/// Interprets the result as a Nullable Int32
/// </summary>
public static explicit operator int? (RedisResult result) { return result.AsNullableInt32(); }
/// <summary>
/// Interprets the result as a Nullable Boolean
/// </summary>
public static explicit operator bool? (RedisResult result) { return result.AsNullableBoolean(); }
/// <summary>
/// Interprets the result as an array of String
/// </summary>
public static explicit operator string[] (RedisResult result) { return result.AsStringArray(); }
/// <summary>
/// Interprets the result as an array of Byte[]
/// </summary>
public static explicit operator byte[][] (RedisResult result) { return result.AsByteArrayArray(); }
/// <summary>
/// Interprets the result as an array of Double
/// </summary>
public static explicit operator double[] (RedisResult result) { return result.AsDoubleArray(); }
/// <summary>
/// Interprets the result as an array of Int64
/// </summary>
public static explicit operator long[] (RedisResult result) { return result.AsInt64Array(); }
/// <summary>
/// Interprets the result as an array of Int32
/// </summary>
public static explicit operator int[] (RedisResult result) { return result.AsInt32Array(); }
/// <summary>
/// Interprets the result as an array of Boolean
/// </summary>
public static explicit operator bool[] (RedisResult result) { return result.AsBooleanArray(); }
/// <summary>
/// Interprets the result as an array of RedisValue
/// </summary>
public static explicit operator RedisValue[] (RedisResult result) { return result.AsRedisValueArray(); }
/// <summary>
/// Interprets the result as an array of RedisKey
/// </summary>
public static explicit operator RedisKey[] (RedisResult result) { return result.AsRedisKeyArray(); }
/// <summary>
/// Interprets the result as an array of RedisResult
/// </summary>
public static explicit operator RedisResult[] (RedisResult result) { return result.AsRedisResultArray(); }
internal abstract bool AsBoolean();
internal abstract bool[] AsBooleanArray();
internal abstract byte[] AsByteArray();
internal abstract byte[][] AsByteArrayArray();
internal abstract double AsDouble();
internal abstract double[] AsDoubleArray();
internal abstract int AsInt32();
internal abstract int[] AsInt32Array();
internal abstract long AsInt64();
internal abstract long[] AsInt64Array();
internal abstract bool? AsNullableBoolean();
internal abstract double? AsNullableDouble();
internal abstract int? AsNullableInt32();
internal abstract long? AsNullableInt64();
internal abstract RedisKey AsRedisKey();
internal abstract RedisKey[] AsRedisKeyArray();
internal abstract RedisResult[] AsRedisResultArray();
internal abstract RedisValue AsRedisValue();
internal abstract RedisValue[] AsRedisValueArray();
internal abstract string AsString();
internal abstract string[] AsStringArray();
private sealed class ArrayRedisResult : RedisResult
{
public override bool IsNull
{
get { return value == null; }
}
private readonly RedisResult[] value;
public ArrayRedisResult(RedisResult[] value)
{
if (value == null) throw new ArgumentNullException("value");
this.value = value;
}
public override string ToString()
{
return value.Length + " element(s)";
}
internal override bool AsBoolean()
{
if (value.Length == 1) return value[0].AsBoolean();
throw new InvalidCastException();
}
internal override bool[] AsBooleanArray() { return ConvertHelper.ConvertAll(value, x => x.AsBoolean()); }
internal override byte[] AsByteArray()
{
if (value.Length == 1) return value[0].AsByteArray();
throw new InvalidCastException();
}
internal override byte[][] AsByteArrayArray() { return ConvertHelper.ConvertAll(value, x => x.AsByteArray()); }
internal override double AsDouble()
{
if (value.Length == 1) return value[0].AsDouble();
throw new InvalidCastException();
}
internal override double[] AsDoubleArray() { return ConvertHelper.ConvertAll(value, x => x.AsDouble()); }
internal override int AsInt32()
{
if (value.Length == 1) return value[0].AsInt32();
throw new InvalidCastException();
}
internal override int[] AsInt32Array() { return ConvertHelper.ConvertAll(value, x => x.AsInt32()); }
internal override long AsInt64()
{
if (value.Length == 1) return value[0].AsInt64();
throw new InvalidCastException();
}
internal override long[] AsInt64Array() { return ConvertHelper.ConvertAll(value, x => x.AsInt64()); }
internal override bool? AsNullableBoolean()
{
if (value.Length == 1) return value[0].AsNullableBoolean();
throw new InvalidCastException();
}
internal override double? AsNullableDouble()
{
if (value.Length == 1) return value[0].AsNullableDouble();
throw new InvalidCastException();
}
internal override int? AsNullableInt32()
{
if (value.Length == 1) return value[0].AsNullableInt32();
throw new InvalidCastException();
}
internal override long? AsNullableInt64()
{
if (value.Length == 1) return value[0].AsNullableInt64();
throw new InvalidCastException();
}
internal override RedisKey AsRedisKey()
{
if (value.Length == 1) return value[0].AsRedisKey();
throw new InvalidCastException();
}
internal override RedisKey[] AsRedisKeyArray() { return ConvertHelper.ConvertAll(value, x => x.AsRedisKey()); }
internal override RedisResult[] AsRedisResultArray() { return value; }
internal override RedisValue AsRedisValue()
{
if (value.Length == 1) return value[0].AsRedisValue();
throw new InvalidCastException();
}
internal override RedisValue[] AsRedisValueArray() { return ConvertHelper.ConvertAll(value, x => x.AsRedisValue()); }
internal override string AsString()
{
if (value.Length == 1) return value[0].AsString();
throw new InvalidCastException();
}
internal override string[] AsStringArray() { return ConvertHelper.ConvertAll(value, x => x.AsString()); }
}
private sealed class ErrorRedisResult : RedisResult
{
private readonly string value;
public ErrorRedisResult(string value)
{
if (value == null) throw new ArgumentNullException("value");
this.value = value;
}
public override bool IsNull
{
get { return value == null; }
}
public override string ToString() { return value; }
internal override bool AsBoolean() { throw new RedisServerException(value); }
internal override bool[] AsBooleanArray() { throw new RedisServerException(value); }
internal override byte[] AsByteArray() { throw new RedisServerException(value); }
internal override byte[][] AsByteArrayArray() { throw new RedisServerException(value); }
internal override double AsDouble() { throw new RedisServerException(value); }
internal override double[] AsDoubleArray() { throw new RedisServerException(value); }
internal override int AsInt32() { throw new RedisServerException(value); }
internal override int[] AsInt32Array() { throw new RedisServerException(value); }
internal override long AsInt64() { throw new RedisServerException(value); }
internal override long[] AsInt64Array() { throw new RedisServerException(value); }
internal override bool? AsNullableBoolean() { throw new RedisServerException(value); }
internal override double? AsNullableDouble() { throw new RedisServerException(value); }
internal override int? AsNullableInt32() { throw new RedisServerException(value); }
internal override long? AsNullableInt64() { throw new RedisServerException(value); }
internal override RedisKey AsRedisKey() { throw new RedisServerException(value); }
internal override RedisKey[] AsRedisKeyArray() { throw new RedisServerException(value); }
internal override RedisResult[] AsRedisResultArray() { throw new RedisServerException(value); }
internal override RedisValue AsRedisValue() { throw new RedisServerException(value); }
internal override RedisValue[] AsRedisValueArray() { throw new RedisServerException(value); }
internal override string AsString() { throw new RedisServerException(value); }
internal override string[] AsStringArray() { throw new RedisServerException(value); }
}
private sealed class SingleRedisResult : RedisResult
{
private readonly RedisValue value;
public SingleRedisResult(RedisValue value)
{
this.value = value;
}
public override bool IsNull
{
get { return value.IsNull; }
}
public override string ToString() { return value.ToString(); }
internal override bool AsBoolean() { return (bool)value; }
internal override bool[] AsBooleanArray() { return new[] { AsBoolean() }; }
internal override byte[] AsByteArray() { return (byte[])value; }
internal override byte[][] AsByteArrayArray() { return new[] { AsByteArray() }; }
internal override double AsDouble() { return (double)value; }
internal override double[] AsDoubleArray() { return new[] { AsDouble() }; }
internal override int AsInt32() { return (int)value; }
internal override int[] AsInt32Array() { return new[] { AsInt32() }; }
internal override long AsInt64() { return (long)value; }
internal override long[] AsInt64Array() { return new[] { AsInt64() }; }
internal override bool? AsNullableBoolean() { return (bool?)value; }
internal override double? AsNullableDouble() { return (double?)value; }
internal override int? AsNullableInt32() { return (int?)value; }
internal override long? AsNullableInt64() { return (long?)value; }
internal override RedisKey AsRedisKey() { return (byte[])value; }
internal override RedisKey[] AsRedisKeyArray() { return new[] { AsRedisKey() }; }
internal override RedisResult[] AsRedisResultArray() { throw new InvalidCastException(); }
internal override RedisValue AsRedisValue() { return value; }
internal override RedisValue[] AsRedisValueArray() { return new[] { AsRedisValue() }; }
internal override string AsString() { return (string)value; }
internal override string[] AsStringArray() { return new[] { AsString() }; }
}
}
}
using System;
#if DNXCORE50
#if CORE_CLR
using System.Collections.Generic;
using System.Reflection;
#endif
......@@ -306,11 +306,11 @@ public int CompareTo(RedisValue other)
if (otherType == CompareType.Double) return thisDouble.CompareTo(otherDouble);
}
// otherwise, compare as strings
#if !DNXCORE50
#if !CORE_CLR
return StringComparer.InvariantCulture.Compare((string)this, (string)other);
#else
var compareInfo = System.Globalization.CultureInfo.InvariantCulture.CompareInfo;
return compareInfo.Compare((string)this, (string)other, System.Globalization.CompareOptions.IgnoreCase);
return compareInfo.Compare((string)this, (string)other, System.Globalization.CompareOptions.Ordinal);
#endif
}
catch(Exception ex)
......@@ -716,7 +716,7 @@ public bool TryParse(out double val)
internal static class ReflectionExtensions
{
#if DNXCORE50
#if CORE_CLR
internal static TypeCode GetTypeCode(this Type type)
{
if (type == null) return TypeCode.Empty;
......
......@@ -313,7 +313,7 @@ static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool, ref Loc
LocalBuilder redisKeyLoc = null;
var loc = il.DeclareLocal(t);
il.Emit(OpCodes.Ldarg_0); // object
#if !DNXCORE50
#if !CORE_CLR
if (t.IsValueType)
#else
if (t.GetTypeInfo().IsValueType)
......@@ -348,7 +348,7 @@ static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool, ref Loc
{
il.Emit(OpCodes.Dup); // RedisKey[] RedisKey[]
il.Emit(OpCodes.Ldc_I4, i); // RedisKey[] RedisKey[] int
#if !DNXCORE50
#if !CORE_CLR
if (t.IsValueType)
#else
if (t.GetTypeInfo().IsValueType)
......@@ -380,7 +380,7 @@ static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool, ref Loc
{
il.Emit(OpCodes.Dup); // RedisKey[] RedisValue[] RedisValue[]
il.Emit(OpCodes.Ldc_I4, i); // RedisKey[] RedisValue[] RedisValue[] int
#if !DNXCORE50
#if !CORE_CLR
if (t.IsValueType)
#else
if (t.GetTypeInfo().IsValueType)
......
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace StackExchange.Redis
{
[Flags]
internal enum UnselectableFlags
{
None = 0,
RedundantMaster = 1,
DidNotRespond = 2,
ServerType = 4
}
internal sealed partial class ServerEndPoint : IDisposable
{
internal volatile ServerEndPoint Master;
internal volatile ServerEndPoint[] Slaves = NoSlaves;
private static readonly Regex nameSanitizer = new Regex("[^!-~]", InternalRegexCompiledOption.Default);
private static readonly ServerEndPoint[] NoSlaves = new ServerEndPoint[0];
private readonly EndPoint endpoint;
private readonly Hashtable knownScripts = new Hashtable(StringComparer.Ordinal);
private readonly ConnectionMultiplexer multiplexer;
private int databases, writeEverySeconds;
private PhysicalBridge interactive, subscription;
bool isDisposed;
ServerType serverType;
private bool slaveReadOnly, isSlave;
private volatile UnselectableFlags unselectableReasons;
private Version version;
internal void ResetNonConnected()
{
var tmp = interactive;
if (tmp != null) tmp.ResetNonConnected();
tmp = subscription;
if (tmp != null) tmp.ResetNonConnected();
}
public ServerEndPoint(ConnectionMultiplexer multiplexer, EndPoint endpoint, TextWriter log)
{
this.multiplexer = multiplexer;
this.endpoint = endpoint;
var config = multiplexer.RawConfig;
version = config.DefaultVersion;
slaveReadOnly = true;
isSlave = false;
databases = 0;
writeEverySeconds = config.KeepAlive > 0 ? config.KeepAlive : 60;
interactive = CreateBridge(ConnectionType.Interactive, log);
serverType = ServerType.Standalone;
// overrides for twemproxy
if (multiplexer.RawConfig.Proxy == Proxy.Twemproxy)
{
databases = 1;
serverType = ServerType.Twemproxy;
}
}
public ClusterConfiguration ClusterConfiguration { get; private set; }
public int Databases { get { return databases; } set { SetConfig(ref databases, value); } }
public EndPoint EndPoint { get { return endpoint; } }
public bool HasDatabases { get { return serverType == ServerType.Standalone; } }
public bool IsConnected
{
get
{
var tmp = interactive;
return tmp != null && tmp.IsConnected;
}
}
public bool IsSlave { get { return isSlave; } set { SetConfig(ref isSlave, value); } }
public long OperationCount
{
get
{
long total = 0;
var tmp = interactive;
if (tmp != null) total += tmp.OperationCount;
tmp = subscription;
if (tmp != null) total += tmp.OperationCount;
return total;
}
}
public bool RequiresReadMode { get { return serverType == ServerType.Cluster && IsSlave; } }
public ServerType ServerType { get { return serverType; } set { SetConfig(ref serverType, value); } }
public bool SlaveReadOnly { get { return slaveReadOnly; } set { SetConfig(ref slaveReadOnly, value); } }
public bool AllowSlaveWrites { get; set; }
public Version Version { get { return version; } set { SetConfig(ref version, value); } }
public int WriteEverySeconds { get { return writeEverySeconds; } set { SetConfig(ref writeEverySeconds, value); } }
internal ConnectionMultiplexer Multiplexer { get { return multiplexer; } }
public void ClearUnselectable(UnselectableFlags flags)
{
var oldFlags = unselectableReasons;
if (oldFlags != 0)
{
unselectableReasons &= ~flags;
if (unselectableReasons != oldFlags)
{
multiplexer.Trace(unselectableReasons == 0 ? "Now usable" : ("Now unusable: " + flags), ToString());
}
}
}
public void Dispose()
{
isDisposed = true;
var tmp = interactive;
interactive = null;
if (tmp != null) tmp.Dispose();
tmp = subscription;
subscription = null;
if (tmp != null) tmp.Dispose();
}
public PhysicalBridge GetBridge(ConnectionType type, bool create = true, TextWriter log = null)
{
if (isDisposed) return null;
switch (type)
{
case ConnectionType.Interactive:
return interactive ?? (create ? interactive = CreateBridge(ConnectionType.Interactive, log) : null);
case ConnectionType.Subscription:
return subscription ?? (create ? subscription = CreateBridge(ConnectionType.Subscription, log) : null);
}
return null;
}
public PhysicalBridge GetBridge(RedisCommand command, bool create = true)
{
if (isDisposed) return null;
switch (command)
{
case RedisCommand.SUBSCRIBE:
case RedisCommand.UNSUBSCRIBE:
case RedisCommand.PSUBSCRIBE:
case RedisCommand.PUNSUBSCRIBE:
return subscription ?? (create ? subscription = CreateBridge(ConnectionType.Subscription, null) : null);
default:
return interactive;
}
}
public RedisFeatures GetFeatures()
{
return new RedisFeatures(version);
}
public void SetClusterConfiguration(ClusterConfiguration configuration)
{
ClusterConfiguration = configuration;
if (configuration != null)
{
multiplexer.Trace("Updating cluster ranges...");
multiplexer.UpdateClusterRange(configuration);
multiplexer.Trace("Resolving genealogy...");
var thisNode = configuration.Nodes.FirstOrDefault(x => x.EndPoint == this.EndPoint);
if (thisNode != null)
{
List<ServerEndPoint> slaves = null;
ServerEndPoint master = null;
foreach (var node in configuration.Nodes)
{
if (node.NodeId == thisNode.ParentNodeId)
{
master = multiplexer.GetServerEndPoint(node.EndPoint);
}
else if (node.ParentNodeId == thisNode.NodeId)
{
if (slaves == null) slaves = new List<ServerEndPoint>();
slaves.Add(multiplexer.GetServerEndPoint(node.EndPoint));
}
}
Master = master;
Slaves = slaves == null ? NoSlaves : slaves.ToArray();
}
multiplexer.Trace("Cluster configured");
}
}
public void SetUnselectable(UnselectableFlags flags)
{
if (flags != 0)
{
var oldFlags = unselectableReasons;
unselectableReasons |= flags;
if (unselectableReasons != oldFlags)
{
multiplexer.Trace(unselectableReasons == 0 ? "Now usable" : ("Now unusable: " + flags), ToString());
}
}
}
public override string ToString()
{
return Format.ToString(EndPoint);
}
public bool TryEnqueue(Message message)
{
var bridge = GetBridge(message.Command);
return bridge != null && bridge.TryEnqueue(message, isSlave);
}
internal void Activate(ConnectionType type, TextWriter log)
{
GetBridge(type, true, log);
}
internal void AddScript(string script, byte[] hash)
{
lock (knownScripts)
{
knownScripts[script] = hash;
}
}
internal void AutoConfigure(PhysicalConnection connection)
{
if (serverType == ServerType.Twemproxy)
{
// don't try to detect configuration; all the config commands are disabled, and
// the fallback master/slave detection won't help
return;
}
var commandMap = multiplexer.CommandMap;
const CommandFlags flags = CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect;
var features = GetFeatures();
Message msg;
if (commandMap.IsAvailable(RedisCommand.CONFIG))
{
if (multiplexer.RawConfig.KeepAlive <= 0)
{
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.timeout);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.slave_read_only);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.databases);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
if (commandMap.IsAvailable(RedisCommand.INFO))
{
lastInfoReplicationCheckTicks = Environment.TickCount;
if (features.InfoSections)
{
msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.replication);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.server);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
else
{
msg = Message.Create(-1, flags, RedisCommand.INFO);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
}
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...
RedisKey key = Guid.NewGuid().ToByteArray();
msg = Message.Create(0, flags, RedisCommand.SET, key, RedisLiterals.slave_read_only, RedisLiterals.PX, 1, RedisLiterals.NX);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
if (commandMap.IsAvailable(RedisCommand.CLUSTER))
{
msg = Message.Create(-1, flags, RedisCommand.CLUSTER, RedisLiterals.NODES);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.ClusterNodes);
}
}
internal Task Close()
{
var tmp = interactive;
Task result;
if (tmp == null || !tmp.IsConnected || !multiplexer.CommandMap.IsAvailable(RedisCommand.QUIT))
{
result = CompletedTask<bool>.Default(null);
}
else
{
result = QueueDirectAsync(Message.Create(-1, CommandFlags.None, RedisCommand.QUIT), ResultProcessor.DemandOK, bridge: interactive);
}
return result;
}
internal void FlushScriptCache()
{
lock (knownScripts)
{
knownScripts.Clear();
}
}
private string runId;
internal string RunId
{
get { return runId; }
set
{
if (value != runId) // we only care about changes
{
// if we had an old run-id, and it has changed, then the
// server has been restarted; which means the script cache
// is toast
if (runId != null) FlushScriptCache();
runId = value;
}
}
}
internal ServerCounters GetCounters()
{
var counters = new ServerCounters(endpoint);
var tmp = interactive;
if (tmp != null) tmp.GetCounters(counters.Interactive);
tmp = subscription;
if (tmp != null) tmp.GetCounters(counters.Subscription);
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)
{
var bridge = GetBridge(command, false);
if (bridge == null)
{
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);
}
internal string GetProfile()
{
var sb = new StringBuilder();
sb.Append("Circular op-count snapshot; int:");
var tmp = interactive;
if (tmp != null) tmp.AppendProfile(sb);
sb.Append("; sub:");
tmp = subscription;
if (tmp != null) tmp.AppendProfile(sb);
return sb.ToString();
}
internal byte[] GetScriptHash(string script, RedisCommand command)
{
var found = (byte[])knownScripts[script];
if(found == null && command == RedisCommand.EVALSHA)
{
// the script provided is a hex sha; store and re-use the ascii for that
found = Encoding.ASCII.GetBytes(script);
lock(knownScripts)
{
knownScripts[script] = found;
}
}
return found;
}
internal string GetStormLog(RedisCommand command)
{
var bridge = GetBridge(command);
return bridge == null ? null : bridge.GetStormLog();
}
internal Message GetTracerMessage(bool assertIdentity)
{
// different configurations block certain commands, as can ad-hoc local configurations, so
// 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
// see also: TracerProcessor
var map = multiplexer.CommandMap;
Message msg;
const CommandFlags flags = CommandFlags.NoRedirect | CommandFlags.FireAndForget;
if (assertIdentity && map.IsAvailable(RedisCommand.ECHO))
{
msg = Message.Create(-1, flags, RedisCommand.ECHO, (RedisValue)multiplexer.UniqueId);
}
else if (map.IsAvailable(RedisCommand.PING))
{
msg = Message.Create(-1, flags, RedisCommand.PING);
}
else if (map.IsAvailable(RedisCommand.TIME))
{
msg = Message.Create(-1, flags, RedisCommand.TIME);
}
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)
msg = Message.Create(-1, flags, RedisCommand.ECHO, (RedisValue)multiplexer.UniqueId);
}
else
{
map.AssertAvailable(RedisCommand.EXISTS);
msg = Message.Create(0, flags, RedisCommand.EXISTS, (RedisValue)multiplexer.UniqueId);
}
msg.SetInternalCall();
return msg;
}
internal bool IsSelectable(RedisCommand command)
{
var bridge = unselectableReasons == 0 ? GetBridge(command, false) : null;
return bridge != null && bridge.IsConnected;
}
internal void OnEstablishing(PhysicalConnection connection, TextWriter log)
{
try
{
if (connection == null) return;
Handshake(connection, log);
}
catch (Exception ex)
{
connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
}
}
internal void OnFullyEstablished(PhysicalConnection connection)
{
try
{
if (connection == null) return;
var bridge = connection.Bridge;
if (bridge == subscription)
{
multiplexer.ResendSubscriptions(this);
}
multiplexer.OnConnectionRestored(endpoint, bridge.ConnectionType);
}
catch (Exception ex)
{
connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
}
}
internal int LastInfoReplicationCheckSecondsAgo
{
get { return unchecked(Environment.TickCount - VolatileWrapper.Read(ref lastInfoReplicationCheckTicks)) / 1000; }
}
private EndPoint masterEndPoint;
public EndPoint MasterEndPoint
{
get { return masterEndPoint; }
set { SetConfig(ref masterEndPoint, value); }
}
internal bool CheckInfoReplication()
{
lastInfoReplicationCheckTicks = Environment.TickCount;
PhysicalBridge bridge;
if (version >= RedisFeatures.v2_8_0 && multiplexer.CommandMap.IsAvailable(RedisCommand.INFO)
&& (bridge = GetBridge(ConnectionType.Interactive, false)) != null)
{
var msg = Message.Create(-1, CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect, RedisCommand.INFO, RedisLiterals.replication);
msg.SetInternalCall();
QueueDirectFireAndForget(msg, ResultProcessor.AutoConfigure, bridge);
return true;
}
return false;
}
private int lastInfoReplicationCheckTicks;
internal void OnHeartbeat()
{
try
{
var tmp = interactive;
if (tmp != null) tmp.OnHeartbeat(false);
tmp = subscription;
if (tmp != null) tmp.OnHeartbeat(false);
} catch(Exception ex)
{
multiplexer.OnInternalError(ex, EndPoint);
}
}
internal Task<T> QueueDirectAsync<T>(Message message, ResultProcessor<T> processor, object asyncState = null, PhysicalBridge bridge = null)
{
var tcs = TaskSource.CreateDenyExecSync<T>(asyncState);
var source = ResultBox<T>.Get(tcs);
message.SetSource(processor, source);
if (bridge == null) bridge = GetBridge(message.Command);
if (!bridge.TryEnqueue(message, isSlave))
{
ConnectionMultiplexer.ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(multiplexer.IncludeDetailInExceptions, message.Command, message, this));
}
return tcs.Task;
}
internal void QueueDirectFireAndForget<T>(Message message, ResultProcessor<T> processor, PhysicalBridge bridge = null)
{
if (message != null)
{
message.SetSource(processor, null);
multiplexer.Trace("Enqueue: " + message);
(bridge ?? GetBridge(message.Command)).TryEnqueue(message, isSlave);
}
}
internal void ReportNextFailure()
{
var tmp = interactive;
if (tmp != null) tmp.ReportNextFailure();
tmp = subscription;
if (tmp != null) tmp.ReportNextFailure();
}
internal Task<bool> SendTracer(TextWriter log = null)
{
var msg = GetTracerMessage(false);
msg = LoggingMessage.Create(log, msg);
return QueueDirectAsync(msg, ResultProcessor.Tracer);
}
internal string Summary()
{
var sb = new StringBuilder(Format.ToString(endpoint))
.Append(": ").Append(serverType).Append(" v").Append(version).Append(", ").Append(isSlave ? "slave" : "master");
if (databases > 0) sb.Append("; ").Append(databases).Append(" databases");
if (writeEverySeconds > 0)
sb.Append("; keep-alive: ").Append(TimeSpan.FromSeconds(writeEverySeconds));
var tmp = interactive;
sb.Append("; int: ").Append(tmp == null ? "n/a" : tmp.ConnectionState.ToString());
tmp = subscription;
if(tmp == null)
{
sb.Append("; sub: n/a");
} else
{
var state = tmp.ConnectionState;
sb.Append("; sub: ").Append(state);
if(state == PhysicalBridge.State.ConnectedEstablished)
{
sb.Append(", ").Append(tmp.SubscriptionCount).Append(" active");
}
}
var flags = unselectableReasons;
if (flags != 0)
{
sb.Append("; not in use: ").Append(flags);
}
return sb.ToString();
}
internal void WriteDirectOrQueueFireAndForget<T>(PhysicalConnection connection, Message message, ResultProcessor<T> processor)
{
if (message != null)
{
message.SetSource(processor, null);
if (connection == null)
{
multiplexer.Trace("Enqueue: " + message);
GetBridge(message.Command).TryEnqueue(message, isSlave);
}
else
{
multiplexer.Trace("Writing direct: " + message);
connection.Bridge.WriteMessageDirect(connection, message);
}
}
}
private PhysicalBridge CreateBridge(ConnectionType type, TextWriter log)
{
multiplexer.Trace(type.ToString());
var bridge = new PhysicalBridge(this, type);
bridge.TryConnect(log);
return bridge;
}
void Handshake(PhysicalConnection connection, TextWriter log)
{
multiplexer.LogLocked(log, "Server handshake");
if (connection == null)
{
multiplexer.Trace("No connection!?");
return;
}
Message msg;
string password = multiplexer.RawConfig.Password;
if (!string.IsNullOrWhiteSpace(password))
{
multiplexer.LogLocked(log, "Authenticating (password)");
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.AUTH, (RedisValue)password);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.DemandOK);
}
if (multiplexer.CommandMap.IsAvailable(RedisCommand.CLIENT))
{
string name = multiplexer.ClientName;
if (!string.IsNullOrWhiteSpace(name))
{
name = nameSanitizer.Replace(name, "");
if (!string.IsNullOrWhiteSpace(name))
{
multiplexer.LogLocked(log, "Setting client name: {0}", name);
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.CLIENT, RedisLiterals.SETNAME, (RedisValue)name);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.DemandOK);
}
}
}
var connType = connection.Bridge.ConnectionType;
if (connType == ConnectionType.Interactive)
{
multiplexer.LogLocked(log, "Auto-configure...");
AutoConfigure(connection);
}
multiplexer.LogLocked(log, "Sending critical tracer: {0}", connection.Bridge);
var tracer = GetTracerMessage(true);
tracer = LoggingMessage.Create(log, tracer);
WriteDirectOrQueueFireAndForget(connection, tracer, ResultProcessor.EstablishConnection);
// 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
if (connType == ConnectionType.Subscription)
{
var configChannel = multiplexer.ConfigurationChangedChannel;
if(configChannel != null)
{
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.SUBSCRIBE, (RedisChannel)configChannel);
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.TrackSubscriptions);
}
}
multiplexer.LogLocked(log, "Flushing outbound buffer");
connection.Flush();
}
private void SetConfig<T>(ref T field, T value, [CallerMemberName] string caller = null)
{
if(!EqualityComparer<T>.Default.Equals(field, value))
{
multiplexer.Trace(caller + " changed from " + field + " to " + value, "Configuration");
field = value;
multiplexer.ReconfigureIfNeeded(endpoint, false, caller);
}
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace StackExchange.Redis
{
[Flags]
internal enum UnselectableFlags
{
None = 0,
RedundantMaster = 1,
DidNotRespond = 2,
ServerType = 4
}
internal sealed partial class ServerEndPoint : IDisposable
{
internal volatile ServerEndPoint Master;
internal volatile ServerEndPoint[] Slaves = NoSlaves;
private static readonly Regex nameSanitizer = new Regex("[^!-~]", InternalRegexCompiledOption.Default);
private static readonly ServerEndPoint[] NoSlaves = new ServerEndPoint[0];
private readonly EndPoint endpoint;
private readonly Hashtable knownScripts = new Hashtable(StringComparer.Ordinal);
private readonly ConnectionMultiplexer multiplexer;
private int databases, writeEverySeconds;
private PhysicalBridge interactive, subscription;
bool isDisposed;
ServerType serverType;
private bool slaveReadOnly, isSlave;
private volatile UnselectableFlags unselectableReasons;
private Version version;
internal void ResetNonConnected()
{
var tmp = interactive;
if (tmp != null) tmp.ResetNonConnected();
tmp = subscription;
if (tmp != null) tmp.ResetNonConnected();
}
public ServerEndPoint(ConnectionMultiplexer multiplexer, EndPoint endpoint, TextWriter log)
{
this.multiplexer = multiplexer;
this.endpoint = endpoint;
var config = multiplexer.RawConfig;
version = config.DefaultVersion;
slaveReadOnly = true;
isSlave = false;
databases = 0;
writeEverySeconds = config.KeepAlive > 0 ? config.KeepAlive : 60;
interactive = CreateBridge(ConnectionType.Interactive, log);
serverType = ServerType.Standalone;
// overrides for twemproxy
if (multiplexer.RawConfig.Proxy == Proxy.Twemproxy)
{
databases = 1;
serverType = ServerType.Twemproxy;
}
}
public ClusterConfiguration ClusterConfiguration { get; private set; }
public int Databases { get { return databases; } set { SetConfig(ref databases, value); } }
public EndPoint EndPoint { get { return endpoint; } }
public bool HasDatabases { get { return serverType == ServerType.Standalone; } }
public bool IsConnected
{
get
{
var tmp = interactive;
return tmp != null && tmp.IsConnected;
}
}
public bool IsSlave { get { return isSlave; } set { SetConfig(ref isSlave, value); } }
public long OperationCount
{
get
{
long total = 0;
var tmp = interactive;
if (tmp != null) total += tmp.OperationCount;
tmp = subscription;
if (tmp != null) total += tmp.OperationCount;
return total;
}
}
public bool RequiresReadMode { get { return serverType == ServerType.Cluster && IsSlave; } }
public ServerType ServerType { get { return serverType; } set { SetConfig(ref serverType, value); } }
public bool SlaveReadOnly { get { return slaveReadOnly; } set { SetConfig(ref slaveReadOnly, value); } }
public bool AllowSlaveWrites { get; set; }
public Version Version { get { return version; } set { SetConfig(ref version, value); } }
public int WriteEverySeconds { get { return writeEverySeconds; } set { SetConfig(ref writeEverySeconds, value); } }
internal ConnectionMultiplexer Multiplexer { get { return multiplexer; } }
public void ClearUnselectable(UnselectableFlags flags)
{
var oldFlags = unselectableReasons;
if (oldFlags != 0)
{
unselectableReasons &= ~flags;
if (unselectableReasons != oldFlags)
{
multiplexer.Trace(unselectableReasons == 0 ? "Now usable" : ("Now unusable: " + flags), ToString());
}
}
}
public void Dispose()
{
isDisposed = true;
var tmp = interactive;
interactive = null;
if (tmp != null) tmp.Dispose();
tmp = subscription;
subscription = null;
if (tmp != null) tmp.Dispose();
}
public PhysicalBridge GetBridge(ConnectionType type, bool create = true, TextWriter log = null)
{
if (isDisposed) return null;
switch (type)
{
case ConnectionType.Interactive:
return interactive ?? (create ? interactive = CreateBridge(ConnectionType.Interactive, log) : null);
case ConnectionType.Subscription:
return subscription ?? (create ? subscription = CreateBridge(ConnectionType.Subscription, log) : null);
}
return null;
}
public PhysicalBridge GetBridge(RedisCommand command, bool create = true)
{
if (isDisposed) return null;
switch (command)
{
case RedisCommand.SUBSCRIBE:
case RedisCommand.UNSUBSCRIBE:
case RedisCommand.PSUBSCRIBE:
case RedisCommand.PUNSUBSCRIBE:
return subscription ?? (create ? subscription = CreateBridge(ConnectionType.Subscription, null) : null);
default:
return interactive;
}
}
public RedisFeatures GetFeatures()
{
return new RedisFeatures(version);
}
public void SetClusterConfiguration(ClusterConfiguration configuration)
{
ClusterConfiguration = configuration;
if (configuration != null)
{
multiplexer.Trace("Updating cluster ranges...");
multiplexer.UpdateClusterRange(configuration);
multiplexer.Trace("Resolving genealogy...");
var thisNode = configuration.Nodes.FirstOrDefault(x => x.EndPoint == this.EndPoint);
if (thisNode != null)
{
List<ServerEndPoint> slaves = null;
ServerEndPoint master = null;
foreach (var node in configuration.Nodes)
{
if (node.NodeId == thisNode.ParentNodeId)
{
master = multiplexer.GetServerEndPoint(node.EndPoint);
}
else if (node.ParentNodeId == thisNode.NodeId)
{
if (slaves == null) slaves = new List<ServerEndPoint>();
slaves.Add(multiplexer.GetServerEndPoint(node.EndPoint));
}
}
Master = master;
Slaves = slaves == null ? NoSlaves : slaves.ToArray();
}
multiplexer.Trace("Cluster configured");
}
}
public void SetUnselectable(UnselectableFlags flags)
{
if (flags != 0)
{
var oldFlags = unselectableReasons;
unselectableReasons |= flags;
if (unselectableReasons != oldFlags)
{
multiplexer.Trace(unselectableReasons == 0 ? "Now usable" : ("Now unusable: " + flags), ToString());
}
}
}
public override string ToString()
{
return Format.ToString(EndPoint);
}
public bool TryEnqueue(Message message)
{
var bridge = GetBridge(message.Command);
return bridge != null && bridge.TryEnqueue(message, isSlave);
}
internal void Activate(ConnectionType type, TextWriter log)
{
GetBridge(type, true, log);
}
internal void AddScript(string script, byte[] hash)
{
lock (knownScripts)
{
knownScripts[script] = hash;
}
}
internal void AutoConfigure(PhysicalConnection connection)
{
if (serverType == ServerType.Twemproxy)
{
// don't try to detect configuration; all the config commands are disabled, and
// the fallback master/slave detection won't help
return;
}
var commandMap = multiplexer.CommandMap;
const CommandFlags flags = CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect;
var features = GetFeatures();
Message msg;
if (commandMap.IsAvailable(RedisCommand.CONFIG))
{
if (multiplexer.RawConfig.KeepAlive <= 0)
{
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.timeout);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.slave_read_only);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
msg = Message.Create(-1, flags, RedisCommand.CONFIG, RedisLiterals.GET, RedisLiterals.databases);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
if (commandMap.IsAvailable(RedisCommand.INFO))
{
lastInfoReplicationCheckTicks = Environment.TickCount;
if (features.InfoSections)
{
msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.replication);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
msg = Message.Create(-1, flags, RedisCommand.INFO, RedisLiterals.server);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
else
{
msg = Message.Create(-1, flags, RedisCommand.INFO);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
}
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...
RedisKey key = Guid.NewGuid().ToByteArray();
msg = Message.Create(0, flags, RedisCommand.SET, key, RedisLiterals.slave_read_only, RedisLiterals.PX, 1, RedisLiterals.NX);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.AutoConfigure);
}
if (commandMap.IsAvailable(RedisCommand.CLUSTER))
{
msg = Message.Create(-1, flags, RedisCommand.CLUSTER, RedisLiterals.NODES);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.ClusterNodes);
}
}
internal Task Close()
{
var tmp = interactive;
Task result;
if (tmp == null || !tmp.IsConnected || !multiplexer.CommandMap.IsAvailable(RedisCommand.QUIT))
{
result = CompletedTask<bool>.Default(null);
}
else
{
result = QueueDirectAsync(Message.Create(-1, CommandFlags.None, RedisCommand.QUIT), ResultProcessor.DemandOK, bridge: interactive);
}
return result;
}
internal void FlushScriptCache()
{
lock (knownScripts)
{
knownScripts.Clear();
}
}
private string runId;
internal string RunId
{
get { return runId; }
set
{
if (value != runId) // we only care about changes
{
// if we had an old run-id, and it has changed, then the
// server has been restarted; which means the script cache
// is toast
if (runId != null) FlushScriptCache();
runId = value;
}
}
}
internal ServerCounters GetCounters()
{
var counters = new ServerCounters(endpoint);
var tmp = interactive;
if (tmp != null) tmp.GetCounters(counters.Interactive);
tmp = subscription;
if (tmp != null) tmp.GetCounters(counters.Subscription);
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)
{
var bridge = GetBridge(command, false);
if (bridge == null)
{
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);
}
internal string GetProfile()
{
var sb = new StringBuilder();
sb.Append("Circular op-count snapshot; int:");
var tmp = interactive;
if (tmp != null) tmp.AppendProfile(sb);
sb.Append("; sub:");
tmp = subscription;
if (tmp != null) tmp.AppendProfile(sb);
return sb.ToString();
}
internal byte[] GetScriptHash(string script, RedisCommand command)
{
var found = (byte[])knownScripts[script];
if(found == null && command == RedisCommand.EVALSHA)
{
// the script provided is a hex sha; store and re-use the ascii for that
found = Encoding.ASCII.GetBytes(script);
lock(knownScripts)
{
knownScripts[script] = found;
}
}
return found;
}
internal string GetStormLog(RedisCommand command)
{
var bridge = GetBridge(command);
return bridge == null ? null : bridge.GetStormLog();
}
internal Message GetTracerMessage(bool assertIdentity)
{
// different configurations block certain commands, as can ad-hoc local configurations, so
// 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
// see also: TracerProcessor
var map = multiplexer.CommandMap;
Message msg;
const CommandFlags flags = CommandFlags.NoRedirect | CommandFlags.FireAndForget;
if (assertIdentity && map.IsAvailable(RedisCommand.ECHO))
{
msg = Message.Create(-1, flags, RedisCommand.ECHO, (RedisValue)multiplexer.UniqueId);
}
else if (map.IsAvailable(RedisCommand.PING))
{
msg = Message.Create(-1, flags, RedisCommand.PING);
}
else if (map.IsAvailable(RedisCommand.TIME))
{
msg = Message.Create(-1, flags, RedisCommand.TIME);
}
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)
msg = Message.Create(-1, flags, RedisCommand.ECHO, (RedisValue)multiplexer.UniqueId);
}
else
{
map.AssertAvailable(RedisCommand.EXISTS);
msg = Message.Create(0, flags, RedisCommand.EXISTS, (RedisValue)multiplexer.UniqueId);
}
msg.SetInternalCall();
return msg;
}
internal bool IsSelectable(RedisCommand command)
{
var bridge = unselectableReasons == 0 ? GetBridge(command, false) : null;
return bridge != null && bridge.IsConnected;
}
internal void OnEstablishing(PhysicalConnection connection, TextWriter log)
{
try
{
if (connection == null) return;
Handshake(connection, log);
}
catch (Exception ex)
{
connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
}
}
internal void OnFullyEstablished(PhysicalConnection connection)
{
try
{
if (connection == null) return;
var bridge = connection.Bridge;
if (bridge == subscription)
{
multiplexer.ResendSubscriptions(this);
}
multiplexer.OnConnectionRestored(endpoint, bridge.ConnectionType);
}
catch (Exception ex)
{
connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
}
}
internal int LastInfoReplicationCheckSecondsAgo
{
get { return unchecked(Environment.TickCount - VolatileWrapper.Read(ref lastInfoReplicationCheckTicks)) / 1000; }
}
private EndPoint masterEndPoint;
public EndPoint MasterEndPoint
{
get { return masterEndPoint; }
set { SetConfig(ref masterEndPoint, value); }
}
internal bool CheckInfoReplication()
{
lastInfoReplicationCheckTicks = Environment.TickCount;
PhysicalBridge bridge;
if (version >= RedisFeatures.v2_8_0 && multiplexer.CommandMap.IsAvailable(RedisCommand.INFO)
&& (bridge = GetBridge(ConnectionType.Interactive, false)) != null)
{
var msg = Message.Create(-1, CommandFlags.FireAndForget | CommandFlags.HighPriority | CommandFlags.NoRedirect, RedisCommand.INFO, RedisLiterals.replication);
msg.SetInternalCall();
QueueDirectFireAndForget(msg, ResultProcessor.AutoConfigure, bridge);
return true;
}
return false;
}
private int lastInfoReplicationCheckTicks;
internal void OnHeartbeat()
{
try
{
var tmp = interactive;
if (tmp != null) tmp.OnHeartbeat(false);
tmp = subscription;
if (tmp != null) tmp.OnHeartbeat(false);
} catch(Exception ex)
{
multiplexer.OnInternalError(ex, EndPoint);
}
}
internal Task<T> QueueDirectAsync<T>(Message message, ResultProcessor<T> processor, object asyncState = null, PhysicalBridge bridge = null)
{
var tcs = TaskSource.CreateDenyExecSync<T>(asyncState);
var source = ResultBox<T>.Get(tcs);
message.SetSource(processor, source);
if (bridge == null) bridge = GetBridge(message.Command);
if (!bridge.TryEnqueue(message, isSlave))
{
ConnectionMultiplexer.ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(multiplexer.IncludeDetailInExceptions, message.Command, message, this));
}
return tcs.Task;
}
internal void QueueDirectFireAndForget<T>(Message message, ResultProcessor<T> processor, PhysicalBridge bridge = null)
{
if (message != null)
{
message.SetSource(processor, null);
multiplexer.Trace("Enqueue: " + message);
(bridge ?? GetBridge(message.Command)).TryEnqueue(message, isSlave);
}
}
internal void ReportNextFailure()
{
var tmp = interactive;
if (tmp != null) tmp.ReportNextFailure();
tmp = subscription;
if (tmp != null) tmp.ReportNextFailure();
}
internal Task<bool> SendTracer(TextWriter log = null)
{
var msg = GetTracerMessage(false);
msg = LoggingMessage.Create(log, msg);
return QueueDirectAsync(msg, ResultProcessor.Tracer);
}
internal string Summary()
{
var sb = new StringBuilder(Format.ToString(endpoint))
.Append(": ").Append(serverType).Append(" v").Append(version).Append(", ").Append(isSlave ? "slave" : "master");
if (databases > 0) sb.Append("; ").Append(databases).Append(" databases");
if (writeEverySeconds > 0)
sb.Append("; keep-alive: ").Append(TimeSpan.FromSeconds(writeEverySeconds));
var tmp = interactive;
sb.Append("; int: ").Append(tmp == null ? "n/a" : tmp.ConnectionState.ToString());
tmp = subscription;
if(tmp == null)
{
sb.Append("; sub: n/a");
} else
{
var state = tmp.ConnectionState;
sb.Append("; sub: ").Append(state);
if(state == PhysicalBridge.State.ConnectedEstablished)
{
sb.Append(", ").Append(tmp.SubscriptionCount).Append(" active");
}
}
var flags = unselectableReasons;
if (flags != 0)
{
sb.Append("; not in use: ").Append(flags);
}
return sb.ToString();
}
internal void WriteDirectOrQueueFireAndForget<T>(PhysicalConnection connection, Message message, ResultProcessor<T> processor)
{
if (message != null)
{
message.SetSource(processor, null);
if (connection == null)
{
multiplexer.Trace("Enqueue: " + message);
GetBridge(message.Command).TryEnqueue(message, isSlave);
}
else
{
multiplexer.Trace("Writing direct: " + message);
connection.Bridge.WriteMessageDirect(connection, message);
}
}
}
private PhysicalBridge CreateBridge(ConnectionType type, TextWriter log)
{
multiplexer.Trace(type.ToString());
var bridge = new PhysicalBridge(this, type);
bridge.TryConnect(log);
return bridge;
}
void Handshake(PhysicalConnection connection, TextWriter log)
{
multiplexer.LogLocked(log, "Server handshake");
if (connection == null)
{
multiplexer.Trace("No connection!?");
return;
}
Message msg;
string password = multiplexer.RawConfig.Password;
if (!string.IsNullOrWhiteSpace(password))
{
multiplexer.LogLocked(log, "Authenticating (password)");
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.AUTH, (RedisValue)password);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.DemandOK);
}
if (multiplexer.CommandMap.IsAvailable(RedisCommand.CLIENT))
{
string name = multiplexer.ClientName;
if (!string.IsNullOrWhiteSpace(name))
{
name = nameSanitizer.Replace(name, "");
if (!string.IsNullOrWhiteSpace(name))
{
multiplexer.LogLocked(log, "Setting client name: {0}", name);
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.CLIENT, RedisLiterals.SETNAME, (RedisValue)name);
msg.SetInternalCall();
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.DemandOK);
}
}
}
var connType = connection.Bridge.ConnectionType;
if (connType == ConnectionType.Interactive)
{
multiplexer.LogLocked(log, "Auto-configure...");
AutoConfigure(connection);
}
multiplexer.LogLocked(log, "Sending critical tracer: {0}", connection.Bridge);
var tracer = GetTracerMessage(true);
tracer = LoggingMessage.Create(log, tracer);
WriteDirectOrQueueFireAndForget(connection, tracer, ResultProcessor.EstablishConnection);
// 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
if (connType == ConnectionType.Subscription)
{
var configChannel = multiplexer.ConfigurationChangedChannel;
if(configChannel != null)
{
msg = Message.Create(-1, CommandFlags.FireAndForget, RedisCommand.SUBSCRIBE, (RedisChannel)configChannel);
WriteDirectOrQueueFireAndForget(connection, msg, ResultProcessor.TrackSubscriptions);
}
}
multiplexer.LogLocked(log, "Flushing outbound buffer");
connection.Flush();
}
private void SetConfig<T>(ref T field, T value, [CallerMemberName] string caller = null)
{
if(!EqualityComparer<T>.Default.Equals(field, value))
{
multiplexer.Trace(caller + " changed from " + field + " to " + value, "Configuration");
field = value;
multiplexer.ReconfigureIfNeeded(endpoint, false, caller);
}
}
}
}
......@@ -5,6 +5,7 @@
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
namespace StackExchange.Redis
{
......@@ -126,7 +127,7 @@ public SocketManager(string name = null)
// we need a dedicated writer, because when under heavy ambient load
// (a busy asp.net site, for example), workers are not reliable enough
#if !DNXCORE50
#if !CORE_CLR
Thread dedicatedWriter = new Thread(writeAllQueues, 32 * 1024); // don't need a huge stack;
dedicatedWriter.Priority = ThreadPriority.AboveNormal; // time critical
#else
......@@ -172,37 +173,56 @@ internal SocketToken BeginConnect(EndPoint endpoint, ISocketCallback callback, C
this.ShouldForceConnectCompletionType(ref connectCompletionType);
var formattedEndpoint = Format.ToString(endpoint);
var tuple = Tuple.Create(socket, callback);
if (endpoint is DnsEndPoint)
{
// A work-around for a Mono bug in BeginConnect(EndPoint endpoint, AsyncCallback callback, object state)
DnsEndPoint dnsEndpoint = (DnsEndPoint)endpoint;
#if CORE_CLR
multiplexer.LogLocked(log, "BeginConnect: {0}", formattedEndpoint);
socket.ConnectAsync(dnsEndpoint.Host, dnsEndpoint.Port).ContinueWith(t =>
{
multiplexer.LogLocked(log, "EndConnect: {0}", formattedEndpoint);
EndConnectImpl(t, multiplexer, log, tuple);
multiplexer.LogLocked(log, "Connect complete: {0}", formattedEndpoint);
});
#else
CompletionTypeHelper.RunWithCompletionType(
(cb) =>
{
(cb) => {
multiplexer.LogLocked(log, "BeginConnect: {0}", formattedEndpoint);
return socket.BeginConnect(dnsEndpoint.Host, dnsEndpoint.Port, cb, Tuple.Create(socket, callback));
return socket.BeginConnect(dnsEndpoint.Host, dnsEndpoint.Port, cb, tuple);
},
(ar) =>
{
multiplexer.LogLocked(log, "EndConnect: {0}", formattedEndpoint);
EndConnectImpl(ar, multiplexer, log);
(ar) => {
multiplexer.LogLocked(log, "EndConnect: {0}", formattedEndpoint);
EndConnectImpl(ar, multiplexer, log, tuple);
multiplexer.LogLocked(log, "Connect complete: {0}", formattedEndpoint);
},
connectCompletionType);
#endif
}
else
{
#if CORE_CLR
multiplexer.LogLocked(log, "BeginConnect: {0}", formattedEndpoint);
socket.ConnectAsync(endpoint).ContinueWith(t =>
{
multiplexer.LogLocked(log, "EndConnect: {0}", formattedEndpoint);
EndConnectImpl(t, multiplexer, log, tuple);
});
#else
CompletionTypeHelper.RunWithCompletionType(
(cb) => {
multiplexer.LogLocked(log, "BeginConnect: {0}", formattedEndpoint);
return socket.BeginConnect(endpoint, cb, Tuple.Create(socket, callback));
return socket.BeginConnect(endpoint, cb, tuple);
},
(ar) => {
multiplexer.LogLocked(log, "EndConnect: {0}", formattedEndpoint);
EndConnectImpl(ar, multiplexer, log);
EndConnectImpl(ar, multiplexer, log, tuple);
multiplexer.LogLocked(log, "Connect complete: {0}", formattedEndpoint);
},
connectCompletionType);
#endif
}
}
catch (NotImplementedException ex)
......@@ -221,9 +241,9 @@ internal void SetFastLoopbackOption(Socket socket)
// SIO_LOOPBACK_FAST_PATH (http://msdn.microsoft.com/en-us/library/windows/desktop/jj841212%28v=vs.85%29.aspx)
// Speeds up localhost operations significantly. OK to apply to a socket that will not be hooked up to localhost,
// or will be subject to WFP filtering.
#if !DNXCORE50
const int SIO_LOOPBACK_FAST_PATH = -1744830448;
#if !CORE_CLR
// windows only
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
......@@ -231,8 +251,11 @@ internal void SetFastLoopbackOption(Socket socket)
var osVersion = Environment.OSVersion.Version;
if (osVersion.Major > 6 || osVersion.Major == 6 && osVersion.Minor >= 2)
{
byte[] optionInValue = BitConverter.GetBytes(1);
#endif
byte[] optionInValue = BitConverter.GetBytes(1);
socket.IOControl(SIO_LOOPBACK_FAST_PATH, optionInValue, null);
#if !CORE_CLR
}
}
#endif
......@@ -262,18 +285,20 @@ internal void Shutdown(SocketToken token)
Shutdown(token.Socket);
}
private void EndConnectImpl(IAsyncResult ar, ConnectionMultiplexer multiplexer, TextWriter log)
private void EndConnectImpl(IAsyncResult ar, ConnectionMultiplexer multiplexer, TextWriter log, Tuple<Socket, ISocketCallback> tuple)
{
Tuple<Socket, ISocketCallback> tuple = null;
try
{
tuple = (Tuple<Socket, ISocketCallback>)ar.AsyncState;
bool ignoreConnect = false;
ShouldIgnoreConnect(tuple.Item2, ref ignoreConnect);
if (ignoreConnect) return;
var socket = tuple.Item1;
var callback = tuple.Item2;
#if CORE_CLR
multiplexer.Wait((Task)ar); // make it explode if invalid (note: already complete at this point)
#else
socket.EndConnect(ar);
#endif
var netStream = new NetworkStream(socket, false);
var socketMode = callback == null ? SocketMode.Abort : callback.Connected(netStream, log);
switch (socketMode)
......@@ -298,7 +323,7 @@ private void EndConnectImpl(IAsyncResult ar, ConnectionMultiplexer multiplexer,
break;
}
}
catch(ObjectDisposedException)
catch (ObjectDisposedException)
{
multiplexer.LogLocked(log, "(socket shutdown)");
if (tuple != null)
......@@ -340,7 +365,7 @@ private void Shutdown(Socket socket)
{
OnShutdown(socket);
try { socket.Shutdown(SocketShutdown.Both); } catch { }
#if !DNXCORE50
#if !CORE_CLR
try { socket.Close(); } catch { }
#endif
try { socket.Dispose(); } catch { }
......
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace StackExchange.Redis
{
/// <summary>
/// Describes a sorted-set element with the corresponding value
/// </summary>
public struct SortedSetEntry : IEquatable<SortedSetEntry>, IComparable, IComparable<SortedSetEntry>
{
internal readonly RedisValue element;
internal readonly double score;
/// <summary>
/// Initializes a SortedSetEntry value
/// </summary>
public SortedSetEntry(RedisValue element, double score)
{
this.element = element;
this.score = score;
}
/// <summary>
/// The unique element stored in the sorted set
/// </summary>
public RedisValue Element { get { return element; } }
/// <summary>
/// The score against the element
/// </summary>
public double Score { get { return score; } }
/// <summary>
/// The score against the element
/// </summary>
#if !DNXCORE50
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Score", false)]
public double Value { get { return score; } }
/// <summary>
/// The unique element stored in the sorted set
/// </summary>
#if !DNXCORE50
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Element", false)]
public RedisValue Key { get { return element; } }
/// <summary>
/// Converts to a key/value pair
/// </summary>
public static implicit operator KeyValuePair<RedisValue,double>(SortedSetEntry value)
{
return new KeyValuePair<RedisValue, double>(value.element, value.score);
}
/// <summary>
/// Converts from a key/value pair
/// </summary>
public static implicit operator SortedSetEntry(KeyValuePair<RedisValue, double> value)
{
return new SortedSetEntry(value.Key, value.Value);
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
return element + ": " + score;
}
/// <summary>
/// See Object.GetHashCode()
/// </summary>
public override int GetHashCode()
{
return element.GetHashCode() ^ score.GetHashCode();
}
/// <summary>
/// Compares two values for equality
/// </summary>
public override bool Equals(object obj)
{
return obj is SortedSetEntry && Equals((SortedSetEntry)obj);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public bool Equals(SortedSetEntry value)
{
return this.score == value.score && this.element == value.element;
}
/// <summary>
/// Compares two values by score
/// </summary>
public int CompareTo(SortedSetEntry value)
{
return this.score.CompareTo(value.score);
}
/// <summary>
/// Compares two values by score
/// </summary>
public int CompareTo(object value)
{
return value is SortedSetEntry ? CompareTo((SortedSetEntry)value) : -1;
}
/// <summary>
/// Compares two values for equality
/// </summary>
public static bool operator ==(SortedSetEntry x, SortedSetEntry y)
{
return x.score == y.score && x.element == y.element;
}
/// <summary>
/// Compares two values for non-equality
/// </summary>
public static bool operator !=(SortedSetEntry x, SortedSetEntry y)
{
return x.score != y.score || x.element != y.element;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace StackExchange.Redis
{
/// <summary>
/// Describes a sorted-set element with the corresponding value
/// </summary>
public struct SortedSetEntry : IEquatable<SortedSetEntry>, IComparable, IComparable<SortedSetEntry>
{
internal readonly RedisValue element;
internal readonly double score;
/// <summary>
/// Initializes a SortedSetEntry value
/// </summary>
public SortedSetEntry(RedisValue element, double score)
{
this.element = element;
this.score = score;
}
/// <summary>
/// The unique element stored in the sorted set
/// </summary>
public RedisValue Element { get { return element; } }
/// <summary>
/// The score against the element
/// </summary>
public double Score { get { return score; } }
/// <summary>
/// The score against the element
/// </summary>
#if !CORE_CLR
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Score", false)]
public double Value { get { return score; } }
/// <summary>
/// The unique element stored in the sorted set
/// </summary>
#if !CORE_CLR
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Element", false)]
public RedisValue Key { get { return element; } }
/// <summary>
/// Converts to a key/value pair
/// </summary>
public static implicit operator KeyValuePair<RedisValue,double>(SortedSetEntry value)
{
return new KeyValuePair<RedisValue, double>(value.element, value.score);
}
/// <summary>
/// Converts from a key/value pair
/// </summary>
public static implicit operator SortedSetEntry(KeyValuePair<RedisValue, double> value)
{
return new SortedSetEntry(value.Key, value.Value);
}
/// <summary>
/// See Object.ToString()
/// </summary>
public override string ToString()
{
return element + ": " + score;
}
/// <summary>
/// See Object.GetHashCode()
/// </summary>
public override int GetHashCode()
{
return element.GetHashCode() ^ score.GetHashCode();
}
/// <summary>
/// Compares two values for equality
/// </summary>
public override bool Equals(object obj)
{
return obj is SortedSetEntry && Equals((SortedSetEntry)obj);
}
/// <summary>
/// Compares two values for equality
/// </summary>
public bool Equals(SortedSetEntry value)
{
return this.score == value.score && this.element == value.element;
}
/// <summary>
/// Compares two values by score
/// </summary>
public int CompareTo(SortedSetEntry value)
{
return this.score.CompareTo(value.score);
}
/// <summary>
/// Compares two values by score
/// </summary>
public int CompareTo(object value)
{
return value is SortedSetEntry ? CompareTo((SortedSetEntry)value) : -1;
}
/// <summary>
/// Compares two values for equality
/// </summary>
public static bool operator ==(SortedSetEntry x, SortedSetEntry y)
{
return x.score == y.score && x.element == y.element;
}
/// <summary>
/// Compares two values for non-equality
/// </summary>
public static bool operator !=(SortedSetEntry x, SortedSetEntry y)
{
return x.score != y.score || x.element != y.element;
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Copyright © 2002-2013 Charlie Poole
Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov
Copyright © 2000-2002 Philip A. Craig
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required.
Portions Copyright © 2002-2013 Charlie Poole or Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\..\StackExchange.Redis.Tests\packages.config" />
</repositories>
\ No newline at end of file
{
"version": "1.1.0-alpha1",
"description": "High performance Redis client, incorporating both synchronous and asynchronous usage.",
"authors": [ "Stack Exchange inc., marc.gravell" ],
"owners": [ "marc.gravell" ],
"tags": [ "Async", "Redis", "Cache", "PubSub", "Messaging" ],
"projectUrl": "https://github.com/StackExchange/StackExchange.Redis",
"licenseUrl": "https://raw.github.com/StackExchange/StackExchange.Redis/master/LICENSE",
"copyright": "Stack Exchange inc. 2014-",
"requireLicenseAcceptance": false,
"summary": "Redis client library",
"dependencies": {
},
"compilationOptions": {
"allowUnsafe": true
},
"frameworks": {
"net40": {
"dependencies": {
"Microsoft.Bcl": "1.1.10",
"Microsoft.Bcl.Async": "1.0.168"
}
},
"net45": {
"frameworkAssemblies": {
"System.IO.Compression": "4.0.0.0"
}
},
"net46": {
"frameworkAssemblies": {
"System.IO.Compression": "4.0.0.0"
},
"define": [ "PLAT_SAFE_CONTINUATIONS" ]
},
"dnxcore50": {
"compilationOptions": {
"define": [ "PLAT_SAFE_CONTINUATIONS", "CORE_CLR" ]
},
"dependencies": {
"System.Collections.Concurrent": "4.0.11-beta-23516",
"System.Collections.NonGeneric": "4.0.1-beta-23516",
"System.Diagnostics.Debug": "4.0.11-beta-23516",
"System.Diagnostics.Tools": "4.0.1-beta-23516",
"System.Diagnostics.TraceSource": "4.0.0-beta-23516",
"System.Globalization": "4.0.11-beta-23516",
"System.IO": "4.0.11-beta-23516",
"System.IO.Compression": "4.1.0-beta-23516",
"System.IO.FileSystem": "4.0.1-beta-23516",
"System.Linq": "4.0.1-beta-23516",
"System.Net.NameResolution": "4.0.0-beta-23516",
"System.Net.Primitives": "4.0.11-beta-23516",
"System.Net.Security": "4.0.0-beta-23516",
"System.Net.Sockets": "4.1.0-beta-23516",
"System.Reflection": "4.1.0-beta-23516",
"System.Reflection.Emit": "4.0.1-beta-23516",
"System.Reflection.Emit.Lightweight": "4.0.1-beta-23516",
"System.Reflection.Primitives": "4.0.1-beta-23516",
"System.Reflection.TypeExtensions": "4.1.0-beta-23516",
"System.Security.Cryptography.Algorithms": "4.0.0-beta-23516",
"System.Security.Cryptography.X509Certificates": "4.0.0-beta-23516",
"System.Text.Encoding": "4.0.11-beta-23516",
"System.Text.RegularExpressions": "4.0.11-beta-23516",
"System.Threading": "4.0.11-beta-23516",
"System.Threading.Tasks": "4.0.11-beta-23516",
"System.Threading.Thread": "4.0.0-beta-23516",
"System.Threading.ThreadPool": "4.0.10-beta-23516",
"System.Threading.Timer": "4.0.1-beta-23516"
}
},
"dotnet5.5": {
"compilationOptions": {
"define": [ "PLAT_SAFE_CONTINUATIONS", "CORE_CLR" ]
},
"dependencies": {
"System.Collections.Concurrent": "4.0.11-beta-23516",
"System.Collections.NonGeneric": "4.0.1-beta-23516",
"System.Diagnostics.Debug": "4.0.11-beta-23516",
"System.Diagnostics.Tools": "4.0.1-beta-23516",
"System.Diagnostics.TraceSource": "4.0.0-beta-23516",
"System.Globalization": "4.0.11-beta-23516",
"System.IO": "4.0.11-beta-23516",
"System.IO.Compression": "4.1.0-beta-23516",
"System.IO.FileSystem": "4.0.1-beta-23516",
"System.Linq": "4.0.1-beta-23516",
"System.Net.NameResolution": "4.0.0-beta-23516",
"System.Net.Primitives": "4.0.11-beta-23516",
"System.Net.Security": "4.0.0-beta-23516",
"System.Net.Sockets": "4.1.0-beta-23516",
"System.Reflection": "4.1.0-beta-23516",
"System.Reflection.Emit": "4.0.1-beta-23516",
"System.Reflection.Emit.Lightweight": "4.0.1-beta-23516",
"System.Reflection.Primitives": "4.0.1-beta-23516",
"System.Reflection.TypeExtensions": "4.1.0-beta-23516",
"System.Security.Cryptography.Algorithms": "4.0.0-beta-23516",
"System.Security.Cryptography.X509Certificates": "4.0.0-beta-23516",
"System.Text.Encoding": "4.0.11-beta-23516",
"System.Text.RegularExpressions": "4.0.11-beta-23516",
"System.Threading": "4.0.11-beta-23516",
"System.Threading.Tasks": "4.0.11-beta-23516",
"System.Threading.Thread": "4.0.0-beta-23516",
"System.Threading.ThreadPool": "4.0.10-beta-23516",
"System.Threading.Timer": "4.0.1-beta-23516"
}
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{75CED009-AAC6-4AC1-9C38-A0530619062D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis.StrongName</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseVSHostingProcess>false</UseVSHostingProcess>
<DocumentationFile>bin.snk\Debug\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>StackExchange.Redis.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Runtime">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis\Properties\AssemblyInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Aggregate.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Bitwise.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientType.cs">
<Link>ClientType.cs</Link>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\VolatileWrapper.cs">
<Link>VolatileWrapper.cs</Link>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandMap.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandTrace.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletionManager.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Condition.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Exclude.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExportOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Format.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ICompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IProfiler.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedis.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ISubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ITransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Message.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageQueue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LuaScript.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Order.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RawResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisChannel.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisCommand.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisKey.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisValue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultBox.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SaveType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SetOperation.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ShutdownMode.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.Poll.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\StringSplits.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\TaskSource.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\DatabaseExtension.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\WrapperBase.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="StackExchange.Redis.snk" />
</ItemGroup>
<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')" />
<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="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>
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{75CED009-AAC6-4AC1-9C38-A0530619062D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis.StrongName</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseVSHostingProcess>false</UseVSHostingProcess>
<DocumentationFile>bin.snk\Debug\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>..\StackExchange.Redis.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Runtime">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis\**\*.cs"/>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<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')" />
<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="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>
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{36CAC6B6-2B88-447F-AA35-D4DAA5E4F2C7}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseVSHostingProcess>false</UseVSHostingProcess>
<DocumentationFile>bin\Debug\StackExchange.Redis.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<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>
<Private>True</Private>
</Reference>
<Reference Include="System.Net" />
<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>
<Private>True</Private>
</Reference>
<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>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis\Properties\AssemblyInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Aggregate.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Bitwise.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientType.cs">
<Link>ClientType.cs</Link>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\VolatileWrapper.cs">
<Link>VolatileWrapper.cs</Link>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandMap.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandTrace.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletionManager.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Condition.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Exclude.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExportOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Format.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ICompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IProfiler.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedis.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ISubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ITransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Message.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageQueue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LuaScript.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Order.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RawResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisChannel.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisCommand.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisKey.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisValue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultBox.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SaveType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SetOperation.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ShutdownMode.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.Poll.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\StringSplits.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\TaskSource.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\DatabaseExtension.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\WrapperBase.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<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')" />
<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="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>
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{36CAC6B6-2B88-447F-AA35-D4DAA5E4F2C7}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<UseVSHostingProcess>false</UseVSHostingProcess>
<DocumentationFile>bin\Debug\StackExchange.Redis.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<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>
<Private>True</Private>
</Reference>
<Reference Include="System.Net" />
<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>
<Private>True</Private>
</Reference>
<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>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis\**\*.cs"/>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<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')" />
<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="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>
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EBF46088-E318-4D32-9EFB-01EF130A4554}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis.StrongName</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Debug\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin.snk\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Verbose\StackExchange.Redis.StrongName.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin.snk\LogOutput\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\LogOutput\StackExchange.Redis.StrongName.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>StackExchange.Redis.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
</ItemGroup>
<ItemGroup>
<Compile Include="StackExchange\Redis\Aggregate.cs" />
<Compile Include="StackExchange\Redis\ClientType.cs" />
<Compile Include="StackExchange\Redis\Compat\VolatileWrapper.cs" />
<Compile Include="StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile>
<Compile Include="StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="StackExchange\Redis\HashEntry.cs" />
<Compile Include="StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="StackExchange\Redis\IProfiler.cs" />
<Compile Include="StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="StackExchange\Redis\LuaScript.cs" />
<Compile Include="StackExchange\Redis\RedisChannel.cs" />
<Compile Include="StackExchange\Redis\Bitwise.cs" />
<Compile Include="StackExchange\Redis\ClientFlags.cs" />
<Compile Include="StackExchange\Redis\ClientInfo.cs" />
<Compile Include="StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="StackExchange\Redis\CommandTrace.cs" />
<Compile Include="StackExchange\Redis\Condition.cs" />
<Compile Include="StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile>
<Compile Include="StackExchange\Redis\ConnectionType.cs" />
<Compile Include="StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="StackExchange\Redis\Exclude.cs" />
<Compile Include="StackExchange\Redis\ExportOptions.cs" />
<Compile Include="StackExchange\Redis\Format.cs" />
<Compile Include="StackExchange\Redis\IBatch.cs" />
<Compile Include="StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="StackExchange\Redis\Order.cs" />
<Compile Include="StackExchange\Redis\RedisBatch.cs" />
<Compile Include="StackExchange\Redis\RedisCommand.cs" />
<Compile Include="StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="StackExchange\Redis\ITransaction.cs" />
<Compile Include="StackExchange\Redis\IRedis.cs" />
<Compile Include="StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="StackExchange\Redis\IDatabase.cs" />
<Compile Include="StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="StackExchange\Redis\IServer.cs" />
<Compile Include="StackExchange\Redis\ISubscriber.cs" />
<Compile Include="StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="StackExchange\Redis\RedisBase.cs" />
<Compile Include="StackExchange\Redis\CommandFlags.cs" />
<Compile Include="StackExchange\Redis\CommandMap.cs" />
<Compile Include="StackExchange\Redis\CompletionManager.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="StackExchange\Redis\ICompletable.cs" />
<Compile Include="StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="StackExchange\Redis\Message.cs" />
<Compile Include="StackExchange\Redis\MessageQueue.cs" />
<Compile Include="StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StackExchange\Redis\RedisResult.cs" />
<Compile Include="StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="StackExchange\Redis\RedisKey.cs" />
<Compile Include="StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="StackExchange\Redis\RedisServer.cs" />
<Compile Include="StackExchange\Redis\RedisType.cs" />
<Compile Include="StackExchange\Redis\RedisValue.cs" />
<Compile Include="StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="StackExchange\Redis\RawResult.cs" />
<Compile Include="StackExchange\Redis\ResultBox.cs" />
<Compile Include="StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="StackExchange\Redis\ResultType.cs" />
<Compile Include="StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="StackExchange\Redis\ServerCounters.cs" />
<Compile Include="StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="StackExchange\Redis\ServerType.cs" />
<Compile Include="StackExchange\Redis\SetOperation.cs" />
<Compile Include="StackExchange\Redis\SocketManager.cs" />
<Compile Include="StackExchange\Redis\SocketManager.NoPoll.cs">
<DependentUpon>SocketManager.cs</DependentUpon>
</Compile>
<Compile Include="StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="StackExchange\Redis\SortType.cs" />
<Compile Include="StackExchange\Redis\StringSplits.cs" />
<Compile Include="StackExchange\Redis\TaskSource.cs" />
<Compile Include="StackExchange\Redis\When.cs" />
<Compile Include="StackExchange\Redis\ShutdownMode.cs" />
<Compile Include="StackExchange\Redis\SaveType.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\BatchWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\DatabaseExtension.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\DatabaseWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\TransactionWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\WrapperBase.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="StackExchange\Redis\SocketManager.Poll.cs">
<DependentUpon>SocketManager.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="StackExchange.Redis.snk" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EBF46088-E318-4D32-9EFB-01EF130A4554}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis.StrongName</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Debug\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin.snk\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Verbose\StackExchange.Redis.StrongName.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin.snk\LogOutput\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\LogOutput\StackExchange.Redis.StrongName.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>..\StackExchange.Redis.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis\**\*.cs"/>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7CEC07F2-8C03-4C42-B048-738B215824C1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\StackExchange.Redis.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\StackExchange.Redis.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Log Output\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\StackExchange.Redis.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;__MonoCS__ FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
</ItemGroup>
<ItemGroup>
<Compile Include="StackExchange\Redis\Aggregate.cs" />
<Compile Include="StackExchange\Redis\ClientType.cs" />
<Compile Include="StackExchange\Redis\Compat\VolatileWrapper.cs" />
<Compile Include="StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile>
<Compile Include="StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="StackExchange\Redis\HashEntry.cs" />
<Compile Include="StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="StackExchange\Redis\IProfiler.cs" />
<Compile Include="StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="StackExchange\Redis\LuaScript.cs" />
<Compile Include="StackExchange\Redis\RedisChannel.cs" />
<Compile Include="StackExchange\Redis\Bitwise.cs" />
<Compile Include="StackExchange\Redis\ClientFlags.cs" />
<Compile Include="StackExchange\Redis\ClientInfo.cs" />
<Compile Include="StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="StackExchange\Redis\CommandTrace.cs" />
<Compile Include="StackExchange\Redis\Condition.cs" />
<Compile Include="StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile>
<Compile Include="StackExchange\Redis\ConnectionType.cs" />
<Compile Include="StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="StackExchange\Redis\Exclude.cs" />
<Compile Include="StackExchange\Redis\ExportOptions.cs" />
<Compile Include="StackExchange\Redis\Format.cs" />
<Compile Include="StackExchange\Redis\IBatch.cs" />
<Compile Include="StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="StackExchange\Redis\Order.cs" />
<Compile Include="StackExchange\Redis\RedisBatch.cs" />
<Compile Include="StackExchange\Redis\RedisCommand.cs" />
<Compile Include="StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="StackExchange\Redis\ITransaction.cs" />
<Compile Include="StackExchange\Redis\IRedis.cs" />
<Compile Include="StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="StackExchange\Redis\IDatabase.cs" />
<Compile Include="StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="StackExchange\Redis\IServer.cs" />
<Compile Include="StackExchange\Redis\ISubscriber.cs" />
<Compile Include="StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="StackExchange\Redis\RedisBase.cs" />
<Compile Include="StackExchange\Redis\CommandFlags.cs" />
<Compile Include="StackExchange\Redis\CommandMap.cs" />
<Compile Include="StackExchange\Redis\CompletionManager.cs" />
<Compile Include="StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="StackExchange\Redis\ICompletable.cs" />
<Compile Include="StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="StackExchange\Redis\Message.cs" />
<Compile Include="StackExchange\Redis\MessageQueue.cs" />
<Compile Include="StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StackExchange\Redis\RedisResult.cs" />
<Compile Include="StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="StackExchange\Redis\RedisKey.cs" />
<Compile Include="StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="StackExchange\Redis\RedisServer.cs" />
<Compile Include="StackExchange\Redis\RedisType.cs" />
<Compile Include="StackExchange\Redis\RedisValue.cs" />
<Compile Include="StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="StackExchange\Redis\RawResult.cs" />
<Compile Include="StackExchange\Redis\ResultBox.cs" />
<Compile Include="StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="StackExchange\Redis\ResultType.cs" />
<Compile Include="StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="StackExchange\Redis\ServerCounters.cs" />
<Compile Include="StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="StackExchange\Redis\ServerType.cs" />
<Compile Include="StackExchange\Redis\SetOperation.cs" />
<Compile Include="StackExchange\Redis\SocketManager.cs" />
<Compile Include="StackExchange\Redis\SocketManager.NoPoll.cs">
<DependentUpon>SocketManager.cs</DependentUpon>
</Compile>
<Compile Include="StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="StackExchange\Redis\SortType.cs" />
<Compile Include="StackExchange\Redis\StringSplits.cs" />
<Compile Include="StackExchange\Redis\TaskSource.cs" />
<Compile Include="StackExchange\Redis\When.cs" />
<Compile Include="StackExchange\Redis\ShutdownMode.cs" />
<Compile Include="StackExchange\Redis\SaveType.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\BatchWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\DatabaseExtension.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\DatabaseWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\TransactionWrapper.cs" />
<Compile Include="StackExchange\Redis\KeyspaceIsolation\WrapperBase.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="StackExchange\Redis\SocketManager.Poll.cs">
<DependentUpon>SocketManager.cs</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<?xml version="1.0" encoding="utf-8"?>
<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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7CEC07F2-8C03-4C42-B048-738B215824C1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis</RootNamespace>
<AssemblyName>StackExchange.Redis</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\StackExchange.Redis.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\StackExchange.Redis.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Log Output\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\StackExchange.Redis.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;__MonoCS__ FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis\**\*.cs"/>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
......@@ -42,7 +42,7 @@
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>StackExchange.Redis.snk</AssemblyOriginatorKeyFile>
<AssemblyOriginatorKeyFile>..\StackExchange.Redis.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
......@@ -62,116 +62,11 @@
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis\Properties\AssemblyInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Aggregate.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Bitwise.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientType.cs">
<Link>ClientType.cs</Link>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\VolatileWrapper.cs">
<Link>VolatileWrapper.cs</Link>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandMap.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandTrace.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletionManager.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Condition.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Exclude.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExportOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Format.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ICompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IProfiler.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedis.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ISubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ITransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Message.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageQueue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LuaScript.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Order.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RawResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisChannel.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisCommand.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisKey.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisValue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultBox.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SaveType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SetOperation.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ShutdownMode.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.Poll.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\StringSplits.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\TaskSource.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\DatabaseExtension.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\WrapperBase.cs" />
<ItemGroup>
<Compile Include="..\StackExchange.Redis\**\*.cs"/>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="StackExchange.Redis.snk" />
</ItemGroup>
<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')" />
......
......@@ -56,112 +56,8 @@
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\StackExchange.Redis\Properties\AssemblyInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Aggregate.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Bitwise.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientInfo.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClientType.cs">
<Link>ClientType.cs</Link>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Compat\VolatileWrapper.cs">
<Link>VolatileWrapper.cs</Link>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConcurrentProfileStorageCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.Profiling.cs">
<DependentUpon>ConnectionMultiplexer.cs</DependentUpon>
</Compile>
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ClusterConfiguration.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandFlags.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandMap.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CommandTrace.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletedDefaultTask.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\CompletionManager.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Condition.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConfigurationOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionFailureType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionMultiplexer.ReaderWriter.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ConnectionType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\DebuggingAids.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointCollection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\EndPointEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExceptionFactory.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Exclude.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExportOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ExtensionMethods.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Format.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\HashSlotMovedEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ICompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IConnectionMultiplexer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IDatabaseAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IMultiMessage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\InternalRegexCompiledOption.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IProfiler.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedis.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IRedisAsync.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\IServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ISubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ITransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LoggingTextStream.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Message.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageCompletable.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MessageQueue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\MigrateOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileContextTracker.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ProfileStorage.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\LuaScript.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\Order.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalBridge.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\PhysicalConnection.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RawResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisBatch.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisChannel.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisCommand.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisDatabase.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisErrorEventArgs.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisFeatures.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisKey.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisLiterals.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisResult.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisServer.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisSubscriber.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisTransaction.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\RedisValue.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ReplicationChangeOptions.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultBox.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultProcessor.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ResultType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ScriptParameterMapper.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SaveType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerCounters.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerEndPoint.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerSelectionStrategy.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ServerType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SetOperation.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\ShutdownMode.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.Poll.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortedSetEntry.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\SortType.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\StringSplits.cs" />
<Compile Include="..\StackExchange.Redis\StackExchange\Redis\TaskSource.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\DatabaseExtension.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\WrapperBase.cs" />
<ItemGroup>
<Compile Include="..\StackExchange.Redis\**\*.cs"/>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
......
{
"version": "1.1.0-*",
"description": "StackExchange.Redis",
"authors": [ "jeremymeng" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"compile": [
"../../StackExchange.Redis/**/*.cs"
],
"dependencies": {
},
"configurations": {
"Debug": {
"compilationOptions": {
"define": [ "DEBUG", "TRACE" ],
"allowUnsafe": true
}
},
"Release": {
"compilationOptions": {
"define": [ "TRACE" ],
"allowUnsafe": true
}
}
},
"frameworks": {
"dnxcore50": {
"dependencies": {
"System.Diagnostics.Debug": "4.0.0",
"System.Diagnostics.TraceSource": "4.0.0-beta-23409",
"System.Diagnostics.Tools": "4.0.0",
"System.IO.Compression": "4.0.0",
"System.Globalization": "4.0.10",
"System.Linq": "4.0.0",
"System.Net.Primitives": "4.0.10",
"System.Net.Sockets": "4.1.0-beta-23409",
"System.Net.Security": "4.0.0-beta-23409",
"System.Net.NameResolution": "4.0.0-beta-23409",
"System.Reflection": "4.0.0",
"System.Reflection.Emit": "4.0.0",
"System.Reflection.TypeExtensions": "4.0.0",
"System.Reflection.Primitives": "4.0.0",
"System.Reflection.Emit.Lightweight": "4.0.0",
"System.Security.Cryptography.Algorithms": "4.0.0-beta-23409",
"System.Security.Cryptography.X509Certificates": "4.0.0-beta-23409",
"System.Text.RegularExpressions": "4.0.10",
"System.Threading": "4.0.0",
"System.Threading.Thread": "4.0.0-*",
"System.Threading.ThreadPool": "4.0.10-beta-23409",
"System.Threading.Timer": "4.0.1-beta-23409",
"System.Threading.Tasks": "4.0.0"
}
}
}
}
\ No newline at end of file
{
"sdk": {
"version": "1.0.0-beta8",
"version": "1.0.0-rc1-final",
"runtime": "coreclr",
"architecture": "x86"
},
......
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