Commit 2712ccf9 authored by Marc Gravell's avatar Marc Gravell

Merge branch 'netcore' of https://github.com/jeremymeng/StackExchange.Redis into jeremymeng-netcore

parents 9a4e4087 53d5028b
......@@ -17,3 +17,5 @@ redis-cli.exe
Redis Configs/*.dat
RedisQFork*.dat
StackExchange.Redis.*.zip
.vs/
*.lock.json
\ No newline at end of file
......@@ -35,9 +35,17 @@ static void MassiveBulkOpsAsync(int AsyncOpsQty, bool preserveOrder, bool withCo
var conn = muxer.GetDatabase();
muxer.Wait(conn.PingAsync());
int number = 0;
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++)
......
<?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>9d83baba-a92e-495f-bf63-deb4f6b09355</ProjectGuid>
<RootNamespace>BasicTest_dnxcore50</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.0.0-*",
"description": "StackExchange.Redis.BasicTest dnxcore50",
"authors": [ "jeremymeng" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"compile": [
"../BasicTest/Program.cs"
],
"dependencies": {
"StackExchange.Redis": "1.1.0-*"
},
"commands": {
"run": "BasicTest_dnxcore50"
},
"configurations": {
"Debug": {
"compilationOptions": {
"define": [ "DEBUG", "TRACE" ]
}
},
"Release": {
"compilationOptions": {
"define": [ "TRACE" ]
}
}
},
"frameworks": {
"dnxcore50": {
"dependencies": {
"System.Console": "4.0.0-beta-23409"
}
}
}
}
......@@ -122,25 +122,36 @@ public void CanOpenSecuredConnection()
}
}
[Test, ExpectedException(typeof(RedisConnectionException))]
[Test]
public void CanNotOpenNonsenseConnection_IP()
{
Assert.Throws<RedisConnectionException>(() =>
{
var log = new StringWriter();
try {
using (var conn = ConnectionMultiplexer.Connect(Config.LocalHost + ":6500")) { }
} finally {
}
finally {
Console.WriteLine(log);
}
});
}
[Test, ExpectedException(typeof(RedisConnectionException))]
[Test]
public void CanNotOpenNonsenseConnection_DNS()
{
Assert.Throws<RedisConnectionException>(() =>
{
var log = new StringWriter();
try {
try
{
using (var conn = ConnectionMultiplexer.Connect("doesnot.exist.ds.aasd981230d.com:6500", log)) { }
} finally {
}
finally
{
Console.WriteLine(log);
}
});
}
[Test]
......
......@@ -55,8 +55,10 @@ public void ExecuteWithEmptyStartingPoint()
}
}
[Test, ExpectedException(typeof(RedisServerException), ExpectedMessage = "WRONGTYPE Operation against a key holding the wrong kind of value")]
[Test]
public void ExecuteWithNonHashStartingPoint()
{
Assert.Throws<RedisConnectionException>(() =>
{
using (var muxer = Config.GetUnsecuredConnection())
{
......@@ -72,11 +74,14 @@ public void ExecuteWithNonHashStartingPoint()
{
conn.Wait(taskResult);
Assert.Fail();
} catch(AggregateException ex)
}
catch (AggregateException ex)
{
throw ex.InnerExceptions[0];
}
}
},
message: "WRONGTYPE Operation against a key holding the wrong kind of value");
}
}
}
......@@ -44,9 +44,9 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<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" />
......
......@@ -100,7 +100,6 @@ where Attribute.IsDefined(method, typeof(TestAttribute))
foreach (var test in tests)
{
var expectedFail = Attribute.GetCustomAttribute(test, typeof(ExpectedExceptionAttribute)) as ExpectedExceptionAttribute;
Console.Write(test.Name + ": ");
Exception err = null;
......@@ -131,35 +130,6 @@ where Attribute.IsDefined(method, typeof(TestAttribute))
err = ((AggregateException)err).InnerExceptions[0];
}
if (expectedFail != null)
{
if (err == null)
{
err = new NUnit.Framework.AssertionException("failed to fail");
}
else
{
int issues = 0;
if (expectedFail.ExpectedException != null && !expectedFail.ExpectedException.IsAssignableFrom(err.GetType()))
{
issues++;
}
if (expectedFail.ExpectedExceptionName != null && err.GetType().FullName != expectedFail.ExpectedExceptionName)
{
issues++;
}
if (expectedFail.ExpectedMessage != null && err.Message != expectedFail.ExpectedMessage)
{
issues++;
}
if (issues == 0) err = null;
else
{
err = new InvalidOperationException("Failed in a different way", err);
}
}
}
if (err == null)
{
Console.WriteLine("pass");
......
......@@ -264,8 +264,10 @@ public void NonAsciiScripts()
}
}
[Test, ExpectedException(typeof(RedisServerException), ExpectedMessage = "oops")]
[Test]
public void ScriptThrowsError()
{
Assert.Throws<RedisServerException>(() =>
{
using (var muxer = GetScriptConn())
{
......@@ -274,11 +276,14 @@ public void ScriptThrowsError()
try
{
conn.Wait(result);
} catch(AggregateException ex)
}
catch (AggregateException ex)
{
throw ex.InnerExceptions[0];
}
}
},
message: "oops");
}
[Test]
......
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="2.6.4" targetFramework="net45" />
<package id="NUnit" version="3.0.0" targetFramework="net45" />
</packages>
\ No newline at end of file
......@@ -2,7 +2,9 @@
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
......@@ -72,26 +74,28 @@ public void PingMany(bool preserveOrder)
}
[Test]
[ExpectedException(typeof(ArgumentException), ExpectedMessage = @"A null key is not valid in this context")]
public void GetWithNullKey()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = null;
db.StringGet(key);
Assert.Throws<ArgumentException>(
() => db.StringGet(key),
"A null key is not valid in this context");
}
}
[Test]
[ExpectedException(typeof(ArgumentException), ExpectedMessage = @"A null key is not valid in this context")]
public void SetWithNullKey()
{
using (var muxer = Create())
{
var db = muxer.GetDatabase();
string key = null, value = "abc";
db.StringSet(key, value);
Assert.Throws<ArgumentException>(
() => db.StringSet(key, value),
"A null key is not valid in this context");
}
}
......@@ -230,9 +234,19 @@ public void MassiveBulkOpsAsync(bool preserveOrder, bool withContinuation)
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++)
......@@ -293,7 +307,6 @@ public void GetWithExpiry(bool exists, bool hasExpiry)
}
}
[Test]
[ExpectedException(typeof(RedisServerException), ExpectedMessage = "WRONGTYPE Operation against a key holding the wrong kind of value")]
public void GetWithExpiryWrongTypeAsync()
{
using (var conn = Create())
......@@ -302,21 +315,26 @@ public void GetWithExpiryWrongTypeAsync()
RedisKey key = Me();
db.KeyDelete(key);
db.SetAdd(key, "abc");
Assert.Throws<RedisServerException>(() =>
{
try
{
var async = db.Wait(db.StringGetWithExpiryAsync(key));
}
catch(AggregateException ex)
catch (AggregateException ex)
{
throw ex.InnerExceptions[0];
}
Assert.Fail();
},
"A null key is not valid in this context");
}
}
[Test]
[ExpectedException(typeof(RedisServerException), ExpectedMessage = "WRONGTYPE Operation against a key holding the wrong kind of value")]
public void GetWithExpiryWrongTypeSync()
{
Assert.Throws<RedisServerException>(() =>
{
using (var conn = Create())
{
......@@ -327,8 +345,11 @@ public void GetWithExpiryWrongTypeSync()
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)]
......@@ -378,7 +399,7 @@ public void MassiveBulkOpsAsyncOldStyle(bool withContinuation, bool suspendFlush
completionMode, AsyncOpsQty / watch.Elapsed.TotalSeconds);
}
}
#endif
[Test]
[TestCase(true, 1)]
......@@ -423,6 +444,8 @@ public void MassiveBulkOpsSync(bool preserveOrder, int threads)
#endif
}
}
#if FEATURE_BOOKSLEEVE
[Test]
[TestCase(ResultCompletionMode.Concurrent, 1)]
[TestCase(ResultCompletionMode.ConcurrentIfContinuation, 1)]
......@@ -462,6 +485,7 @@ public void MassiveBulkOpsSyncOldStyle(ResultCompletionMode completionMode, int
completionMode, threads, (workPerThread * threads) / timeTaken.TotalSeconds);
}
}
#endif
[Test]
[TestCase(true, 1)]
......
using System;
#if FEATURE_MOQ
using System;
using Moq;
using NUnit.Framework;
using StackExchange.Redis.KeyspaceIsolation;
......@@ -12,7 +13,8 @@ public sealed class BatchWrapperTests
private Mock<IBatch> mock;
private BatchWrapper wrapper;
[TestFixtureSetUp]
//[TestFixtureSetUp]
[OneTimeSetUpAttribute]
public void Initialize()
{
mock = new Mock<IBatch>();
......@@ -27,3 +29,4 @@ public void Execute()
}
}
}
#endif
\ No newline at end of file
......@@ -20,7 +20,11 @@ public class Cluster : TestBase
protected override string GetConfiguration()
{
var server = ClusterIp;
#if !DNXCORE50
if (string.Equals(Environment.MachineName, "MARC-LAPTOP", StringComparison.InvariantCultureIgnoreCase))
#else
if (string.Equals(Environment.GetEnvironmentVariable("COMPUTERNAME"), "MARC-LAPTOP", StringComparison.OrdinalIgnoreCase))
#endif
{
server = "192.168.56.101";
}
......@@ -130,7 +134,7 @@ public void IntentionalWrongServer()
using (var conn = Create())
{
var endpoints = conn.GetEndPoints();
var servers = Array.ConvertAll(endpoints, e => conn.GetServer(e));
var servers = endpoints.Select(e => conn.GetServer(e));
var key = Me();
const string value = "abc";
......@@ -198,10 +202,11 @@ public void IntentionalWrongServer()
}
[Test]
[ExpectedException(typeof(RedisCommandException), ExpectedMessage = "Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot")]
public void TransactionWithMultiServerKeys()
{
using(var muxer = Create())
Assert.Throws<RedisCommandException>(() =>
{
using (var muxer = Create())
{
// connect
var cluster = muxer.GetDatabase();
......@@ -249,11 +254,14 @@ public void TransactionWithMultiServerKeys()
//Assert.IsFalse(cluster.Wait(existsX), "x exists");
//Assert.IsFalse(cluster.Wait(existsY), "y exists");
}
},
"Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot");
}
[Test]
[ExpectedException(typeof(RedisCommandException), ExpectedMessage = "Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot")]
public void TransactionWithSameServerKeys()
{
Assert.Throws<RedisCommandException>(() =>
{
using (var muxer = Create())
{
......@@ -302,6 +310,8 @@ public void TransactionWithSameServerKeys()
//Assert.IsTrue(cluster.Wait(existsX), "x exists");
//Assert.IsTrue(cluster.Wait(existsY), "y exists");
}
},
"Multi-key operations must involve a single slot; keys can use 'hash tags' to help this, i.e. '{/users/12345}/account' and '{/users/12345}/contacts' will always be in the same slot");
}
[Test]
......@@ -361,7 +371,7 @@ public void Keys(string pattern, int pageSize)
using (var conn = Create(allowAdmin: true))
{
var cluster = conn.GetDatabase();
var server = Array.ConvertAll(conn.GetEndPoints(), x => conn.GetServer(x)).First(x => !x.IsSlave);
var server = conn.GetEndPoints().Select(x => conn.GetServer(x)).First(x => !x.IsSlave);
server.FlushAllDatabases();
try
{
......@@ -467,7 +477,7 @@ public void AccessRandomKeys()
Task[] send = new Task[COUNT];
int index = 0;
var servers = Array.ConvertAll(conn.GetEndPoints(), x => conn.GetServer(x));
var servers = conn.GetEndPoints().Select(x => conn.GetServer(x));
foreach (var server in servers)
{
if (!server.IsSlave)
......@@ -593,7 +603,7 @@ public void MovedProfiling()
conn.RegisterProfiler(profiler);
var endpoints = conn.GetEndPoints();
var servers = Array.ConvertAll(endpoints, e => conn.GetServer(e));
var servers = endpoints.Select(e => conn.GetServer(e));
conn.BeginProfiling(profiler.MyContext);
var db = conn.GetDatabase();
......
......@@ -125,13 +125,16 @@ public void ClientName()
}
[Test]
[ExpectedException(typeof(RedisCommandException), ExpectedMessage = "This operation has been disabled in the command-map and cannot be used: CONFIG")]
public void ReadConfigWithConfigDisabled()
{
using (var muxer = Create(allowAdmin: true, disabledCommands: new[] { "config", "info" }))
{
var conn = GetServer(muxer);
Assert.Throws<RedisCommandException>(() =>
{
var all = conn.ConfigGet();
},
"This operation has been disabled in the command-map and cannot be used: CONFIG");
}
}
[Test]
......@@ -144,7 +147,11 @@ public void ReadConfig()
var all = conn.ConfigGet();
Assert.IsTrue(all.Length > 0, "any");
#if !DNXCORE50
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);
#endif
Assert.AreEqual(all.Length, pairs.Count);
Assert.IsTrue(pairs.ContainsKey("timeout"), "timeout");
......@@ -157,7 +164,7 @@ public void ReadConfig()
}
[Test]
public async void TestConfigureAsync()
public async System.Threading.Tasks.Task TestConfigureAsync()
{
using(var muxer = Create())
{
......
using System;
#if FEATURE_MOQ
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Net;
......@@ -15,7 +16,8 @@ public sealed class DatabaseWrapperTests
private Mock<IDatabase> mock;
private DatabaseWrapper wrapper;
[TestFixtureSetUp]
//[TestFixtureSetUp]
[OneTimeSetUp]
public void Initialize()
{
mock = new Mock<IDatabase>();
......@@ -289,10 +291,9 @@ public void KeyPersist()
}
[Test]
[ExpectedException(typeof(NotSupportedException))]
public void KeyRandom()
{
wrapper.KeyRandom();
Assert.Throws<NotSupportedException>(() => wrapper.KeyRandom());
}
[Test]
......@@ -933,3 +934,4 @@ public void StringSetRange()
}
}
}
#endif
\ No newline at end of file
......@@ -23,15 +23,21 @@ public void UnkonwnKeywordHandling_Ignore()
{
var options = ConfigurationOptions.Parse("ssl2=true", true);
}
[Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Keyword 'ssl2' is not supported")]
[Test]
public void UnkonwnKeywordHandling_ExplicitFail()
{
Assert.Throws<ArgumentException>(() => {
var options = ConfigurationOptions.Parse("ssl2=true", false);
},
"Keyword 'ssl2' is not supported");
}
[Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Keyword 'ssl2' is not supported")]
[Test]
public void UnkonwnKeywordHandling_ImplicitFail()
{
Assert.Throws<ArgumentException>(() => {
var options = ConfigurationOptions.Parse("ssl2=true");
},
"Keyword 'ssl2' is not supported");
}
}
}
......@@ -9,7 +9,7 @@ public class SO25567566 : TestBase
{
protected override string GetConfiguration()
{
return "127.0.0.1";
return "127.0.0.1:6379";
}
[Test]
public async void Execute()
......
......@@ -127,7 +127,7 @@ public enum TestMode
NoMultiExec,
Twemproxy
}
public IEnumerable<TestMode> TestModes()
public static IEnumerable<TestMode> TestModes()
{
return (TestMode[])Enum.GetValues(typeof(TestMode));
}
......
......@@ -14,16 +14,19 @@ protected override string GetConfiguration()
return PrimaryServer + ":" + SecurePort + "," + PrimaryServer + ":" + PrimaryPort + ",password=" + SecurePassword;
}
[Test, ExpectedException(typeof(RedisCommandException), ExpectedMessage = "Command cannot be issued to a slave: FLUSHDB")]
[Test]
public void CannotFlushSlave()
{
Assert.Throws<RedisCommandException>(() => {
ConfigurationOptions config = GetMasterSlaveConfig();
using (var conn = ConnectionMultiplexer.Connect(config))
{
var servers = Array.ConvertAll(conn.GetEndPoints(), e => conn.GetServer(e));
var servers = conn.GetEndPoints().Select(e => conn.GetServer(e));
var slave = servers.First(x => x.IsSlave);
slave.FlushDatabase();
}
},
"Command cannot be issued to a slave: FLUSHDB");
}
[Test]
......
......@@ -17,7 +17,7 @@ public class Naming
public void CheckSignatures(Type type, bool isAsync)
{
// check that all methods and interfaces look appropriate for their sync/async nature
CheckName(type, isAsync);
CheckName(type.GetTypeInfo(), isAsync);
var members = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
foreach(var member in members)
{
......@@ -29,9 +29,9 @@ public void CheckSignatures(Type type, bool isAsync)
[Test]
public void ShowReadOnlyOperations()
{
var msg = typeof(ConnectionMultiplexer).Assembly.GetType("StackExchange.Redis.Message");
var msg = typeof(ConnectionMultiplexer).GetTypeInfo().Assembly.GetType("StackExchange.Redis.Message");
Assert.IsNotNull(msg, "Message");
var cmd = typeof(ConnectionMultiplexer).Assembly.GetType("StackExchange.Redis.RedisCommand");
var cmd = typeof(ConnectionMultiplexer).GetTypeInfo().Assembly.GetType("StackExchange.Redis.RedisCommand");
Assert.IsNotNull(cmd, "RedisCommand");
var method = msg.GetMethod("IsMasterOnly", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
Assert.IsNotNull(method, "IsMasterOnly");
......@@ -89,7 +89,7 @@ static bool UsesKey(Type type)
{
if (UsesKey(type.GetElementType())) return true;
}
if(type.IsGenericType) // KVP, etc
if(type.GetTypeInfo().IsGenericType) // KVP, etc
{
var args = type.GetGenericArguments();
if (args.Any(UsesKey)) return true;
......@@ -139,7 +139,7 @@ public void CheckSyncAsyncMethodsMatch(Type from, Type to)
{
huntType = null;
}
else if (method.ReturnType.IsSubclassOf(typeof(Task)))
else if (method.ReturnType.GetTypeInfo().IsSubclassOf(typeof(Task)))
{
huntType = method.ReturnType.GetGenericArguments()[0];
}
......@@ -148,9 +148,14 @@ public void CheckSyncAsyncMethodsMatch(Type from, Type to)
huntType = typeof(Task<>).MakeGenericType(method.ReturnType);
}
var pFrom = method.GetParameters();
Type[] args = Array.ConvertAll(pFrom, x => x.ParameterType);
Type[] args = pFrom.Select(x => x.ParameterType).ToArray();
Assert.AreEqual(typeof(CommandFlags), args.Last());
#if !DNXCORE50
var found = to.GetMethod(huntName, flags, null, method.CallingConvention, args, null);
#else
var found = to.GetMethods(flags)
.SingleOrDefault(m => m.Name == huntName && m.HasMatchingParameterTypes(args));
#endif
Assert.IsNotNull(found, "Found " + name + ", no " + huntName);
var pTo = found.GetParameters();
......@@ -166,16 +171,24 @@ public void CheckSyncAsyncMethodsMatch(Type from, Type to)
Console.WriteLine("Validated: {0} ({1} methods)", from.Name, count);
}
static readonly Type ignoreType = typeof(ConnectionMultiplexer).Assembly.GetType("StackExchange.Redis.IgnoreNamePrefixAttribute");
static readonly Type ignoreType = typeof(ConnectionMultiplexer).GetTypeInfo().Assembly.GetType("StackExchange.Redis.IgnoreNamePrefixAttribute");
void CheckMethod(MethodInfo method, bool isAsync)
{
#if DEBUG
#if !DNXCORE50
bool ignorePrefix = ignoreType != null && Attribute.IsDefined(method, ignoreType);
if(ignorePrefix)
#else
bool ignorePrefix = ignoreType != null && method.IsDefined(ignoreType);
#endif
if (ignorePrefix)
{
#if !DNXCORE50
Attribute attrib = Attribute.GetCustomAttribute(method, ignoreType);
if((bool)attrib.GetType().GetProperty("IgnoreEntireMethod").GetValue(attrib))
#else
Attribute attrib = method.GetCustomAttribute(ignoreType);
#endif
if ((bool)attrib.GetType().GetProperty("IgnoreEntireMethod").GetValue(attrib))
{
return;
}
......@@ -212,4 +225,34 @@ void CheckName(MemberInfo member, bool isAsync)
else Assert.IsFalse(member.Name.EndsWith("Async"), member.Name + ":Name - don't end *Async");
}
}
public static class ReflectionExtensions
{
#if !DNXCORE50
public static Type GetTypeInfo(this Type type)
{
return type;
}
#else
public static bool HasMatchingParameterTypes(this MethodInfo method, Type[] paramTypes)
{
var types = method.GetParameters().Select(pi => pi.ParameterType).ToArray();
if (types.Length != paramTypes.Length)
{
return false;
}
for (int i = 0; i < types.Length; i++)
{
if (types[i] != paramTypes[i])
{
return false;
}
}
return true;
}
#endif
}
}
......@@ -2,6 +2,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
#if DNXCORE50
using System.Reflection;
#endif
using System.Threading.Tasks;
using NUnit.Framework;
using System.Threading;
......@@ -456,11 +459,11 @@ public void LowAllocationEnumerable()
conn.WaitAll(allTasks.ToArray());
var res = conn.FinishProfiling(profiler.MyContext);
Assert.IsTrue(res.GetType().IsValueType);
Assert.IsTrue(res.GetType().GetTypeInfo().IsValueType);
using(var e = res.GetEnumerator())
{
Assert.IsTrue(e.GetType().IsValueType);
Assert.IsTrue(e.GetType().GetTypeInfo().IsValueType);
Assert.IsTrue(e.MoveNext());
var i = e.Current;
......
......@@ -38,17 +38,17 @@ public void ExplicitPublishMode()
Thread.Sleep(1000);
pub.Publish("abcd", "efg");
Thread.Sleep(500);
Assert.AreEqual(0, Thread.VolatileRead(ref a), "a1");
Assert.AreEqual(1, Thread.VolatileRead(ref b), "b1");
Assert.AreEqual(1, Thread.VolatileRead(ref c), "c1");
Assert.AreEqual(1, Thread.VolatileRead(ref d), "d1");
Assert.AreEqual(0, VolatileWrapper.Read(ref a), "a1");
Assert.AreEqual(1, VolatileWrapper.Read(ref b), "b1");
Assert.AreEqual(1, VolatileWrapper.Read(ref c), "c1");
Assert.AreEqual(1, VolatileWrapper.Read(ref d), "d1");
pub.Publish("*bcd", "efg");
Thread.Sleep(500);
Assert.AreEqual(1, Thread.VolatileRead(ref a), "a2");
//Assert.AreEqual(1, Thread.VolatileRead(ref b), "b2");
//Assert.AreEqual(1, Thread.VolatileRead(ref c), "c2");
//Assert.AreEqual(1, Thread.VolatileRead(ref d), "d2");
Assert.AreEqual(1, VolatileWrapper.Read(ref a), "a2");
//Assert.AreEqual(1, VolatileWrapper.Read(ref b), "b2");
//Assert.AreEqual(1, VolatileWrapper.Read(ref c), "c2");
//Assert.AreEqual(1, VolatileWrapper.Read(ref d), "d2");
}
}
......@@ -101,7 +101,7 @@ public void TestBasicPubSub(bool preserveOrder, string channelPrefix, bool wildC
{
Assert.AreEqual(0, received.Count);
}
Assert.AreEqual(0, Thread.VolatileRead(ref secondHandler));
Assert.AreEqual(0, VolatileWrapper.Read(ref secondHandler));
var count = sub.Publish(pubChannel, "def");
Ping(muxer, pub, sub, 3);
......@@ -110,7 +110,7 @@ public void TestBasicPubSub(bool preserveOrder, string channelPrefix, bool wildC
{
Assert.AreEqual(1, received.Count);
}
Assert.AreEqual(1, Thread.VolatileRead(ref secondHandler));
Assert.AreEqual(1, VolatileWrapper.Read(ref secondHandler));
// unsubscribe from first; should still see second
sub.Unsubscribe(subChannel, handler1);
......@@ -120,7 +120,7 @@ public void TestBasicPubSub(bool preserveOrder, string channelPrefix, bool wildC
{
Assert.AreEqual(1, received.Count);
}
Assert.AreEqual(2, Thread.VolatileRead(ref secondHandler));
Assert.AreEqual(2, VolatileWrapper.Read(ref secondHandler));
Assert.AreEqual(1, count);
// unsubscribe from second; should see nothing this time
......@@ -131,7 +131,7 @@ public void TestBasicPubSub(bool preserveOrder, string channelPrefix, bool wildC
{
Assert.AreEqual(1, received.Count);
}
Assert.AreEqual(2, Thread.VolatileRead(ref secondHandler));
Assert.AreEqual(2, VolatileWrapper.Read(ref secondHandler));
Assert.AreEqual(0, count);
}
}
......@@ -172,7 +172,7 @@ public void TestBasicPubSubFireAndForget(bool preserveOrder)
{
Assert.AreEqual(0, received.Count);
}
Assert.AreEqual(0, Thread.VolatileRead(ref secondHandler));
Assert.AreEqual(0, VolatileWrapper.Read(ref secondHandler));
Ping(muxer, pub, sub);
var count = sub.Publish(key, "def", CommandFlags.FireAndForget);
Ping(muxer, pub, sub);
......@@ -181,7 +181,7 @@ public void TestBasicPubSubFireAndForget(bool preserveOrder)
{
Assert.AreEqual(1, received.Count);
}
Assert.AreEqual(1, Thread.VolatileRead(ref secondHandler));
Assert.AreEqual(1, VolatileWrapper.Read(ref secondHandler));
sub.Unsubscribe(key);
count = sub.Publish(key, "ghi", CommandFlags.FireAndForget);
......@@ -247,7 +247,7 @@ public void TestPatternPubSub(bool preserveOrder)
{
Assert.AreEqual(0, received.Count);
}
Assert.AreEqual(0, Thread.VolatileRead(ref secondHandler));
Assert.AreEqual(0, VolatileWrapper.Read(ref secondHandler));
var count = sub.Publish("abc", "def");
Ping(muxer, pub, sub);
......@@ -256,7 +256,7 @@ public void TestPatternPubSub(bool preserveOrder)
{
Assert.AreEqual(1, received.Count);
}
Assert.AreEqual(1, Thread.VolatileRead(ref secondHandler));
Assert.AreEqual(1, VolatileWrapper.Read(ref secondHandler));
sub.Unsubscribe("a*c");
count = sub.Publish("abc", "ghi");
......@@ -392,7 +392,7 @@ public void SubscriptionsSurviveConnectionFailure()
});
sub.Publish(channel, "abc");
sub.Ping();
Assert.AreEqual(1, Thread.VolatileRead(ref counter), "counter");
Assert.AreEqual(1, VolatileWrapper.Read(ref counter), "counter");
var server = GetServer(muxer);
Assert.AreEqual(1, server.GetCounters().Subscription.SocketCount, "sockets");
......@@ -408,8 +408,20 @@ public void SubscriptionsSurviveConnectionFailure()
#endif
sub.Publish(channel, "abc");
sub.Ping();
Assert.AreEqual(2, Thread.VolatileRead(ref counter), "counter");
Assert.AreEqual(2, VolatileWrapper.Read(ref counter), "counter");
}
}
}
internal static class VolatileWrapper
{
public static int Read(ref int location)
{
#if !DNXCORE50
return Thread.VolatileRead(ref location);
#else
return Volatile.Read(ref location);
#endif
}
}
}
......@@ -158,7 +158,7 @@ public void TestCallByHash()
var db = conn.GetDatabase();
RedisKey[] keys = { Me() };
string hexHash = string.Concat(Array.ConvertAll(hash, x => x.ToString("X2")));
string hexHash = string.Concat(hash.Select(x => x.ToString("X2")));
Assert.AreEqual("2BAB3B661081DB58BD2341920E0BA7CF5DC77B25", hexHash);
db.ScriptEvaluate(hexHash, keys);
......
......@@ -68,14 +68,16 @@ public void Connect()
[Test]
[TestCase("wrong")]
[TestCase("")]
[ExpectedException(typeof(RedisConnectionException), ExpectedMessage = "No connection is available to service this operation: PING")]
public void ConnectWithWrongPassword(string password)
{
Assert.Throws<RedisConnectionException>(() => {
SetExpectedAmbientFailureCount(-1);
using (var server = Create(password: password, checkConnect: false))
{
server.GetDatabase().Ping();
}
},
"No connection is available to service this operation: PING");
}
}
}
......@@ -6,7 +6,7 @@
namespace StackExchange.Redis.Tests
{
[TestFixture, Ignore]
[TestFixture, Ignore("reason?")]
public class Sentinel
{
// TODO fill in these constants before running tests
......@@ -100,7 +100,7 @@ public void SentinelSlavesTest()
}
}
[Test, Ignore]
[Test, Ignore("reason?")]
public void SentinelFailoverTest()
{
Server.SentinelFailover(ServiceName);
......
......@@ -18,7 +18,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;PLAT_SAFE_CONTINUATIONS</DefineConstants>
<DefineConstants>TRACE;DEBUG;PLAT_SAFE_CONTINUATIONS;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
......@@ -28,14 +28,14 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;PLAT_SAFE_CONTINUATIONS</DefineConstants>
<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</DefineConstants>
<DefineConstants>TRACE;DEBUG;VERBOSE;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
......@@ -45,7 +45,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Log Output\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT</DefineConstants>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
......@@ -53,7 +53,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>TRACE;FEATURE_BOOKSLEEVE;FEATURE_MOQ</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
......@@ -68,9 +68,9 @@
<HintPath>..\packages\Moq.4.2.1502.0911\lib\net40\Moq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<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" />
......
......@@ -8,7 +8,9 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
#if FEATURE_BOOKSLEEVE
using BookSleeve;
#endif
using NUnit.Framework;
namespace StackExchange.Redis.Tests
......@@ -221,6 +223,7 @@ protected static string Me([CallerMemberName] string caller = null)
return caller;
}
#if FEATURE_BOOKSLEEVE
protected static RedisConnection GetOldStyleConnection(bool open = true, bool allowAdmin = false, bool waitForOpen = false, int syncTimeout = 5000, int ioTimeout = 5000)
{
return GetOldStyleConnection(PrimaryServer, PrimaryPort, open, allowAdmin, waitForOpen, syncTimeout, ioTimeout);
......@@ -239,7 +242,7 @@ private static RedisConnection GetOldStyleConnection(string host, int port, bool
}
return conn;
}
#endif
protected static TimeSpan RunConcurrent(Action work, int threads, int timeout = 10000, [CallerMemberName] string caller = null)
{
if (work == null) throw new ArgumentNullException("work");
......@@ -282,11 +285,13 @@ protected static TimeSpan RunConcurrent(Action work, int threads, int timeout =
}
if (!allDone.WaitOne(timeout))
{
for(int i = 0; i < threads; i++)
#if !DNXCORE50
for (int i = 0; i < threads; i++)
{
var thd = threadArr[i];
if (thd.IsAlive) thd.Abort();
}
#endif
throw new TimeoutException();
}
......
using System.Text;
#if FEATURE_MOQ
using System.Text;
using Moq;
using NUnit.Framework;
using StackExchange.Redis.KeyspaceIsolation;
......@@ -11,7 +12,7 @@ public sealed class TransactionWrapperTests
private Mock<ITransaction> mock;
private TransactionWrapper wrapper;
[TestFixtureSetUp]
[OneTimeSetUp]
public void Initialize()
{
mock = new Mock<ITransaction>();
......@@ -89,3 +90,4 @@ public void Execute()
}
}
}
#endif
\ No newline at end of file
......@@ -28,34 +28,42 @@ public void BlankPrefixYieldsSame_String()
Assert.AreSame(raw, prefixed);
}
}
[Test, ExpectedException(typeof(ArgumentNullException))]
[Test]
public void NullPrefixIsError_Bytes()
{
Assert.Throws<ArgumentNullException>(() => {
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix((byte[])null);
}
});
}
[Test, ExpectedException(typeof(ArgumentNullException))]
[Test]
public void NullPrefixIsError_String()
{
Assert.Throws<ArgumentNullException>(() => {
using (var conn = Create())
{
var raw = conn.GetDatabase(1);
var prefixed = raw.WithKeyPrefix((string)null);
}
});
}
[Test, ExpectedException(typeof(ArgumentNullException))]
[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 System;
#if FEATURE_MOQ
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Net;
......@@ -15,7 +16,8 @@ public sealed class WrapperBaseTests
private Mock<IDatabaseAsync> mock;
private WrapperBase<IDatabaseAsync> wrapper;
[TestFixtureSetUp]
//[TestFixtureSetUp]
[OneTimeSetUp]
public void Initialize()
{
mock = new Mock<IDatabaseAsync>();
......@@ -258,10 +260,11 @@ public void KeyPersistAsync()
}
[Test]
[ExpectedException(typeof(NotSupportedException))]
public void KeyRandomAsync()
{
Assert.Throws<NotSupportedException>(() => {
wrapper.KeyRandomAsync();
});
}
[Test]
......@@ -888,3 +891,4 @@ public void StringSetRangeAsync()
}
}
}
#endif
\ No newline at end of file
......@@ -2,5 +2,5 @@
<packages>
<package id="BookSleeve" version="1.3.41" targetFramework="net45" />
<package id="Moq" version="4.2.1502.0911" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" />
<package id="NUnit" version="3.0.0" targetFramework="net45" />
</packages>
\ No newline at end of file
using System;
using System.Reflection;
using NUnitLite;
namespace StackExchange.Redis.Tests
{
public class Program
{
public int Main(string[] args)
{
return new AutoRun().Execute(typeof(TestBase).GetTypeInfo().Assembly, Console.Out, Console.In, args);
}
}
}
\ 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>a51dca17-e8f1-44e1-9a37-328fab14d2ce</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>
</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.0.0-*",
"description": "StackExchange.Redis.Tests",
"authors": [ "jeremymeng" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"compile": [
"../../StackExchange.Redis.Tests/**/*.cs"
],
"dependencies": {
"StackExchange.Redis": "1.1.0-*"
},
"commands": {
"run": "StackExchange.Redis.Tests"
},
"configurations": {
"Debug": {
"compilationOptions": {
"define": [ "DEBUG", "TRACE", "PLAT_SAFE_CONTINUATIONS" ]
}
},
"Release": {
"compilationOptions": {
"define": [ "TRACE", "PLAT_SAFE_CONTINUATIONS" ]
}
}
},
"frameworks": {
"dnxcore50": {
"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",
"nunitlite": "3.0.0"
}
}
}
}

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24709.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}"
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}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "BasicTest_dnxcore50", "BasicTest_dnxcore50\BasicTest_dnxcore50.xproj", "{9D83BABA-A92E-495F-BF63-DEB4F6B09355}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
......@@ -17,7 +17,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;DEBUG;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -27,7 +27,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -36,7 +36,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin.snk\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE STRONG_NAME</DefineConstants>
<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>
......@@ -48,7 +48,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin.snk\LogOutput\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT STRONG_NAME</DefineConstants>
<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>
......@@ -64,7 +64,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize>
......@@ -81,6 +81,7 @@
<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>
......@@ -89,6 +90,7 @@
<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" />
......
......@@ -17,7 +17,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
<DefineConstants>TRACE;DEBUG;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -27,7 +27,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>TRACE;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -36,7 +36,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Verbose\</OutputPath>
<DefineConstants>TRACE;DEBUG;VERBOSE</DefineConstants>
<DefineConstants>TRACE;DEBUG;VERBOSE;FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\StackExchange.Redis.xml</DocumentationFile>
<DebugType>full</DebugType>
......@@ -48,7 +48,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Log Output|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Log Output\</OutputPath>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT</DefineConstants>
<DefineConstants>TRACE;DEBUG;LOGOUTPUT FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\StackExchange.Redis.xml</DocumentationFile>
<DebugType>full</DebugType>
......@@ -58,7 +58,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;__MonoCS__</DefineConstants>
<DefineConstants>TRACE;__MonoCS__ FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
<Optimize>true</Optimize>
......@@ -75,6 +75,7 @@
<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>
......@@ -83,6 +84,7 @@
<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" />
......
......@@ -85,8 +85,7 @@ public static CommandMap Create(Dictionary<string, string> overrides)
{
if (overrides == null || overrides.Count == 0) return Default;
if (ReferenceEquals(overrides.Comparer, StringComparer.OrdinalIgnoreCase) ||
ReferenceEquals(overrides.Comparer, StringComparer.InvariantCultureIgnoreCase))
if (ReferenceEquals(overrides.Comparer, StringComparer.OrdinalIgnoreCase))
{
// that's ok; we're happy with ordinal/invariant case-insensitive
// (but not culture-specific insensitive; completely untested)
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StackExchange.Redis
{
internal static class VolatileWrapper
{
public static int Read(ref int location)
{
#if !DNXCORE50
return System.Threading.Thread.VolatileRead(ref location);
#else
return System.Threading.Volatile.Read(ref location);
#endif
}
public static void Write(ref int address, int value)
{
#if !DNXCORE50
System.Threading.Thread.VolatileWrite(ref address, value);
#else
System.Threading.Volatile.Write(ref address, value);
#endif
}
}
}
......@@ -145,7 +145,7 @@ private void ProcessAsyncCompletionQueueImpl()
// give it a moment and try again, noting that we might lose the battle
// when we pause
Interlocked.CompareExchange(ref activeAsyncWorkerThread, 0, currentThread);
if (Thread.Yield() && Interlocked.CompareExchange(ref activeAsyncWorkerThread, currentThread, 0) == 0)
if (SpinWait() && Interlocked.CompareExchange(ref activeAsyncWorkerThread, currentThread, 0) == 0)
{
// we paused, and we got the lock back; anything else?
lock (asyncCompletionQueue)
......@@ -176,5 +176,20 @@ private void ProcessAsyncCompletionQueueImpl()
Interlocked.CompareExchange(ref activeAsyncWorkerThread, 0, currentThread);
}
}
private bool SpinWait()
{
var sw = new SpinWait();
byte maxSpins = 128;
do
{
if (sw.NextSpinWillYield)
return true;
maxSpins--;
}
while (maxSpins > 0);
return false;
}
}
}
......@@ -29,7 +29,10 @@ public enum Proxy
/// <summary>
/// The options relevant to a set of redis connections
/// </summary>
public sealed class ConfigurationOptions : ICloneable
public sealed class ConfigurationOptions
#if !DNXCORE50
: ICloneable
#endif
{
internal const string DefaultTieBreaker = "__Booksleeve_TieBreak", DefaultConfigurationChannel = "__Booksleeve_MasterChanged";
......@@ -84,7 +87,7 @@ internal static void Unknown(string key)
ConfigChannel, AbortOnConnectFail, ResolveDns,
ChannelPrefix, Proxy, ConnectRetry,
ConfigCheckSeconds, DefaultDatabase,
}.ToDictionary(x => x, StringComparer.InvariantCultureIgnoreCase);
}.ToDictionary(x => x, StringComparer.OrdinalIgnoreCase);
public static string TryNormalize(string value)
{
......@@ -139,7 +142,11 @@ public static string TryNormalize(string value)
/// <summary>
/// Indicates whether the connection should be encrypted
/// </summary>
[Obsolete("Please use .Ssl instead of .UseSsl"), Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Please use .Ssl instead of .UseSsl"),
#if !DNXCORE50
Browsable(false),
#endif
EditorBrowsable(EditorBrowsableState.Never)]
public bool UseSsl { get { return Ssl; } set { Ssl = value; } }
/// <summary>
......@@ -248,7 +255,7 @@ public CommandMap CommandMap
/// <summary>
/// Specifies the time in milliseconds that the system should allow for synchronous operations (defaults to 1 second)
/// </summary>
public int SyncTimeout { get { return syncTimeout.GetValueOrDefault(1000); } set { syncTimeout = value; } }
public int SyncTimeout { get { return syncTimeout.GetValueOrDefault(20000); } set { syncTimeout = value; } }
/// <summary>
/// Specifies the time in milliseconds that the system should allow for responses before concluding that the socket is unhealthy
......@@ -394,7 +401,7 @@ internal bool HasDnsEndPoints()
#pragma warning disable 1998 // NET40 is sync, not async, currently
internal async Task ResolveEndPointsAsync(ConnectionMultiplexer multiplexer, TextWriter log)
{
Dictionary<string, IPAddress> cache = new Dictionary<string, IPAddress>(StringComparer.InvariantCultureIgnoreCase);
Dictionary<string, IPAddress> cache = new Dictionary<string, IPAddress>(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < endpoints.Count; i++)
{
var dns = endpoints[i] as DnsEndPoint;
......@@ -463,10 +470,13 @@ static void Append(StringBuilder sb, string prefix, object value)
}
}
#if !DNXCORE50
static bool IsOption(string option, string prefix)
{
return option.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase);
}
#endif
void Clear()
{
clientName = serviceName = password = tieBreaker = sslHost = configChannel = null;
......@@ -482,7 +492,9 @@ void Clear()
SocketManager = null;
}
#if !DNXCORE50
object ICloneable.Clone() { return Clone(); }
#endif
private void DoParse(string configuration, bool ignoreUnknown)
{
......@@ -586,7 +598,7 @@ private void DoParse(string configuration, bool ignoreUnknown)
var cmdName = option.Substring(1, idx - 1);
if (Enum.TryParse(cmdName, true, out cmd))
{
if (map == null) map = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
if (map == null) map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
map[cmdName] = value;
}
}
......
......@@ -95,7 +95,7 @@ public ServerCounters GetCounters()
/// <summary>
/// Gets the client-name that will be used on all new connections
/// </summary>
public string ClientName { get { return configuration.ClientName ?? Environment.MachineName; } }
public string ClientName { get { return configuration.ClientName ?? Environment.GetEnvironmentVariable("ComputerName"); } }
/// <summary>
/// Gets the configuration of the connection
......@@ -482,7 +482,7 @@ public EndPoint[] GetEndPoints(bool configuredOnly = false)
{
if (configuredOnly) return configuration.EndPoints.ToArray();
return Array.ConvertAll(serverSnapshot, x => x.EndPoint);
return serverSnapshot.Select(x => x.EndPoint).ToArray();
}
private readonly int timeoutMilliseconds;
......@@ -560,6 +560,8 @@ private static bool WaitAllIgnoreErrors(Task[] tasks, int timeout)
}
return false;
}
#if !DNXCORE50
private void LogLockedWithThreadPoolStats(TextWriter log, string message, out int busyWorkerCount)
{
busyWorkerCount = 0;
......@@ -573,6 +575,8 @@ private void LogLockedWithThreadPoolStats(TextWriter log, string message, out in
LogLocked(log, sb.ToString());
}
}
#endif
static bool AllComplete(Task[] tasks)
{
for(int i = 0 ; i < tasks.Length ; i++)
......@@ -599,16 +603,19 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
}
var watch = Stopwatch.StartNew();
#if !DNXCORE50
int busyWorkerCount;
LogLockedWithThreadPoolStats(log, "Awaiting task completion", out busyWorkerCount);
#endif
try
{
// if none error, great
var remaining = timeoutMilliseconds - checked((int)watch.ElapsedMilliseconds);
if (remaining <= 0)
{
#if !DNXCORE50
LogLockedWithThreadPoolStats(log, "Timeout before awaiting for tasks", out busyWorkerCount);
#endif
return false;
}
......@@ -620,7 +627,9 @@ 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
LogLockedWithThreadPoolStats(log, all ? "All tasks completed cleanly" : "Not all tasks completed cleanly", out busyWorkerCount);
#endif
return all;
}
catch
......@@ -636,7 +645,9 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
var remaining = timeoutMilliseconds - checked((int)watch.ElapsedMilliseconds);
if (remaining <= 0)
{
#if !DNXCORE50
LogLockedWithThreadPoolStats(log, "Timeout awaiting tasks", out busyWorkerCount);
#endif
return false;
}
try
......@@ -652,7 +663,9 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
{ }
}
}
#if !DNXCORE50
LogLockedWithThreadPoolStats(log, "Finished awaiting tasks", out busyWorkerCount);
#endif
return false;
}
......@@ -928,11 +941,11 @@ private void OnHeartbeat()
internal long LastHeartbeatSecondsAgo {
get {
if (pulse == null) return -1;
return unchecked(Environment.TickCount - Thread.VolatileRead(ref lastHeartbeatTicks)) / 1000;
return unchecked(Environment.TickCount - VolatileWrapper.Read(ref lastHeartbeatTicks)) / 1000;
}
}
internal static long LastGlobalHeartbeatSecondsAgo
{ get { return unchecked(Environment.TickCount - Thread.VolatileRead(ref lastGlobalHeartbeatTicks)) / 1000; } }
{ get { return unchecked(Environment.TickCount - VolatileWrapper.Read(ref lastGlobalHeartbeatTicks)) / 1000; } }
internal CompletionManager UnprocessableCompletionManager { get { return unprocessableCompletionManager; } }
......@@ -1434,7 +1447,7 @@ private async Task<ServerEndPoint> NominatePreferredMaster(TextWriter log, Serve
Dictionary<string, int> uniques = null;
if (useTieBreakers)
{ // count the votes
uniques = new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
uniques = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
await WaitAllIgnoreErrorsAsync(tieBreakers, 50, log).ForAwait();
for (int i = 0; i < tieBreakers.Length; i++)
{
......@@ -1874,8 +1887,7 @@ internal T ExecuteSyncImpl<T>(Message message, ResultProcessor<T> processor, Ser
else
{
int inst, qu, qs, qc, wr, wq, @in, ar;
string iocp, worker;
#if !__MonoCS__
#if FEATURE_SOCKET_MODE_POLL
var mgrState = socketManager.State;
var lastError = socketManager.LastErrorTimeRelative();
......@@ -1889,9 +1901,8 @@ internal T ExecuteSyncImpl<T>(Message message, ResultProcessor<T> processor, Ser
};
int queue = server.GetOutstandingCount(message.Command, out inst, out qu, out qs, out qc, out wr, out wq, out @in, out ar);
int busyWorkerCount = GetThreadPoolStats(out iocp, out worker);
add("Instantaneous", "inst", inst.ToString());
#if !__MonoCS__
#if FEATURE_SOCKET_MODE_POLL
add("Manager-State", "mgr", mgrState.ToString());
add("Last-Error", "err", lastError);
#endif
......@@ -1904,10 +1915,14 @@ internal T ExecuteSyncImpl<T>(Message message, ResultProcessor<T> processor, Ser
add("Inbound-Bytes", "in", @in.ToString());
add("Active-Readers", "ar", ar.ToString());
add("Client-Name", "clientName", ClientName);
#if !DNXCORE50
string iocp, worker;
int busyWorkerCount = GetThreadPoolStats(out iocp, out worker);
add("ThreadPool-IO-Completion", "IOCP", iocp);
add("ThreadPool-Workers", "WORKER", worker);
add("Client-Name", "clientName", ClientName);
data.Add(Tuple.Create("Busy-Workers", busyWorkerCount.ToString()));
#endif
errMessage = sb.ToString();
if (stormLogThreshold >= 0 && queue >= stormLogThreshold && Interlocked.CompareExchange(ref haveStormLog, 1, 0) == 0)
{
......@@ -1937,6 +1952,8 @@ internal T ExecuteSyncImpl<T>(Message message, ResultProcessor<T> processor, Ser
return val;
}
}
#if !DNXCORE50
private static int GetThreadPoolStats(out string iocp, out string worker)
{
//BusyThreads = TP.GetMaxThreads() –TP.GetAVailable();
......@@ -1958,6 +1975,7 @@ private static int GetThreadPoolStats(out string iocp, out string worker)
worker = string.Format("(Busy={0},Free={1},Min={2},Max={3})", busyWorkerThreads, freeWorkerThreads, minWorkerThreads, maxWorkerThreads);
return busyWorkerThreads;
}
#endif
/// <summary>
/// Should exceptions include identifiable details? (key names, additional .Data annotations)
......
using System;
using System.Collections.Generic;
using System.Linq;
namespace StackExchange.Redis
{
......@@ -120,7 +121,7 @@ public static string[] ToStringArray(this RedisValue[] values)
{
if (values == null) return null;
if (values.Length == 0) return nix;
return Array.ConvertAll(values, x => (string)x);
return values.Select(x => (string)x).ToArray();
}
}
}
......@@ -31,7 +31,10 @@ public HashEntry(RedisValue name, RedisValue value)
/// <summary>
/// The name of the hash field
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Name", false)]
#if !DNXCORE50
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Name", false)]
public RedisValue Key { get { return name; } }
/// <summary>
......
#if DNXCORE50
using System;
#endif
using System.Text.RegularExpressions;
namespace StackExchange.Redis
{
internal static class InternalRegexCompiledOption
{
private static readonly RegexOptions RegexCompiledOption;
static InternalRegexCompiledOption()
{
#if DNXCORE50
if (!Enum.TryParse("Compiled", out RegexCompiledOption))
RegexCompiledOption = RegexOptions.None;
#else
RegexCompiledOption = RegexOptions.Compiled;
#endif
}
/// <summary>
/// Gets the default <see cref="RegexOptions"/> to use.
/// <see cref="System.Text.RegularExpressions.RegexOptions.Compiled"/> option isn't available yet for dnxcore50.
/// This returns <see cref="System.Text.RegularExpressions.RegexOptions.Compiled"/> if it is supported;
/// <see cref="System.Text.RegularExpressions.RegexOptions.None"/> otherwise.
/// </summary>
public static RegexOptions Default
{
get
{
return RegexCompiledOption;
}
}
}
}
......@@ -119,7 +119,7 @@ internal void ExtractParameters(object ps, RedisKey? keyPrefix, out RedisKey[] k
{
string missingMember;
string badMemberType;
if(!ScriptParameterMapper.IsValidParameterHash(psType, this, out missingMember, out badMemberType))
if (!ScriptParameterMapper.IsValidParameterHash(psType, this, out missingMember, out badMemberType))
{
if (missingMember != null)
{
......
......@@ -2,7 +2,9 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
#if FEATURE_SERIALIZATION
using System.Runtime.Serialization;
#endif
using System.Text;
using System.Threading.Tasks;
......@@ -11,10 +13,14 @@ namespace StackExchange.Redis
/// <summary>
/// Indicates that a command was illegal and was not sent to the server
/// </summary>
#if FEATURE_SERIALIZATION
[Serializable]
#endif
public sealed class RedisCommandException : Exception
{
#if FEATURE_SERIALIZATION
private RedisCommandException(SerializationInfo info, StreamingContext ctx) : base(info, ctx) { }
#endif
internal RedisCommandException(string message) : base(message) { }
internal RedisCommandException(string message, Exception innerException) : base(message, innerException) { }
}
......@@ -24,9 +30,12 @@ public sealed class RedisCommandException : Exception
/// <summary>
/// Indicates a connection fault when communicating with redis
/// </summary>
#if FEATURE_SERIALIZATION
[Serializable]
#endif
public sealed class RedisConnectionException : RedisException
{
#if FEATURE_SERIALIZATION
private RedisConnectionException(SerializationInfo info, StreamingContext ctx) : base(info, ctx)
{
this.FailureType = (ConnectionFailureType)info.GetInt32("failureType");
......@@ -39,6 +48,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
base.GetObjectData(info, context);
info.AddValue("failureType", (int)this.FailureType);
}
#endif
internal RedisConnectionException(ConnectionFailureType failureType, string message) : base(message)
{
......@@ -58,13 +68,17 @@ internal RedisConnectionException(ConnectionFailureType failureType, string mess
/// <summary>
/// Indicates an issue communicating with redis
/// </summary>
#if FEATURE_SERIALIZATION
[Serializable]
#endif
public class RedisException : Exception
{
/// <summary>
/// Deserialization constructor; not intended for general usage
/// </summary>
#if FEATURE_SERIALIZATION
protected RedisException(SerializationInfo info, StreamingContext ctx) : base(info, ctx) { }
#endif
internal RedisException(string message) : base(message) { }
internal RedisException(string message, Exception innerException) : base(message, innerException) { }
......@@ -72,10 +86,14 @@ public class RedisException : Exception
/// <summary>
/// Indicates an exception raised by a redis server
/// </summary>
#if FEATURE_SERIALIZATION
[Serializable]
#endif
public sealed class RedisServerException : RedisException
{
#if FEATURE_SERIALIZATION
private RedisServerException(SerializationInfo info, StreamingContext ctx) : base(info, ctx) { }
#endif
internal RedisServerException(string message) : base(message) { }
}
......
......@@ -394,7 +394,7 @@ internal void OnHeartbeat(bool ifConnectedOnly)
switch (state)
{
case (int)State.Connecting:
int connectTimeMilliseconds = unchecked(Environment.TickCount - Thread.VolatileRead(ref connectStartTicks));
int connectTimeMilliseconds = unchecked(Environment.TickCount - VolatileWrapper.Read(ref connectStartTicks));
if (connectTimeMilliseconds >= multiplexer.RawConfig.ConnectTimeout)
{
Trace("Aborting connect");
......
......@@ -10,6 +10,9 @@
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
#if DNXCORE50
using System.Threading.Tasks;
#endif
namespace StackExchange.Redis
{
......@@ -93,7 +96,7 @@ public PhysicalConnection(PhysicalBridge bridge)
public void BeginConnect(TextWriter log)
{
Thread.VolatileWrite(ref firstUnansweredWriteTickCount, 0);
VolatileWrapper.Write(ref firstUnansweredWriteTickCount, 0);
var endpoint = this.bridge.ServerEndPoint.EndPoint;
multiplexer.Trace("Connecting...", physicalName);
......@@ -113,7 +116,7 @@ public long LastWriteSecondsAgo
{
get
{
return unchecked(Environment.TickCount - Thread.VolatileRead(ref lastWriteTickCount)) / 1000;
return unchecked(Environment.TickCount - VolatileWrapper.Read(ref lastWriteTickCount)) / 1000;
}
}
......@@ -128,13 +131,17 @@ public void Dispose()
if (outStream != null)
{
multiplexer.Trace("Disconnecting...", physicalName);
#if !DNXCORE50
try { outStream.Close(); } catch { }
#endif
try { outStream.Dispose(); } catch { }
outStream = null;
}
if (netStream != null)
{
#if !DNXCORE50
try { netStream.Close(); } catch { }
#endif
try { netStream.Dispose(); } catch { }
netStream = null;
}
......@@ -189,9 +196,9 @@ public void RecordConnectionFailed(ConnectionFailureType failureType, ref Socket
if (isCurrent && Interlocked.CompareExchange(ref failureReported, 1, 0) == 0)
{
managerState = SocketManager.ManagerState.RecordConnectionFailed_ReportFailure;
int now = Environment.TickCount, lastRead = Thread.VolatileRead(ref lastReadTickCount), lastWrite = Thread.VolatileRead(ref lastWriteTickCount),
lastBeat = Thread.VolatileRead(ref lastBeatTickCount);
int unansweredRead = Thread.VolatileRead(ref firstUnansweredWriteTickCount);
int now = Environment.TickCount, lastRead = VolatileWrapper.Read(ref lastReadTickCount), lastWrite = VolatileWrapper.Read(ref lastWriteTickCount),
lastBeat = VolatileWrapper.Read(ref lastBeatTickCount);
int unansweredRead = VolatileWrapper.Read(ref firstUnansweredWriteTickCount);
var exMessage = new StringBuilder(failureType + " on " + Format.ToString(bridge.ServerEndPoint.EndPoint) + "/" + connectionType);
var data = new List<Tuple<string, string>>
......@@ -224,7 +231,7 @@ public void RecordConnectionFailed(ConnectionFailureType failureType, ref Socket
add("Last-Heartbeat", "last-heartbeat", (lastBeat == 0 ? "never" : (unchecked(now - lastBeat)/1000 + "s ago"))+ (bridge.IsBeating ? " (mid-beat)" : "") );
add("Last-Multiplexer-Heartbeat", "last-mbeat", multiplexer.LastHeartbeatSecondsAgo + "s ago");
add("Last-Global-Heartbeat", "global", ConnectionMultiplexer.LastGlobalHeartbeatSecondsAgo + "s ago");
#if !__MonoCS__
#if FEATURE_SOCKET_MODE_POLL
var mgr = bridge.Multiplexer.SocketManager;
add("SocketManager-State", "mgr", mgr.State.ToString());
add("Last-Error", "err", mgr.LastErrorTimeRelative());
......@@ -595,23 +602,20 @@ unsafe void WriteRaw(Stream stream, string value, int encodedLength)
stream.Write(outScratch, 0, bytes);
}
else
{
fixed (char* c = value)
fixed (byte* b = outScratch)
{
int charsRemaining = value.Length, charOffset = 0, bytesWritten;
var valueCharArray = value.ToCharArray();
while (charsRemaining > Scratch_CharsPerBlock)
{
bytesWritten = outEncoder.GetBytes(c + charOffset, Scratch_CharsPerBlock, b, ScratchSize, false);
bytesWritten = outEncoder.GetBytes(valueCharArray, charOffset, Scratch_CharsPerBlock, outScratch, 0, false);
stream.Write(outScratch, 0, bytesWritten);
charOffset += Scratch_CharsPerBlock;
charsRemaining -= Scratch_CharsPerBlock;
}
bytesWritten = outEncoder.GetBytes(c + charOffset, charsRemaining, b, ScratchSize, true);
bytesWritten = outEncoder.GetBytes(valueCharArray, charOffset, charsRemaining, outScratch, 0, true);
if (bytesWritten != 0) stream.Write(outScratch, 0, bytesWritten);
}
}
}
const int ScratchSize = 512;
static readonly int Scratch_CharsPerBlock = ScratchSize / Encoding.UTF8.GetMaxByteCount(1);
private readonly byte[] outScratch = new byte[ScratchSize];
......@@ -657,6 +661,14 @@ void BeginReading()
int space = EnsureSpaceAndComputeBytesToRead();
multiplexer.Trace("Beginning async read...", physicalName);
var result = netStream.BeginRead(ioBuffer, ioBufferBytes, space, endRead, this);
#if DNXCORE50
Task<int> t = (Task<int>)result;
if (t.Status == TaskStatus.RanToCompletion && t.Result == -1)
{
multiplexer.Trace("Could not connect: ", physicalName);
return;
}
#endif
if (result.CompletedSynchronously)
{
multiplexer.Trace("Completed synchronously: processing immediately", physicalName);
......@@ -664,7 +676,13 @@ void BeginReading()
}
} while (keepReading);
}
catch(System.IO.IOException ex)
#if DNXCORE50
catch (AggregateException ex)
{
throw ex.InnerException;
}
#endif
catch (System.IO.IOException ex)
{
multiplexer.Trace("Could not connect: " + ex.Message, physicalName);
}
......@@ -724,8 +742,11 @@ SocketMode ISocketCallback.Connected(Stream stream, TextWriter log)
, EncryptionPolicy.RequireEncryption
#endif
);
try
{
ssl.AuthenticateAsClient(host);
if (!ssl.IsEncrypted)
}
catch (AuthenticationException)
{
RecordConnectionFailed(ConnectionFailureType.AuthenticationFailure);
multiplexer.Trace("Encryption failure");
......@@ -738,7 +759,11 @@ SocketMode ISocketCallback.Connected(Stream stream, TextWriter log)
int bufferSize = config.WriteBuffer;
this.netStream = stream;
#if !DNXCORE50
this.outStream = bufferSize <= 0 ? stream : new BufferedStream(stream, bufferSize);
#else
this.outStream = stream;
#endif
multiplexer.LogLocked(log, "Connected {0}", bridge);
bridge.OnConnected(this, log);
......@@ -895,7 +920,7 @@ private bool ProcessReadBytes(int bytesRead)
Interlocked.Exchange(ref lastReadTickCount, Environment.TickCount);
// reset unanswered write timestamp
Thread.VolatileWrite(ref firstUnansweredWriteTickCount, 0);
VolatileWrapper.Write(ref firstUnansweredWriteTickCount, 0);
ioBufferBytes += bytesRead;
multiplexer.Trace("More bytes available: " + bytesRead + " (" + ioBufferBytes + ")", physicalName);
......@@ -1058,7 +1083,7 @@ RawResult TryParseResult(byte[] buffer, ref int offset, ref int count)
public void CheckForStaleConnection(ref SocketManager.ManagerState managerState)
{
int firstUnansweredWrite;
firstUnansweredWrite = Thread.VolatileRead(ref firstUnansweredWriteTickCount);
firstUnansweredWrite = VolatileWrapper.Read(ref firstUnansweredWriteTickCount);
DebugEmulateStaleConnection(ref firstUnansweredWrite);
......@@ -1070,4 +1095,38 @@ public void CheckForStaleConnection(ref SocketManager.ManagerState managerState)
}
}
}
#if DNXCORE50
internal static class StreamExtensions
{
internal static IAsyncResult BeginRead(this Stream stream, byte[] buffer, int offset, int count, AsyncCallback ac, object state)
{
Task<int> f = Task<int>.Factory.StartNew(_ => {
try
{
return stream.Read(buffer, offset, count);
}
catch (IOException ex)
{
System.Diagnostics.Trace.WriteLine("Could not connect: " + ex.InnerException.Message);
return -1;
}
}, state);
if (ac != null) f.ContinueWith(res => ac(f));
return f;
}
internal static int EndRead(this Stream stream, IAsyncResult ar)
{
try
{
return ((Task<int>)ar).Result;
}
catch (AggregateException ex)
{
throw ex.InnerException;
}
}
}
#endif
}
using System;
using System.Linq;
namespace StackExchange.Redis
{
......@@ -194,14 +195,14 @@ internal override bool AsBoolean()
throw new InvalidCastException();
}
internal override bool[] AsBooleanArray() { return Array.ConvertAll(value, x => x.AsBoolean()); }
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 Array.ConvertAll(value, x => x.AsByteArray()); }
internal override byte[][] AsByteArrayArray() { return value.Select(x => x.AsByteArray()).ToArray(); }
internal override double AsDouble()
{
......@@ -209,7 +210,7 @@ internal override double AsDouble()
throw new InvalidCastException();
}
internal override double[] AsDoubleArray() { return Array.ConvertAll(value, x => x.AsDouble()); }
internal override double[] AsDoubleArray() { return value.Select(x => x.AsDouble()).ToArray(); }
internal override int AsInt32()
{
......@@ -217,7 +218,7 @@ internal override int AsInt32()
throw new InvalidCastException();
}
internal override int[] AsInt32Array() { return Array.ConvertAll(value, x => x.AsInt32()); }
internal override int[] AsInt32Array() { return value.Select(x => x.AsInt32()).ToArray(); }
internal override long AsInt64()
{
......@@ -225,7 +226,7 @@ internal override long AsInt64()
throw new InvalidCastException();
}
internal override long[] AsInt64Array() { return Array.ConvertAll(value, x => x.AsInt64()); }
internal override long[] AsInt64Array() { return value.Select(x => x.AsInt64()).ToArray(); }
internal override bool? AsNullableBoolean()
{
......@@ -257,7 +258,7 @@ internal override RedisKey AsRedisKey()
throw new InvalidCastException();
}
internal override RedisKey[] AsRedisKeyArray() { return Array.ConvertAll(value, x => x.AsRedisKey()); }
internal override RedisKey[] AsRedisKeyArray() { return value.Select(x => x.AsRedisKey()).ToArray(); }
internal override RedisResult[] AsRedisResultArray() { return value; }
......@@ -267,14 +268,14 @@ internal override RedisValue AsRedisValue()
throw new InvalidCastException();
}
internal override RedisValue[] AsRedisValueArray() { return Array.ConvertAll(value, x => x.AsRedisValue()); }
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 Array.ConvertAll(value, x => x.AsString()); }
internal override string[] AsStringArray() { return value.Select(x => x.AsString()).ToArray(); }
}
private sealed class ErrorRedisResult : RedisResult
......
using System;
#if DNXCORE50
using System.Collections.Generic;
using System.Reflection;
#endif
using System.Text;
namespace StackExchange.Redis
......@@ -302,7 +306,12 @@ public int CompareTo(RedisValue other)
if (otherType == CompareType.Double) return thisDouble.CompareTo(otherDouble);
}
// otherwise, compare as strings
#if !DNXCORE50
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);
#endif
}
catch(Exception ex)
{
......@@ -601,7 +610,7 @@ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
if (conversionType== null) throw new ArgumentNullException("conversionType");
if (conversionType== typeof(byte[])) return (byte[])this;
if (conversionType == typeof(RedisValue)) return this;
switch(Type.GetTypeCode(conversionType))
switch(conversionType.GetTypeCode())
{
case TypeCode.Boolean: return (bool)this;
case TypeCode.Byte: return (byte)this;
......@@ -704,4 +713,48 @@ public bool TryParse(out double val)
return TryParseDouble(blob, out val);
}
}
internal static class ReflectionExtensions
{
#if DNXCORE50
internal static TypeCode GetTypeCode(this Type type)
{
if (type == null) return TypeCode.Empty;
TypeCode result;
if (typeCodeLookup.TryGetValue(type, out result)) return result;
if (type.GetTypeInfo().IsEnum)
{
type = Enum.GetUnderlyingType(type);
if (typeCodeLookup.TryGetValue(type, out result)) return result;
}
return TypeCode.Object;
}
static readonly Dictionary<Type, TypeCode> typeCodeLookup = new Dictionary<Type, TypeCode>
{
{typeof(bool), TypeCode.Boolean },
{typeof(byte), TypeCode.Byte },
{typeof(char), TypeCode.Char},
{typeof(DateTime), TypeCode.DateTime},
{typeof(decimal), TypeCode.Decimal},
{typeof(double), TypeCode.Double },
{typeof(short), TypeCode.Int16 },
{typeof(int), TypeCode.Int32 },
{typeof(long), TypeCode.Int64 },
{typeof(object), TypeCode.Object},
{typeof(sbyte), TypeCode.SByte },
{typeof(float), TypeCode.Single },
{typeof(string), TypeCode.String },
{typeof(ushort), TypeCode.UInt16 },
{typeof(uint), TypeCode.UInt32 },
{typeof(ulong), TypeCode.UInt64 },
};
#else
internal static TypeCode GetTypeCode(this Type type)
{
return type.GetTypeCode();
}
#endif
}
}
......@@ -347,7 +347,7 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
internal sealed class ScriptLoadProcessor : ResultProcessor<byte[]>
{
static readonly Regex sha1 = new Regex("^[0-9a-f]{40}$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
static readonly Regex sha1 = new Regex("^[0-9a-f]{40}$", InternalRegexCompiledOption.Default | RegexOptions.IgnoreCase);
internal static bool IsSHA1(string script)
{
......
......@@ -23,7 +23,7 @@ public ScriptParameters(RedisKey[] keys, RedisValue[] args)
}
}
static readonly Regex ParameterExtractor = new Regex(@"@(?<paramName> ([a-z]|_) ([a-z]|_|\d)*)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
static readonly Regex ParameterExtractor = new Regex(@"@(?<paramName> ([a-z]|_) ([a-z]|_|\d)*)", InternalRegexCompiledOption.Default | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
static string[] ExtractParameters(string script)
{
var ps = ParameterExtractor.Matches(script);
......@@ -313,7 +313,11 @@ 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 (t.IsValueType)
#else
if (t.GetTypeInfo().IsValueType)
#endif
{
il.Emit(OpCodes.Unbox_Any, t); // T
}
......@@ -344,7 +348,11 @@ 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 (t.IsValueType)
#else
if (t.GetTypeInfo().IsValueType)
#endif
{
il.Emit(OpCodes.Ldloca, loc); // RedisKey[] RedisKey[] int T*
}
......@@ -372,7 +380,11 @@ 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 (t.IsValueType)
#else
if (t.GetTypeInfo().IsValueType)
#endif
{
il.Emit(OpCodes.Ldloca, loc); // RedisKey[] RedisValue[] RedisValue[] int T*
}
......
......@@ -26,7 +26,7 @@ internal sealed partial class ServerEndPoint : IDisposable
{
internal volatile ServerEndPoint Master;
internal volatile ServerEndPoint[] Slaves = NoSlaves;
private static readonly Regex nameSanitizer = new Regex("[^!-~]", RegexOptions.Compiled);
private static readonly Regex nameSanitizer = new Regex("[^!-~]", InternalRegexCompiledOption.Default);
private static readonly ServerEndPoint[] NoSlaves = new ServerEndPoint[0];
private readonly EndPoint endpoint;
......@@ -484,7 +484,7 @@ internal void OnFullyEstablished(PhysicalConnection connection)
internal int LastInfoReplicationCheckSecondsAgo
{
get { return unchecked(Environment.TickCount - Thread.VolatileRead(ref lastInfoReplicationCheckTicks)) / 1000; }
get { return unchecked(Environment.TickCount - VolatileWrapper.Read(ref lastInfoReplicationCheckTicks)) / 1000; }
}
private EndPoint masterEndPoint;
......
#if __MonoCS__
#if !FEATURE_SOCKET_MODE_POLL
namespace StackExchange.Redis
{
......
using System;
#if FEATURE_SOCKET_MODE_POLL
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading;
#if !__MonoCS__
namespace StackExchange.Redis
{
......@@ -377,9 +377,9 @@ private void ReadImpl()
private void StartReader()
{
var thread = new Thread(read, 32 * 1024); // don't need a huge stack
thread.Priority = ThreadPriority.AboveNormal; // time critical
thread.Name = name + ":Read";
thread.IsBackground = true;
thread.Priority = ThreadPriority.AboveNormal; // time critical
thread.Start(this);
}
[StructLayout(LayoutKind.Sequential)]
......
......@@ -126,8 +126,12 @@ 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
Thread dedicatedWriter = new Thread(writeAllQueues, 32 * 1024); // don't need a huge stack;
dedicatedWriter.Priority = ThreadPriority.AboveNormal; // time critical
#else
Thread dedicatedWriter = new Thread(writeAllQueues);
#endif
dedicatedWriter.Name = name + ":Write";
dedicatedWriter.IsBackground = true; // should not keep process alive
dedicatedWriter.Start(this); // will self-exit when disposed
......@@ -217,6 +221,7 @@ 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;
// windows only
......@@ -230,6 +235,7 @@ internal void SetFastLoopbackOption(Socket socket)
socket.IOControl(SIO_LOOPBACK_FAST_PATH, optionInValue, null);
}
}
#endif
}
internal void RequestWrite(PhysicalBridge bridge, bool forced)
......@@ -334,7 +340,9 @@ private void Shutdown(Socket socket)
{
OnShutdown(socket);
try { socket.Shutdown(SocketShutdown.Both); } catch { }
#if !DNXCORE50
try { socket.Close(); } catch { }
#endif
try { socket.Dispose(); } catch { }
}
}
......
......@@ -32,13 +32,19 @@ public SortedSetEntry(RedisValue element, double score)
/// <summary>
/// The score against the element
/// </summary>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Score", false)]
#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>
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Element", false)]
#if !DNXCORE50
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Please use Element", false)]
public RedisValue Key { get { return element; } }
/// <summary>
......
......@@ -17,7 +17,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET40 STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;DEBUG;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -28,7 +28,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;NET40 STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
......@@ -43,7 +43,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET40 STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;NET40 STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize>
......@@ -85,6 +85,9 @@
<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>
......@@ -120,6 +123,7 @@
<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" />
......
......@@ -17,7 +17,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET40</DefineConstants>
<DefineConstants>TRACE;DEBUG;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -28,7 +28,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NET40</DefineConstants>
<DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
......@@ -37,7 +37,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET40</DefineConstants>
<DefineConstants>TRACE;NET40 FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
<Optimize>true</Optimize>
......@@ -82,6 +82,9 @@
<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>
......@@ -117,6 +120,7 @@
<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" />
......
......@@ -18,7 +18,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin.snk\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET46 PLAT_SAFE_CONTINUATIONS STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;DEBUG;NET46 PLAT_SAFE_CONTINUATIONS STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -30,7 +30,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin.snk\Release\</OutputPath>
<DefineConstants>TRACE;NET46 PLAT_SAFE_CONTINUATIONS STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;NET46 PLAT_SAFE_CONTINUATIONS STRONG_NAME FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
......@@ -46,7 +46,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET46 PLAT_SAFE_CONTINUATIONS STRONG_NAME</DefineConstants>
<DefineConstants>TRACE;NET46 PLAT_SAFE_CONTINUATIONS STRONG_NAME FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin.snk\Release\StackExchange.Redis.StrongName.xml</DocumentationFile>
<Optimize>true</Optimize>
......@@ -71,6 +71,9 @@
<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>
......@@ -106,6 +109,7 @@
<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" />
......
......@@ -18,7 +18,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET46 PLAT_SAFE_CONTINUATIONS</DefineConstants>
<DefineConstants>TRACE;DEBUG;NET46 PLAT_SAFE_CONTINUATIONS FEATURE_SERIALIZATION;FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
......@@ -30,7 +30,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NET46 PLAT_SAFE_CONTINUATIONS</DefineConstants>
<DefineConstants>TRACE;NET46 PLAT_SAFE_CONTINUATIONS FEATURE_SERIALIZATION FEATURE_SOCKET_MODE_POLL</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
......@@ -40,7 +40,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Mono|AnyCPU'">
<OutputPath>bin\Mono\</OutputPath>
<DefineConstants>TRACE;NET46 PLAT_SAFE_CONTINUATIONS</DefineConstants>
<DefineConstants>TRACE;NET46 PLAT_SAFE_CONTINUATIONS FEATURE_SERIALIZATION</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\StackExchange.Redis.xml</DocumentationFile>
<Optimize>true</Optimize>
......@@ -65,6 +65,9 @@
<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>
......@@ -100,6 +103,7 @@
<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" />
......
<?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)' != ''" />
</Project>
\ No newline at end of file
{
"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",
"runtime": "coreclr",
"architecture": "x86"
},
"projects": [ "StackExchange.Redis_dnxcore50" ]
}
Copyright © 2002-2014 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-2014 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.
This diff is collapsed.
Copyright (c) 2015 Charlie Poole
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
NUnit 3.0 is based on earlier versions of NUnit, with Portions
Copyright (c) 2002-2014 Charlie Poole or
Copyright (c) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or
Copyright (c) 2000-2002 Philip A. Craig
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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