Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
StackExchange.Redis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tsai
StackExchange.Redis
Commits
c54c0671
Commit
c54c0671
authored
May 28, 2018
by
Nick Craver
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PoC: Dropping netstandard1.x support
A demo of how much this saves in complexity.
parent
d7c72b05
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
117 additions
and
588 deletions
+117
-588
BasicTest.csproj
BasicTest/BasicTest.csproj
+1
-5
Directory.build.props
Directory.build.props
+1
-1
NRediSearch.Test.csproj
NRediSearch.Test/NRediSearch.Test.csproj
+1
-1
StackExchange.Redis.StrongName.csproj
...ge.Redis.StrongName/StackExchange.Redis.StrongName.csproj
+2
-13
Config.cs
StackExchange.Redis.Tests/Booksleeve/Config.cs
+2
-6
Config.cs
StackExchange.Redis.Tests/Config.cs
+1
-5
Extensions.cs
StackExchange.Redis.Tests/Helpers/Extensions.cs
+0
-2
TestConfig.cs
StackExchange.Redis.Tests/Helpers/TestConfig.cs
+1
-4
MassiveOps.cs
StackExchange.Redis.Tests/MassiveOps.cs
+0
-10
Naming.cs
StackExchange.Redis.Tests/Naming.cs
+6
-49
Profiling.cs
StackExchange.Redis.Tests/Profiling.cs
+3
-6
PubSub.cs
StackExchange.Redis.Tests/PubSub.cs
+18
-30
StackExchange.Redis.Tests.csproj
StackExchange.Redis.Tests/StackExchange.Redis.Tests.csproj
+2
-11
TaskTests.cs
StackExchange.Redis.Tests/TaskTests.cs
+1
-5
TestBase.cs
StackExchange.Redis.Tests/TestBase.cs
+0
-13
StackExchange.Redis.csproj
StackExchange.Redis/StackExchange.Redis.csproj
+0
-11
BrowsableAttribute.cs
...ge.Redis/StackExchange/Redis/Compat/BrowsableAttribute.cs
+0
-15
ConvertHelper.cs
...xchange.Redis/StackExchange/Redis/Compat/ConvertHelper.cs
+0
-30
VolatileWrapper.cs
...hange.Redis/StackExchange/Redis/Compat/VolatileWrapper.cs
+0
-23
ConfigurationOptions.cs
...xchange.Redis/StackExchange/Redis/ConfigurationOptions.cs
+3
-12
ConnectionMultiplexer.cs
...change.Redis/StackExchange/Redis/ConnectionMultiplexer.cs
+3
-23
Exceptions.cs
StackExchange.Redis/StackExchange/Redis/Exceptions.cs
+48
-67
ExtensionMethods.cs
StackExchange.Redis/StackExchange/Redis/ExtensionMethods.cs
+1
-10
PhysicalBridge.cs
StackExchange.Redis/StackExchange/Redis/PhysicalBridge.cs
+1
-1
PhysicalConnection.cs
...kExchange.Redis/StackExchange/Redis/PhysicalConnection.cs
+9
-93
RedisResult.cs
StackExchange.Redis/StackExchange/Redis/RedisResult.cs
+8
-8
RedisValue.cs
StackExchange.Redis/StackExchange/Redis/RedisValue.cs
+3
-55
ResultBox.cs
StackExchange.Redis/StackExchange/Redis/ResultBox.cs
+0
-4
ScriptParameterMapper.cs
...change.Redis/StackExchange/Redis/ScriptParameterMapper.cs
+0
-12
ServerEndPoint.cs
StackExchange.Redis/StackExchange/Redis/ServerEndPoint.cs
+1
-1
SocketManager.cs
StackExchange.Redis/StackExchange/Redis/SocketManager.cs
+0
-53
TaskSource.cs
StackExchange.Redis/StackExchange/Redis/TaskSource.cs
+1
-9
No files found.
BasicTest/BasicTest.csproj
View file @
c54c0671
...
...
@@ -2,7 +2,7 @@
<PropertyGroup>
<Description>StackExchange.Redis.BasicTest .NET Core</Description>
<TargetFrameworks>netcoreapp
1.1;netcoreapp
2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
<AssemblyName>BasicTest</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>BasicTest</PackageId>
...
...
@@ -14,8 +14,4 @@
<ProjectReference Include="..\StackExchange.Redis\StackExchange.Redis.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.1' ">
<PackageReference Include="System.Console" Version="$(CoreFxVersion)" />
</ItemGroup>
</Project>
Directory.build.props
View file @
c54c0671
...
...
@@ -22,7 +22,7 @@
<DefaultLanguage>en-US</DefaultLanguage>
<IncludeSymbols>false</IncludeSymbols>
<LibraryTargetFrameworks>net45;net46;netstandard
1.5;netstandard
2.0</LibraryTargetFrameworks>
<LibraryTargetFrameworks>net45;net46;netstandard2.0</LibraryTargetFrameworks>
<CoreFxVersion>4.3.0</CoreFxVersion>
<xUnitVersion>2.4.0-beta.2.build3981</xUnitVersion>
</PropertyGroup>
...
...
NRediSearch.Test/NRediSearch.Test.csproj
View file @
c54c0671
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFrameworks>netcoreapp
1.1;netcoreapp
2.0</TargetFrameworks>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
...
...
StackExchange.Redis.StrongName/StackExchange.Redis.StrongName.csproj
View file @
c54c0671
...
...
@@ -21,27 +21,16 @@
</ItemGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net46'">
<DefineConstants>$(DefineConstants);FEATURE_S
ERIALIZATION;FEATURE_S
OCKET_MODE_POLL;FEATURE_PERFCOUNTER;FEATURE_THREADPOOL</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_SOCKET_MODE_POLL;FEATURE_PERFCOUNTER;FEATURE_THREADPOOL</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.IO.Compression" Version="$(CoreFxVersion)" />
</ItemGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<DefineConstants>$(DefineConstants);FEATURE_
SERIALIZATION;FEATURE_
THREADPOOL</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_THREADPOOL</DefineConstants>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' ">
<PackageReference Include="System.Collections.NonGeneric" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Net.NameResolution" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Net.Security" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.Emit" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Threading.Thread" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Threading.ThreadPool" Version="$(CoreFxVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.Emit.ILGeneration" Version="$(CoreFxVersion)" />
...
...
StackExchange.Redis.Tests/Booksleeve/Config.cs
View file @
c54c0671
...
...
@@ -4,9 +4,7 @@
using
System.Threading.Tasks
;
using
Xunit
;
using
Xunit.Abstractions
;
#if !NETCOREAPP1_0
using
System.Security.Authentication
;
#endif
namespace
StackExchange.Redis.Tests.Booksleeve
{
...
...
@@ -106,8 +104,7 @@ public void CreateDisconnectedNonsenseConnection_DNS()
Output
.
WriteLine
(
log
.
ToString
());
}
}
#if !NETCOREAPP1_0
[
Fact
]
public
void
SslProtocols_SingleValue
()
{
...
...
@@ -143,7 +140,6 @@ public void SslProtocols_InvalidValue()
var
log
=
new
StringWriter
();
Assert
.
Throws
<
ArgumentOutOfRangeException
>(()
=>
ConfigurationOptions
.
Parse
(
"myhost,sslProtocols=InvalidSslProtocol"
));
}
#endif
[
Fact
]
public
void
ConfigurationOptionsDefaultForAzure
()
...
...
@@ -202,4 +198,4 @@ public void ConfigurationOptionsDefaultWhenNoEndpointsSpecifiedYet()
Assert
.
True
(
options
.
AbortOnConnectFail
);
}
}
}
\ No newline at end of file
}
StackExchange.Redis.Tests/Config.cs
View file @
c54c0671
...
...
@@ -161,12 +161,8 @@ public void ReadConfig()
var
conn
=
GetAnyMaster
(
muxer
);
var
all
=
conn
.
ConfigGet
();
Assert
.
True
(
all
.
Length
>
0
,
"any"
);
#if !NETCOREAPP1_0
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
.
Equal
(
all
.
Length
,
pairs
.
Count
);
Assert
.
True
(
pairs
.
ContainsKey
(
"timeout"
),
"timeout"
);
...
...
StackExchange.Redis.Tests/Helpers/Extensions.cs
View file @
c54c0671
...
...
@@ -12,8 +12,6 @@ static Extensions()
{
#if NET462
VersionInfo
=
"Compiled under .NET 4.6.2"
;
#elif NETCOREAPP1_0
VersionInfo
=
"Compiled under .NETCoreApp1.0"
;
#elif NETCOREAPP2_0
VersionInfo
=
"Compiled under .NETCoreApp2.0"
;
#else
...
...
StackExchange.Redis.Tests/Helpers/TestConfig.cs
View file @
c54c0671
...
...
@@ -2,9 +2,6 @@
using
Jil
;
using
System
;
using
System.Collections.Generic
;
#if NETCOREAPP1_0
using
System.Reflection
;
#endif
namespace
StackExchange.Redis.Tests
{
...
...
@@ -19,7 +16,7 @@ static TestConfig()
Current
=
new
Config
();
try
{
using
(
var
stream
=
typeof
(
TestConfig
).
GetTypeInfo
().
Assembly
.
GetManifestResourceStream
(
"StackExchange.Redis.Tests."
+
FileName
))
using
(
var
stream
=
typeof
(
TestConfig
).
Assembly
.
GetManifestResourceStream
(
"StackExchange.Redis.Tests."
+
FileName
))
{
if
(
stream
!=
null
)
{
...
...
StackExchange.Redis.Tests/MassiveOps.cs
View file @
c54c0671
...
...
@@ -28,19 +28,9 @@ public async Task MassiveBulkOpsAsync(bool preserveOrder, bool withContinuation)
RedisKey
key
=
"MBOA"
;
var
conn
=
muxer
.
GetDatabase
();
await
conn
.
PingAsync
().
ForAwait
();
#if NETCOREAPP1_0
int
number
=
0
;
#endif
Action
<
Task
>
nonTrivial
=
delegate
{
#if NETCOREAPP1_0
for
(
int
i
=
0
;
i
<
50
;
i
++)
{
number
++;
}
#else
Thread
.
SpinWait
(
5
);
#endif
};
var
watch
=
Stopwatch
.
StartNew
();
for
(
int
i
=
0
;
i
<=
AsyncOpsQty
;
i
++)
...
...
StackExchange.Redis.Tests/Naming.cs
View file @
c54c0671
...
...
@@ -20,7 +20,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
.
GetTypeInfo
()
,
isAsync
);
CheckName
(
type
,
isAsync
);
var
members
=
type
.
GetMethods
(
BindingFlags
.
Public
|
BindingFlags
.
Instance
|
BindingFlags
.
Static
|
BindingFlags
.
DeclaredOnly
);
foreach
(
var
member
in
members
)
{
...
...
@@ -32,9 +32,9 @@ public void CheckSignatures(Type type, bool isAsync)
[
Fact
]
public
void
ShowReadOnlyOperations
()
{
var
msg
=
typeof
(
ConnectionMultiplexer
).
GetTypeInfo
().
Assembly
.
GetType
(
"StackExchange.Redis.Message"
);
var
msg
=
typeof
(
ConnectionMultiplexer
).
Assembly
.
GetType
(
"StackExchange.Redis.Message"
);
Assert
.
NotNull
(
msg
);
var
cmd
=
typeof
(
ConnectionMultiplexer
).
GetTypeInfo
().
Assembly
.
GetType
(
"StackExchange.Redis.RedisCommand"
);
var
cmd
=
typeof
(
ConnectionMultiplexer
).
Assembly
.
GetType
(
"StackExchange.Redis.RedisCommand"
);
Assert
.
NotNull
(
cmd
);
var
masterOnlyMethod
=
msg
.
GetMethod
(
nameof
(
Message
.
IsMasterOnly
),
BindingFlags
.
Static
|
BindingFlags
.
NonPublic
|
BindingFlags
.
Public
);
Assert
.
NotNull
(
masterOnlyMethod
);
...
...
@@ -103,7 +103,7 @@ private static bool UsesKey(Type type)
{
if
(
UsesKey
(
type
.
GetElementType
()))
return
true
;
}
if
(
type
.
GetTypeInfo
().
IsGenericType
)
// KVP, etc
if
(
type
.
IsGenericType
)
// KVP, etc
{
var
args
=
type
.
GetGenericArguments
();
if
(
args
.
Any
(
UsesKey
))
return
true
;
...
...
@@ -156,7 +156,7 @@ public void CheckSyncAsyncMethodsMatch(Type from, Type to)
{
huntType
=
null
;
}
else
if
(
method
.
ReturnType
.
GetTypeInfo
().
IsSubclassOf
(
typeof
(
Task
)))
else
if
(
method
.
ReturnType
.
IsSubclassOf
(
typeof
(
Task
)))
{
huntType
=
method
.
ReturnType
.
GetGenericArguments
()[
0
];
}
...
...
@@ -168,12 +168,7 @@ public void CheckSyncAsyncMethodsMatch(Type from, Type to)
Type
[]
args
=
pFrom
.
Select
(
x
=>
x
.
ParameterType
).
ToArray
();
Output
.
WriteLine
(
"Checking: {0}.{1}"
,
from
.
Name
,
method
.
Name
);
Assert
.
Equal
(
typeof
(
CommandFlags
),
args
.
Last
());
#if !NETCOREAPP1_0
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
.
NotNull
(
found
);
// "Found " + name + ", no " + huntName
var
pTo
=
found
.
GetParameters
();
...
...
@@ -188,22 +183,14 @@ public void CheckSyncAsyncMethodsMatch(Type from, Type to)
Output
.
WriteLine
(
"Validated: {0} ({1} methods)"
,
from
.
Name
,
count
);
}
private
static
readonly
Type
ignoreType
=
typeof
(
ConnectionMultiplexer
).
GetTypeInfo
().
Assembly
.
GetType
(
"StackExchange.Redis.IgnoreNamePrefixAttribute"
);
private
static
readonly
Type
ignoreType
=
typeof
(
ConnectionMultiplexer
).
Assembly
.
GetType
(
"StackExchange.Redis.IgnoreNamePrefixAttribute"
);
private
void
CheckMethod
(
MethodInfo
method
,
bool
isAsync
)
{
#if DEBUG
#if !NETCOREAPP1_0
bool
ignorePrefix
=
ignoreType
!=
null
&&
Attribute
.
IsDefined
(
method
,
ignoreType
);
#else
bool
ignorePrefix
=
ignoreType
!=
null
&&
method
.
IsDefined
(
ignoreType
);
#endif
if
(
ignorePrefix
)
{
#if !NETCOREAPP1_0
Attribute
attrib
=
Attribute
.
GetCustomAttribute
(
method
,
ignoreType
);
#else
Attribute
attrib
=
method
.
GetCustomAttribute
(
ignoreType
);
#endif
if
((
bool
)
attrib
.
GetType
().
GetProperty
(
"IgnoreEntireMethod"
).
GetValue
(
attrib
))
{
return
;
...
...
@@ -250,34 +237,4 @@ private void CheckName(MemberInfo member, bool isAsync)
else
Assert
.
False
(
member
.
Name
.
EndsWith
(
"Async"
),
member
.
Name
+
":Name - don't end *Async"
);
}
}
public
static
class
ReflectionExtensions
{
#if !NETCOREAPP1_0
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
}
}
StackExchange.Redis.Tests/Profiling.cs
View file @
c54c0671
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
#if NETCOREAPP1_0
using
System.Reflection
;
#endif
using
System.Threading.Tasks
;
using
System.Threading
;
using
System.Collections.Concurrent
;
...
...
@@ -430,11 +427,11 @@ public void LowAllocationEnumerable()
conn
.
WaitAll
(
allTasks
.
ToArray
());
var
res
=
conn
.
FinishProfiling
(
profiler
.
MyContext
);
Assert
.
True
(
res
.
GetType
().
GetTypeInfo
().
IsValueType
);
Assert
.
True
(
res
.
GetType
().
IsValueType
);
using
(
var
e
=
res
.
GetEnumerator
())
{
Assert
.
True
(
e
.
GetType
().
GetTypeInfo
().
IsValueType
);
Assert
.
True
(
e
.
GetType
().
IsValueType
);
Assert
.
True
(
e
.
MoveNext
());
var
i
=
e
.
Current
;
...
...
@@ -557,4 +554,4 @@ public void ProfilingMD_Ex2()
}
}
}
}
\ No newline at end of file
}
StackExchange.Redis.Tests/PubSub.cs
View file @
c54c0671
...
...
@@ -27,17 +27,17 @@ public void ExplicitPublishMode()
Thread
.
Sleep
(
1000
);
pub
.
Publish
(
"abcd"
,
"efg"
);
Thread
.
Sleep
(
500
);
Assert
.
Equal
(
0
,
VolatileWrapper
.
Read
(
ref
a
));
Assert
.
Equal
(
1
,
VolatileWrapper
.
Read
(
ref
b
));
Assert
.
Equal
(
1
,
VolatileWrapper
.
Read
(
ref
c
));
Assert
.
Equal
(
1
,
VolatileWrapper
.
Read
(
ref
d
));
Assert
.
Equal
(
0
,
Thread
.
Volatile
Read
(
ref
a
));
Assert
.
Equal
(
1
,
Thread
.
Volatile
Read
(
ref
b
));
Assert
.
Equal
(
1
,
Thread
.
Volatile
Read
(
ref
c
));
Assert
.
Equal
(
1
,
Thread
.
Volatile
Read
(
ref
d
));
pub
.
Publish
(
"*bcd"
,
"efg"
);
Thread
.
Sleep
(
500
);
Assert
.
Equal
(
1
,
VolatileWrapper
.
Read
(
ref
a
));
//Assert.Equal(1,
VolatileWrapper.
Read(ref b));
//Assert.Equal(1,
VolatileWrapper.
Read(ref c));
//Assert.Equal(1,
VolatileWrapper.
Read(ref d));
Assert
.
Equal
(
1
,
Thread
.
Volatile
Read
(
ref
a
));
//Assert.Equal(1,
Thread.Volatile
Read(ref b));
//Assert.Equal(1,
Thread.Volatile
Read(ref c));
//Assert.Equal(1,
Thread.Volatile
Read(ref d));
}
}
...
...
@@ -89,7 +89,7 @@ public void TestBasicPubSub(bool preserveOrder, string channelPrefix, bool wildC
{
Assert
.
Empty
(
received
);
}
Assert
.
Equal
(
0
,
VolatileWrapper
.
Read
(
ref
secondHandler
));
Assert
.
Equal
(
0
,
Thread
.
Volatile
Read
(
ref
secondHandler
));
var
count
=
sub
.
Publish
(
pubChannel
,
"def"
);
Ping
(
muxer
,
pub
,
sub
,
3
);
...
...
@@ -98,7 +98,7 @@ public void TestBasicPubSub(bool preserveOrder, string channelPrefix, bool wildC
{
Assert
.
Single
(
received
);
}
Assert
.
Equal
(
1
,
VolatileWrapper
.
Read
(
ref
secondHandler
));
Assert
.
Equal
(
1
,
Thread
.
Volatile
Read
(
ref
secondHandler
));
// unsubscribe from first; should still see second
sub
.
Unsubscribe
(
subChannel
,
handler1
);
...
...
@@ -108,7 +108,7 @@ public void TestBasicPubSub(bool preserveOrder, string channelPrefix, bool wildC
{
Assert
.
Single
(
received
);
}
Assert
.
Equal
(
2
,
VolatileWrapper
.
Read
(
ref
secondHandler
));
Assert
.
Equal
(
2
,
Thread
.
Volatile
Read
(
ref
secondHandler
));
Assert
.
Equal
(
1
,
count
);
// unsubscribe from second; should see nothing this time
...
...
@@ -119,7 +119,7 @@ public void TestBasicPubSub(bool preserveOrder, string channelPrefix, bool wildC
{
Assert
.
Single
(
received
);
}
Assert
.
Equal
(
2
,
VolatileWrapper
.
Read
(
ref
secondHandler
));
Assert
.
Equal
(
2
,
Thread
.
Volatile
Read
(
ref
secondHandler
));
Assert
.
Equal
(
0
,
count
);
}
}
...
...
@@ -156,7 +156,7 @@ public void TestBasicPubSubFireAndForget(bool preserveOrder)
{
Assert
.
Empty
(
received
);
}
Assert
.
Equal
(
0
,
VolatileWrapper
.
Read
(
ref
secondHandler
));
Assert
.
Equal
(
0
,
Thread
.
Volatile
Read
(
ref
secondHandler
));
Ping
(
muxer
,
pub
,
sub
);
var
count
=
sub
.
Publish
(
key
,
"def"
,
CommandFlags
.
FireAndForget
);
Ping
(
muxer
,
pub
,
sub
);
...
...
@@ -165,7 +165,7 @@ public void TestBasicPubSubFireAndForget(bool preserveOrder)
{
Assert
.
Single
(
received
);
}
Assert
.
Equal
(
1
,
VolatileWrapper
.
Read
(
ref
secondHandler
));
Assert
.
Equal
(
1
,
Thread
.
Volatile
Read
(
ref
secondHandler
));
sub
.
Unsubscribe
(
key
);
count
=
sub
.
Publish
(
key
,
"ghi"
,
CommandFlags
.
FireAndForget
);
...
...
@@ -228,7 +228,7 @@ public void TestPatternPubSub(bool preserveOrder)
{
Assert
.
Empty
(
received
);
}
Assert
.
Equal
(
0
,
VolatileWrapper
.
Read
(
ref
secondHandler
));
Assert
.
Equal
(
0
,
Thread
.
Volatile
Read
(
ref
secondHandler
));
var
count
=
sub
.
Publish
(
"abc"
,
"def"
);
Ping
(
muxer
,
pub
,
sub
);
...
...
@@ -237,7 +237,7 @@ public void TestPatternPubSub(bool preserveOrder)
{
Assert
.
Single
(
received
);
}
Assert
.
Equal
(
1
,
VolatileWrapper
.
Read
(
ref
secondHandler
));
Assert
.
Equal
(
1
,
Thread
.
Volatile
Read
(
ref
secondHandler
));
sub
.
Unsubscribe
(
"a*c"
);
count
=
sub
.
Publish
(
"abc"
,
"ghi"
);
...
...
@@ -268,7 +268,7 @@ public async Task SubscriptionsSurviveConnectionFailureAsync()
await
sub
.
PublishAsync
(
channel
,
"abc"
).
ConfigureAwait
(
false
);
sub
.
Ping
();
await
Task
.
Delay
(
200
).
ConfigureAwait
(
false
);
Assert
.
Equal
(
1
,
VolatileWrapper
.
Read
(
ref
counter
));
Assert
.
Equal
(
1
,
Thread
.
Volatile
Read
(
ref
counter
));
var
server
=
GetServer
(
muxer
);
Assert
.
Equal
(
1
,
server
.
GetCounters
().
Subscription
.
SocketCount
);
...
...
@@ -280,21 +280,9 @@ public async Task SubscriptionsSurviveConnectionFailureAsync()
await
sub
.
PublishAsync
(
channel
,
"abc"
).
ConfigureAwait
(
false
);
await
Task
.
Delay
(
200
).
ConfigureAwait
(
false
);
sub
.
Ping
();
Assert
.
Equal
(
2
,
VolatileWrapper
.
Read
(
ref
counter
));
Assert
.
Equal
(
2
,
Thread
.
Volatile
Read
(
ref
counter
));
}
}
#endif
}
internal
static
class
VolatileWrapper
{
public
static
int
Read
(
ref
int
location
)
{
#if !NETCOREAPP1_0
return
Thread
.
VolatileRead
(
ref
location
);
#else
return
Volatile
.
Read
(
ref
location
);
#endif
}
}
}
StackExchange.Redis.Tests/StackExchange.Redis.Tests.csproj
View file @
c54c0671
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>StackExchange.Redis.Tests</Description>
<TargetFrameworks>net462;netcoreapp
1.0;netcoreapp
2.0</TargetFrameworks>
<TargetFrameworks>net462;netcoreapp2.0</TargetFrameworks>
<AssemblyName>StackExchange.Redis.Tests</AssemblyName>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<DebugType>full</DebugType>
</PropertyGroup>
<ItemGroup>
<None Update="*.json" CopyToOutputDirectory="Always" />
<EmbeddedResource Include="*Config.json" />
...
...
@@ -28,13 +28,4 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' ">
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">
<PackageReference Include="System.Console" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Diagnostics.Debug" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Linq.Expressions" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.Extensions" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Runtime.InteropServices" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Threading.Tasks.Parallel" Version="$(CoreFxVersion)" />
<PackageReference Include="Microsoft.CSharp" Version="$(CoreFxVersion)" />
</ItemGroup>
</Project>
StackExchange.Redis.Tests/TaskTests.cs
View file @
c54c0671
...
...
@@ -9,7 +9,6 @@ public class TaskTests
{
#if DEBUG
#if !PLAT_SAFE_CONTINUATIONS // IsSyncSafe doesn't exist if PLAT_SAFE_CONTINUATIONS is defined
[
Theory
]
[
InlineData
(
SourceOrign
.
NewTCS
)]
[
InlineData
(
SourceOrign
.
Create
)]
...
...
@@ -20,13 +19,10 @@ public void VerifyIsSyncSafe(SourceOrign origin)
// ...and if we're dropping NET45 support, we can just nuke it all.
#if NET462
Assert
.
True
(
TaskSource
.
IsSyncSafe
(
source
.
Task
));
#elif NETCOREAPP1_0
Assert
.
True
(
TaskSource
.
IsSyncSafe
(
source
.
Task
));
#elif NETCOREAPP2_0
Assert
.
True
(
TaskSource
.
IsSyncSafe
(
source
.
Task
));
#endif
}
#endif
private
static
TaskCompletionSource
<
T
>
Create
<
T
>(
SourceOrign
origin
)
{
switch
(
origin
)
...
...
@@ -123,4 +119,4 @@ private async void DoAwait(Task task)
}
#endif
}
}
\ No newline at end of file
}
StackExchange.Redis.Tests/TestBase.cs
View file @
c54c0671
...
...
@@ -59,9 +59,6 @@ static TestBase()
{
Console
.
WriteLine
(
"Unobserved: "
+
args
.
Exception
);
args
.
SetObserved
();
#if NETCOREAPP1_0
if
(
IgnorableExceptionPredicates
.
Any
(
predicate
=>
predicate
(
args
.
Exception
.
InnerException
)))
return
;
#endif
lock
(
sharedFailCount
)
{
if
(
sharedFailCount
!=
null
)
...
...
@@ -76,14 +73,6 @@ static TestBase()
};
}
#if NETCOREAPP1_0
private
static
readonly
Func
<
Exception
,
bool
>[]
IgnorableExceptionPredicates
=
new
Func
<
Exception
,
bool
>[]
{
e
=>
e
!=
null
&&
e
is
ObjectDisposedException
&&
e
.
Message
.
Equals
(
"Cannot access a disposed object.\r\nObject name: 'System.Net.Sockets.NetworkStream'."
),
e
=>
e
!=
null
&&
e
is
IOException
&&
e
.
Message
.
StartsWith
(
"Unable to read data from the transport connection:"
)
};
#endif
protected
void
OnConnectionFailed
(
object
sender
,
ConnectionFailedEventArgs
e
)
{
Interlocked
.
Increment
(
ref
privateFailCount
);
...
...
@@ -318,13 +307,11 @@ protected static TimeSpan RunConcurrent(Action work, int threads, int timeout =
}
if
(!
allDone
.
WaitOne
(
timeout
))
{
#if !NETCOREAPP1_0
for
(
int
i
=
0
;
i
<
threads
;
i
++)
{
var
thd
=
threadArr
[
i
];
if
(
thd
.
IsAlive
)
thd
.
Abort
();
}
#endif
throw
new
TimeoutException
();
}
...
...
StackExchange.Redis/StackExchange.Redis.csproj
View file @
c54c0671
...
...
@@ -27,17 +27,6 @@
<DefineConstants>$(DefineConstants);FEATURE_SERIALIZATION;FEATURE_THREADPOOL</DefineConstants>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' ">
<PackageReference Include="System.Collections.NonGeneric" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Net.NameResolution" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Net.Security" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.Emit" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Threading.Thread" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Threading.ThreadPool" Version="$(CoreFxVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Reflection.Emit.ILGeneration" Version="$(CoreFxVersion)" />
...
...
StackExchange.Redis/StackExchange/Redis/Compat/BrowsableAttribute.cs
deleted
100644 → 0
View file @
d7c72b05
#
if
NETSTANDARD1_5
using
System
;
namespace
StackExchange.Redis
{
/// <summary>
/// Strictly for compat and less #if defs on netstandard1.5
/// </summary>
[
AttributeUsage
(
AttributeTargets
.
All
,
AllowMultiple
=
false
)]
internal
class
BrowsableAttribute
:
Attribute
{
public
BrowsableAttribute
(
bool
_
)
{
}
}
}
#
endif
\ No newline at end of file
StackExchange.Redis/StackExchange/Redis/Compat/ConvertHelper.cs
deleted
100644 → 0
View file @
d7c72b05
using
System
;
namespace
StackExchange.Redis
{
/// <summary>
/// Helper for Array.ConvertAll() as it's missing on .Net Core.
/// </summary>
public
static
class
ConvertHelper
{
/// <summary>
/// Converts array of one type to an array of another type.
/// </summary>
/// <typeparam name="TInput">Input type</typeparam>
/// <typeparam name="TOutput">Output type</typeparam>
/// <param name="source">source</param>
/// <param name="selector">selector</param>
/// <returns></returns>
public
static
TOutput
[]
ConvertAll
<
TInput
,
TOutput
>(
TInput
[]
source
,
Func
<
TInput
,
TOutput
>
selector
)
{
#if NETSTANDARD1_5
TOutput
[]
arr
=
new
TOutput
[
source
.
Length
];
for
(
int
i
=
0
;
i
<
arr
.
Length
;
i
++)
arr
[
i
]
=
selector
(
source
[
i
]);
return
arr
;
#else
return
Array
.
ConvertAll
(
source
,
item
=>
selector
(
item
));
#endif
}
}
}
StackExchange.Redis/StackExchange/Redis/Compat/VolatileWrapper.cs
deleted
100644 → 0
View file @
d7c72b05
namespace
StackExchange.Redis
{
internal
static
class
VolatileWrapper
{
public
static
int
Read
(
ref
int
location
)
{
#if NETSTANDARD1_5
return
System
.
Threading
.
Volatile
.
Read
(
ref
location
);
#else
return
System
.
Threading
.
Thread
.
VolatileRead
(
ref
location
);
#endif
}
public
static
void
Write
(
ref
int
address
,
int
value
)
{
#if NETSTANDARD1_5
System
.
Threading
.
Volatile
.
Write
(
ref
address
,
value
);
#else
System
.
Threading
.
Thread
.
VolatileWrite
(
ref
address
,
value
);
#endif
}
}
}
StackExchange.Redis/StackExchange/Redis/ConfigurationOptions.cs
View file @
c54c0671
...
...
@@ -14,10 +14,7 @@ namespace StackExchange.Redis
/// <summary>
/// The options relevant to a set of redis connections
/// </summary>
public
sealed
class
ConfigurationOptions
#if !NETSTANDARD1_5
:
ICloneable
#endif
public
sealed
class
ConfigurationOptions
:
ICloneable
{
internal
const
string
DefaultTieBreaker
=
"__Booksleeve_TieBreak"
,
DefaultConfigurationChannel
=
"__Booksleeve_MasterChanged"
;
...
...
@@ -398,9 +395,7 @@ public ConfigurationOptions Clone()
DefaultDatabase
=
DefaultDatabase
,
ReconnectRetryPolicy
=
reconnectRetryPolicy
,
preserveAsyncOrder
=
preserveAsyncOrder
,
#if !NETSTANDARD1_5
SslProtocols
=
SslProtocols
,
#endif
};
foreach
(
var
item
in
EndPoints
)
options
.
EndPoints
.
Add
(
item
);
...
...
@@ -547,9 +542,7 @@ private void Clear()
SocketManager
=
null
;
}
#if !NETSTANDARD1_5
object
ICloneable
.
Clone
()
{
return
Clone
();
}
#endif
object
ICloneable
.
Clone
()
=>
Clone
();
private
void
DoParse
(
string
configuration
,
bool
ignoreUnknown
)
{
...
...
@@ -652,11 +645,9 @@ private void DoParse(string configuration, bool ignoreUnknown)
case
OptionKeys
.
PreserveAsyncOrder
:
PreserveAsyncOrder
=
OptionKeys
.
ParseBoolean
(
key
,
value
);
break
;
#if !NETSTANDARD1_5
case
OptionKeys
.
SslProtocols
:
SslProtocols
=
OptionKeys
.
ParseSslProtocols
(
key
,
value
);
break
;
#endif
default
:
if
(!
string
.
IsNullOrEmpty
(
key
)
&&
key
[
0
]
==
'$'
)
{
...
...
@@ -731,4 +722,4 @@ private string InferSslHostFromEndpoints()
return
null
;
}
}
}
\ No newline at end of file
}
StackExchange.Redis/StackExchange/Redis/ConnectionMultiplexer.cs
View file @
c54c0671
...
...
@@ -69,9 +69,6 @@ private static string GetDefaultClientName()
/// </summary>
internal
static
string
TryGetAzureRoleInstanceIdNoThrow
()
{
#if NETSTANDARD1_5
return
null
;
#else
string
roleInstanceId
=
null
;
// TODO: CoreCLR port pending https://github.com/dotnet/coreclr/issues/919
try
...
...
@@ -109,7 +106,6 @@ internal static string TryGetAzureRoleInstanceIdNoThrow()
roleInstanceId
=
null
;
}
return
roleInstanceId
;
#endif
}
/// <summary>
...
...
@@ -504,7 +500,7 @@ public EndPoint[] GetEndPoints(bool configuredOnly = false)
{
if
(
configuredOnly
)
return
configuration
.
EndPoints
.
ToArray
();
return
ConvertHelper
.
ConvertAll
(
serverSnapshot
,
x
=>
x
.
EndPoint
);
return
Array
.
ConvertAll
(
serverSnapshot
,
x
=>
x
.
EndPoint
);
}
private
readonly
ConfigurationOptions
configuration
;
...
...
@@ -581,7 +577,6 @@ private static bool WaitAllIgnoreErrors(Task[] tasks, int timeout)
return
false
;
}
#if FEATURE_THREADPOOL
private
void
LogLockedWithThreadPoolStats
(
TextWriter
log
,
string
message
,
out
int
busyWorkerCount
)
{
busyWorkerCount
=
0
;
...
...
@@ -594,7 +589,6 @@ private void LogLockedWithThreadPoolStats(TextWriter log, string message, out in
LogLocked
(
log
,
sb
.
ToString
());
}
}
#endif
private
static
bool
AllComplete
(
Task
[]
tasks
)
{
...
...
@@ -623,27 +617,21 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
}
var
watch
=
Stopwatch
.
StartNew
();
#if FEATURE_THREADPOOL
LogLockedWithThreadPoolStats
(
log
,
"Awaiting task completion"
,
out
int
busyWorkerCount
);
#endif
try
{
// if none error, great
var
remaining
=
timeoutMilliseconds
-
checked
((
int
)
watch
.
ElapsedMilliseconds
);
if
(
remaining
<=
0
)
{
#if FEATURE_THREADPOOL
LogLockedWithThreadPoolStats
(
log
,
"Timeout before awaiting for tasks"
,
out
busyWorkerCount
);
#endif
return
false
;
}
var
allTasks
=
Task
.
WhenAll
(
tasks
).
ObserveErrors
();
var
any
=
Task
.
WhenAny
(
allTasks
,
Task
.
Delay
(
remaining
)).
ObserveErrors
();
bool
all
=
await
any
.
ForAwait
()
==
allTasks
;
#if FEATURE_THREADPOOL
LogLockedWithThreadPoolStats
(
log
,
all
?
"All tasks completed cleanly"
:
"Not all tasks completed cleanly"
,
out
busyWorkerCount
);
#endif
return
all
;
}
catch
...
...
@@ -659,9 +647,7 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
var
remaining
=
timeoutMilliseconds
-
checked
((
int
)
watch
.
ElapsedMilliseconds
);
if
(
remaining
<=
0
)
{
#if FEATURE_THREADPOOL
LogLockedWithThreadPoolStats
(
log
,
"Timeout awaiting tasks"
,
out
busyWorkerCount
);
#endif
return
false
;
}
try
...
...
@@ -672,9 +658,7 @@ private async Task<bool> WaitAllIgnoreErrorsAsync(Task[] tasks, int timeoutMilli
{
}
}
}
#if FEATURE_THREADPOOL
LogLockedWithThreadPoolStats
(
log
,
"Finished awaiting tasks"
,
out
busyWorkerCount
);
#endif
return
false
;
}
...
...
@@ -978,13 +962,13 @@ internal long LastHeartbeatSecondsAgo
get
{
if
(
pulse
==
null
)
return
-
1
;
return
unchecked
(
Environment
.
TickCount
-
VolatileWrapper
.
Read
(
ref
lastHeartbeatTicks
))
/
1000
;
return
unchecked
(
Environment
.
TickCount
-
Thread
.
Volatile
Read
(
ref
lastHeartbeatTicks
))
/
1000
;
}
}
internal
Exception
LastException
{
get
;
set
;
}
internal
static
long
LastGlobalHeartbeatSecondsAgo
=>
unchecked
(
Environment
.
TickCount
-
VolatileWrapper
.
Read
(
ref
lastGlobalHeartbeatTicks
))
/
1000
;
internal
static
long
LastGlobalHeartbeatSecondsAgo
=>
unchecked
(
Environment
.
TickCount
-
Thread
.
Volatile
Read
(
ref
lastGlobalHeartbeatTicks
))
/
1000
;
internal
CompletionManager
UnprocessableCompletionManager
{
get
;
}
...
...
@@ -2063,12 +2047,10 @@ void add(string lk, string sk, string v)
{
add
(
"Key-HashSlot"
,
"keyHashSlot"
,
message
.
GetHashSlot
(
this
.
ServerSelectionStrategy
).
ToString
());
}
#if FEATURE_THREADPOOL
int
busyWorkerCount
=
GetThreadPoolStats
(
out
string
iocp
,
out
string
worker
);
add
(
"ThreadPool-IO-Completion"
,
"IOCP"
,
iocp
);
add
(
"ThreadPool-Workers"
,
"WORKER"
,
worker
);
data
.
Add
(
Tuple
.
Create
(
"Busy-Workers"
,
busyWorkerCount
.
ToString
()));
#endif
#if FEATURE_PERFCOUNTER
if
(
IncludePerformanceCountersInExceptions
)
{
...
...
@@ -2123,7 +2105,6 @@ private static string GetSystemCpuPercent()
:
"unavailable"
;
}
#endif
#if FEATURE_THREADPOOL
private
static
int
GetThreadPoolStats
(
out
string
iocp
,
out
string
worker
)
{
ThreadPool
.
GetMaxThreads
(
out
int
maxWorkerThreads
,
out
int
maxIoThreads
);
...
...
@@ -2137,7 +2118,6 @@ private static int GetThreadPoolStats(out string iocp, out string worker)
worker
=
$"(Busy=
{
busyWorkerThreads
}
,Free=
{
freeWorkerThreads
}
,Min=
{
minWorkerThreads
}
,Max=
{
maxWorkerThreads
}
)"
;
return
busyWorkerThreads
;
}
#endif
/// <summary>
/// Should exceptions include identifiable details? (key names, additional .Data annotations)
...
...
StackExchange.Redis/StackExchange/Redis/Exceptions.cs
View file @
c54c0671
using
System
;
#if FEATURE_SERIALIZATION
using
System.Runtime.Serialization
;
#endif
#pragma warning disable RCS1194 // Implement exception constructors.
namespace
StackExchange.Redis
{
#if FEATURE_SERIALIZATION
[
Serializable
]
public
sealed
partial
class
RedisCommandException
:
Exception
{
private
RedisCommandException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
}
}
[
Serializable
]
public
sealed
partial
class
RedisTimeoutException
:
TimeoutException
{
private
RedisTimeoutException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
Commandstatus
=
(
CommandStatus
)
info
.
GetValue
(
"commandStatus"
,
typeof
(
CommandStatus
));
}
/// <summary>
/// Serialization implementation; not intended for general usage
/// </summary>
/// <param name="info">Serialization info.</param>
/// <param name="context">Serialization context.</param>
public
override
void
GetObjectData
(
SerializationInfo
info
,
StreamingContext
context
)
{
base
.
GetObjectData
(
info
,
context
);
info
.
AddValue
(
"commandStatus"
,
Commandstatus
);
}
}
[
Serializable
]
public
sealed
partial
class
RedisConnectionException
:
RedisException
{
private
RedisConnectionException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
FailureType
=
(
ConnectionFailureType
)
info
.
GetInt32
(
"failureType"
);
CommandStatus
=
(
CommandStatus
)
info
.
GetValue
(
"commandStatus"
,
typeof
(
CommandStatus
));
}
/// <summary>
/// Serialization implementation; not intended for general usage
/// </summary>
/// <param name="info">Serialization info.</param>
/// <param name="context">Serialization context.</param>
public
override
void
GetObjectData
(
SerializationInfo
info
,
StreamingContext
context
)
{
base
.
GetObjectData
(
info
,
context
);
info
.
AddValue
(
"failureType"
,
(
int
)
FailureType
);
info
.
AddValue
(
"commandStatus"
,
CommandStatus
);
}
}
[
Serializable
]
public
partial
class
RedisException
:
Exception
{
/// <summary>
/// Deserialization constructor; not intended for general usage
/// </summary>
/// <param name="info">Serialization info.</param>
/// <param name="ctx">Serialization context.</param>
protected
RedisException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
}
}
[
Serializable
]
public
sealed
partial
class
RedisServerException
:
RedisException
{
private
RedisServerException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
}
}
#endif
/// <summary>
/// Indicates that a command was illegal and was not sent to the server
/// </summary>
[
Serializable
]
public
sealed
partial
class
RedisCommandException
:
Exception
{
/// <summary>
...
...
@@ -88,11 +22,14 @@ public sealed partial class RedisCommandException : Exception
/// <param name="message">The message for the exception.</param>
/// <param name="innerException">The inner exception.</param>
public
RedisCommandException
(
string
message
,
Exception
innerException
)
:
base
(
message
,
innerException
)
{
}
private
RedisCommandException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
}
}
/// <summary>
/// Indicates the time allotted for a command or operation has expired.
/// </summary>
[
Serializable
]
public
sealed
partial
class
RedisTimeoutException
:
TimeoutException
{
/// <summary>
...
...
@@ -109,11 +46,27 @@ public RedisTimeoutException(string message, CommandStatus commandStatus) : base
/// status of the command while communicating with Redis
/// </summary>
public
CommandStatus
Commandstatus
{
get
;
}
private
RedisTimeoutException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
Commandstatus
=
(
CommandStatus
)
info
.
GetValue
(
"commandStatus"
,
typeof
(
CommandStatus
));
}
/// <summary>
/// Serialization implementation; not intended for general usage
/// </summary>
/// <param name="info">Serialization info.</param>
/// <param name="context">Serialization context.</param>
public
override
void
GetObjectData
(
SerializationInfo
info
,
StreamingContext
context
)
{
base
.
GetObjectData
(
info
,
context
);
info
.
AddValue
(
"commandStatus"
,
Commandstatus
);
}
}
/// <summary>
/// Indicates a connection fault when communicating with redis
/// </summary>
[
Serializable
]
public
sealed
partial
class
RedisConnectionException
:
RedisException
{
/// <summary>
...
...
@@ -153,11 +106,29 @@ public RedisConnectionException(ConnectionFailureType failureType, string messag
/// status of the command while communicating with Redis
/// </summary>
public
CommandStatus
CommandStatus
{
get
;
}
private
RedisConnectionException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
FailureType
=
(
ConnectionFailureType
)
info
.
GetInt32
(
"failureType"
);
CommandStatus
=
(
CommandStatus
)
info
.
GetValue
(
"commandStatus"
,
typeof
(
CommandStatus
));
}
/// <summary>
/// Serialization implementation; not intended for general usage
/// </summary>
/// <param name="info">Serialization info.</param>
/// <param name="context">Serialization context.</param>
public
override
void
GetObjectData
(
SerializationInfo
info
,
StreamingContext
context
)
{
base
.
GetObjectData
(
info
,
context
);
info
.
AddValue
(
"failureType"
,
(
int
)
FailureType
);
info
.
AddValue
(
"commandStatus"
,
CommandStatus
);
}
}
/// <summary>
/// Indicates an issue communicating with redis
/// </summary>
[
Serializable
]
public
partial
class
RedisException
:
Exception
{
/// <summary>
...
...
@@ -172,11 +143,19 @@ public partial class RedisException : Exception
/// <param name="message">The message for the exception.</param>
/// <param name="innerException">The inner exception.</param>
public
RedisException
(
string
message
,
Exception
innerException
)
:
base
(
message
,
innerException
)
{
}
/// <summary>
/// Deserialization constructor; not intended for general usage
/// </summary>
/// <param name="info">Serialization info.</param>
/// <param name="ctx">Serialization context.</param>
protected
RedisException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
}
}
/// <summary>
/// Indicates an exception raised by a redis server
/// </summary>
[
Serializable
]
public
sealed
partial
class
RedisServerException
:
RedisException
{
/// <summary>
...
...
@@ -184,5 +163,7 @@ public sealed partial class RedisServerException : RedisException
/// </summary>
/// <param name="message">The message for the exception.</param>
public
RedisServerException
(
string
message
)
:
base
(
message
)
{
}
private
RedisServerException
(
SerializationInfo
info
,
StreamingContext
ctx
)
:
base
(
info
,
ctx
)
{
}
}
}
StackExchange.Redis/StackExchange/Redis/ExtensionMethods.cs
View file @
c54c0671
...
...
@@ -131,7 +131,7 @@ public static string[] ToStringArray(this RedisValue[] values)
{
if
(
values
==
null
)
return
null
;
if
(
values
.
Length
==
0
)
return
nix
;
return
ConvertHelper
.
ConvertAll
(
values
,
x
=>
(
string
)
x
);
return
Array
.
ConvertAll
(
values
,
x
=>
(
string
)
x
);
}
internal
static
void
AuthenticateAsClient
(
this
SslStream
ssl
,
string
host
,
SslProtocols
?
allowedProtocols
)
...
...
@@ -145,21 +145,12 @@ internal static void AuthenticateAsClient(this SslStream ssl, string host, SslPr
var
certificateCollection
=
new
X509CertificateCollection
();
const
bool
checkCertRevocation
=
true
;
#if NETSTANDARD1_5
ssl
.
AuthenticateAsClientAsync
(
host
,
certificateCollection
,
allowedProtocols
.
Value
,
checkCertRevocation
)
.
GetAwaiter
().
GetResult
();
#else
ssl
.
AuthenticateAsClient
(
host
,
certificateCollection
,
allowedProtocols
.
Value
,
checkCertRevocation
);
#endif
}
private
static
void
AuthenticateAsClientUsingDefaultProtocols
(
SslStream
ssl
,
string
host
)
{
#if NETSTANDARD1_5
ssl
.
AuthenticateAsClientAsync
(
host
).
GetAwaiter
().
GetResult
();
#else
ssl
.
AuthenticateAsClient
(
host
);
#endif
}
}
}
StackExchange.Redis/StackExchange/Redis/PhysicalBridge.cs
View file @
c54c0671
...
...
@@ -377,7 +377,7 @@ internal void OnHeartbeat(bool ifConnectedOnly)
switch
(
state
)
{
case
(
int
)
State
.
Connecting
:
int
connectTimeMilliseconds
=
unchecked
(
Environment
.
TickCount
-
VolatileWrapper
.
Read
(
ref
connectStartTicks
));
int
connectTimeMilliseconds
=
unchecked
(
Environment
.
TickCount
-
Thread
.
Volatile
Read
(
ref
connectStartTicks
));
bool
shouldRetry
=
Multiplexer
.
RawConfig
.
ReconnectRetryPolicy
.
ShouldRetry
(
Interlocked
.
Read
(
ref
connectTimeoutRetryCount
),
connectTimeMilliseconds
);
if
(
shouldRetry
)
{
...
...
StackExchange.Redis/StackExchange/Redis/PhysicalConnection.cs
View file @
c54c0671
...
...
@@ -10,9 +10,6 @@
using
System.Security.Cryptography.X509Certificates
;
using
System.Text
;
using
System.Threading
;
#if NETSTANDARD1_5
using
System.Threading.Tasks
;
#endif
namespace
StackExchange.Redis
{
...
...
@@ -24,28 +21,6 @@ internal sealed partial class PhysicalConnection : IDisposable, ISocketCallback
private
static
readonly
byte
[]
Crlf
=
Encoding
.
ASCII
.
GetBytes
(
"\r\n"
);
#if NETSTANDARD1_5
private
readonly
Action
<
Task
<
int
>>
endRead
;
private
static
Action
<
Task
<
int
>>
EndReadFactory
(
PhysicalConnection
physical
)
{
return
result
=>
{
// can't capture AsyncState on SocketRead, so we'll do it once per physical instead
if
(
result
.
IsFaulted
)
{
GC
.
KeepAlive
(
result
.
Exception
);
}
try
{
physical
.
Multiplexer
.
Trace
(
"Completed asynchronously: processing in callback"
,
physical
.
physicalName
);
if
(
physical
.
EndReading
(
result
))
physical
.
BeginReading
();
}
catch
(
Exception
ex
)
{
physical
.
RecordConnectionFailed
(
ConnectionFailureType
.
InternalFailure
,
ex
);
}
};
}
#else
private
static
readonly
AsyncCallback
endRead
=
result
=>
{
PhysicalConnection
physical
;
...
...
@@ -60,7 +35,6 @@ private static Action<Task<int>> EndReadFactory(PhysicalConnection physical)
physical
.
RecordConnectionFailed
(
ConnectionFailureType
.
InternalFailure
,
ex
);
}
};
#endif
private
static
readonly
byte
[]
message
=
Encoding
.
UTF8
.
GetBytes
(
"message"
),
pmessage
=
Encoding
.
UTF8
.
GetBytes
(
"pmessage"
);
...
...
@@ -108,15 +82,12 @@ public PhysicalConnection(PhysicalBridge bridge)
var
endpoint
=
bridge
.
ServerEndPoint
.
EndPoint
;
physicalName
=
connectionType
+
"#"
+
Interlocked
.
Increment
(
ref
totalCount
)
+
"@"
+
Format
.
ToString
(
endpoint
);
Bridge
=
bridge
;
#if NETSTANDARD1_5
endRead
=
EndReadFactory
(
this
);
#endif
OnCreateEcho
();
}
public
void
BeginConnect
(
TextWriter
log
)
{
VolatileWrapper
.
Write
(
ref
firstUnansweredWriteTickCount
,
0
);
Thread
.
Volatile
Write
(
ref
firstUnansweredWriteTickCount
,
0
);
var
endpoint
=
Bridge
.
ServerEndPoint
.
EndPoint
;
Multiplexer
.
Trace
(
"Connecting..."
,
physicalName
);
...
...
@@ -132,7 +103,7 @@ private enum ReadMode : byte
public
PhysicalBridge
Bridge
{
get
;
}
public
long
LastWriteSecondsAgo
=>
unchecked
(
Environment
.
TickCount
-
VolatileWrapper
.
Read
(
ref
lastWriteTickCount
))
/
1000
;
public
long
LastWriteSecondsAgo
=>
unchecked
(
Environment
.
TickCount
-
Thread
.
Volatile
Read
(
ref
lastWriteTickCount
))
/
1000
;
public
ConnectionMultiplexer
Multiplexer
{
get
;
}
...
...
@@ -145,17 +116,13 @@ public void Dispose()
if
(
outStream
!=
null
)
{
Multiplexer
.
Trace
(
"Disconnecting..."
,
physicalName
);
#if !NETSTANDARD1_5
try
{
outStream
.
Close
();
}
catch
{
}
#endif
try
{
outStream
.
Dispose
();
}
catch
{
}
outStream
=
null
;
}
if
(
netStream
!=
null
)
{
#if !NETSTANDARD1_5
try
{
netStream
.
Close
();
}
catch
{
}
#endif
try
{
netStream
.
Dispose
();
}
catch
{
}
netStream
=
null
;
}
...
...
@@ -209,9 +176,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
=
VolatileWrapper
.
Read
(
ref
lastReadTickCount
),
lastWrite
=
VolatileWrapper
.
Read
(
ref
lastWriteTickCount
),
lastBeat
=
VolatileWrapper
.
Read
(
ref
lastBeatTickCount
);
int
unansweredRead
=
VolatileWrapper
.
Read
(
ref
firstUnansweredWriteTickCount
);
int
now
=
Environment
.
TickCount
,
lastRead
=
Thread
.
VolatileRead
(
ref
lastReadTickCount
),
lastWrite
=
Thread
.
Volatile
Read
(
ref
lastWriteTickCount
),
lastBeat
=
Thread
.
Volatile
Read
(
ref
lastBeatTickCount
);
int
unansweredRead
=
Thread
.
Volatile
Read
(
ref
firstUnansweredWriteTickCount
);
var
exMessage
=
new
StringBuilder
(
failureType
.
ToString
());
...
...
@@ -646,19 +613,6 @@ private unsafe void WriteRaw(Stream stream, string value, int encodedLength)
}
else
{
#if NETSTANDARD1_5
int
charsRemaining
=
value
.
Length
,
charOffset
=
0
,
bytesWritten
;
var
valueCharArray
=
value
.
ToCharArray
();
while
(
charsRemaining
>
Scratch_CharsPerBlock
)
{
bytesWritten
=
outEncoder
.
GetBytes
(
valueCharArray
,
charOffset
,
Scratch_CharsPerBlock
,
outScratch
,
0
,
false
);
stream
.
Write
(
outScratch
,
0
,
bytesWritten
);
charOffset
+=
Scratch_CharsPerBlock
;
charsRemaining
-=
Scratch_CharsPerBlock
;
}
bytesWritten
=
outEncoder
.
GetBytes
(
valueCharArray
,
charOffset
,
charsRemaining
,
outScratch
,
0
,
true
);
if
(
bytesWritten
!=
0
)
stream
.
Write
(
outScratch
,
0
,
bytesWritten
);
#else
fixed
(
char
*
c
=
value
)
fixed
(
byte
*
b
=
outScratch
)
{
...
...
@@ -673,7 +627,6 @@ private unsafe void WriteRaw(Stream stream, string value, int encodedLength)
bytesWritten
=
outEncoder
.
GetBytes
(
c
+
charOffset
,
charsRemaining
,
b
,
ScratchSize
,
true
);
if
(
bytesWritten
!=
0
)
stream
.
Write
(
outScratch
,
0
,
bytesWritten
);
}
#endif
}
}
...
...
@@ -721,36 +674,15 @@ private void BeginReading()
keepReading
=
false
;
int
space
=
EnsureSpaceAndComputeBytesToRead
();
Multiplexer
.
Trace
(
"Beginning async read..."
,
physicalName
);
#if NETSTANDARD1_5
var
result
=
netStream
.
ReadAsync
(
ioBuffer
,
ioBufferBytes
,
space
);
switch
(
result
.
Status
)
{
case
TaskStatus
.
RanToCompletion
:
case
TaskStatus
.
Faulted
:
Multiplexer
.
Trace
(
"Completed synchronously: processing immediately"
,
physicalName
);
keepReading
=
EndReading
(
result
);
break
;
default
:
result
.
ContinueWith
(
endRead
);
break
;
}
#else
var
result
=
netStream
.
BeginRead
(
ioBuffer
,
ioBufferBytes
,
space
,
endRead
,
this
);
if
(
result
.
CompletedSynchronously
)
{
Multiplexer
.
Trace
(
"Completed synchronously: processing immediately"
,
physicalName
);
keepReading
=
EndReading
(
result
);
}
#endif
}
while
(
keepReading
);
}
#if NETSTANDARD1_5
catch
(
AggregateException
ex
)
{
throw
ex
.
InnerException
;
}
#endif
catch
(
System
.
IO
.
IOException
ex
)
catch
(
IOException
ex
)
{
Multiplexer
.
Trace
(
"Could not connect: "
+
ex
.
Message
,
physicalName
);
}
...
...
@@ -846,22 +778,6 @@ SocketMode ISocketCallback.Connected(Stream stream, TextWriter log)
}
}
#if NETSTANDARD1_5
private
bool
EndReading
(
Task
<
int
>
result
)
{
try
{
var
tmp
=
netStream
;
int
bytesRead
=
tmp
==
null
?
0
:
result
.
Result
;
// note we expect this to be completed
return
ProcessReadBytes
(
bytesRead
);
}
catch
(
Exception
ex
)
{
RecordConnectionFailed
(
ConnectionFailureType
.
InternalFailure
,
ex
);
return
false
;
}
}
#else
private
bool
EndReading
(
IAsyncResult
result
)
{
try
...
...
@@ -875,7 +791,7 @@ private bool EndReading(IAsyncResult result)
return
false
;
}
}
#endif
private
int
EnsureSpaceAndComputeBytesToRead
()
{
int
space
=
ioBuffer
.
Length
-
ioBufferBytes
;
...
...
@@ -1007,7 +923,7 @@ private bool ProcessReadBytes(int bytesRead)
Interlocked
.
Exchange
(
ref
lastReadTickCount
,
Environment
.
TickCount
);
// reset unanswered write timestamp
VolatileWrapper
.
Write
(
ref
firstUnansweredWriteTickCount
,
0
);
Thread
.
Volatile
Write
(
ref
firstUnansweredWriteTickCount
,
0
);
ioBufferBytes
+=
bytesRead
;
Multiplexer
.
Trace
(
"More bytes available: "
+
bytesRead
+
" ("
+
ioBufferBytes
+
")"
,
physicalName
);
...
...
@@ -1168,7 +1084,7 @@ private RawResult TryParseResult(byte[] buffer, ref int offset, ref int count)
public
void
CheckForStaleConnection
(
ref
SocketManager
.
ManagerState
state
)
{
int
firstUnansweredWrite
=
VolatileWrapper
.
Read
(
ref
firstUnansweredWriteTickCount
);
int
firstUnansweredWrite
=
Thread
.
Volatile
Read
(
ref
firstUnansweredWriteTickCount
);
DebugEmulateStaleConnection
(
ref
firstUnansweredWrite
);
...
...
StackExchange.Redis/StackExchange/Redis/RedisResult.cs
View file @
c54c0671
...
...
@@ -198,7 +198,7 @@ internal override bool AsBoolean()
throw
new
InvalidCastException
();
}
internal
override
bool
[]
AsBooleanArray
()
=>
ConvertHelper
.
ConvertAll
(
value
,
x
=>
x
.
AsBoolean
());
internal
override
bool
[]
AsBooleanArray
()
=>
Array
.
ConvertAll
(
value
,
x
=>
x
.
AsBoolean
());
internal
override
byte
[]
AsByteArray
()
{
...
...
@@ -206,7 +206,7 @@ internal override byte[] AsByteArray()
throw
new
InvalidCastException
();
}
internal
override
byte
[][]
AsByteArrayArray
()
=>
ConvertHelper
.
ConvertAll
(
value
,
x
=>
x
.
AsByteArray
());
internal
override
byte
[][]
AsByteArrayArray
()
=>
Array
.
ConvertAll
(
value
,
x
=>
x
.
AsByteArray
());
internal
override
double
AsDouble
()
{
...
...
@@ -214,7 +214,7 @@ internal override double AsDouble()
throw
new
InvalidCastException
();
}
internal
override
double
[]
AsDoubleArray
()
=>
ConvertHelper
.
ConvertAll
(
value
,
x
=>
x
.
AsDouble
());
internal
override
double
[]
AsDoubleArray
()
=>
Array
.
ConvertAll
(
value
,
x
=>
x
.
AsDouble
());
internal
override
int
AsInt32
()
{
...
...
@@ -222,7 +222,7 @@ internal override int AsInt32()
throw
new
InvalidCastException
();
}
internal
override
int
[]
AsInt32Array
()
=>
ConvertHelper
.
ConvertAll
(
value
,
x
=>
x
.
AsInt32
());
internal
override
int
[]
AsInt32Array
()
=>
Array
.
ConvertAll
(
value
,
x
=>
x
.
AsInt32
());
internal
override
long
AsInt64
()
{
...
...
@@ -230,7 +230,7 @@ internal override long AsInt64()
throw
new
InvalidCastException
();
}
internal
override
long
[]
AsInt64Array
()
=>
ConvertHelper
.
ConvertAll
(
value
,
x
=>
x
.
AsInt64
());
internal
override
long
[]
AsInt64Array
()
=>
Array
.
ConvertAll
(
value
,
x
=>
x
.
AsInt64
());
internal
override
bool
?
AsNullableBoolean
()
{
...
...
@@ -262,7 +262,7 @@ internal override RedisKey AsRedisKey()
throw
new
InvalidCastException
();
}
internal
override
RedisKey
[]
AsRedisKeyArray
()
=>
ConvertHelper
.
ConvertAll
(
value
,
x
=>
x
.
AsRedisKey
());
internal
override
RedisKey
[]
AsRedisKeyArray
()
=>
Array
.
ConvertAll
(
value
,
x
=>
x
.
AsRedisKey
());
internal
override
RedisResult
[]
AsRedisResultArray
()
=>
value
;
...
...
@@ -272,7 +272,7 @@ internal override RedisValue AsRedisValue()
throw
new
InvalidCastException
();
}
internal
override
RedisValue
[]
AsRedisValueArray
()
=>
ConvertHelper
.
ConvertAll
(
value
,
x
=>
x
.
AsRedisValue
());
internal
override
RedisValue
[]
AsRedisValueArray
()
=>
Array
.
ConvertAll
(
value
,
x
=>
x
.
AsRedisValue
());
internal
override
string
AsString
()
{
...
...
@@ -280,7 +280,7 @@ internal override string AsString()
throw
new
InvalidCastException
();
}
internal
override
string
[]
AsStringArray
()
=>
ConvertHelper
.
ConvertAll
(
value
,
x
=>
x
.
AsString
());
internal
override
string
[]
AsStringArray
()
=>
Array
.
ConvertAll
(
value
,
x
=>
x
.
AsString
());
}
private
sealed
class
ErrorRedisResult
:
RedisResult
...
...
StackExchange.Redis/StackExchange/Redis/RedisValue.cs
View file @
c54c0671
using
System
;
#if NETSTANDARD1_5
using
System.Collections.Generic
;
using
System.Reflection
;
#endif
using
System
;
using
System.Text
;
namespace
StackExchange.Redis
...
...
@@ -295,12 +291,7 @@ public int CompareTo(RedisValue other)
if
(
otherType
==
CompareType
.
Double
)
return
thisDouble
.
CompareTo
(
otherDouble
);
}
// otherwise, compare as strings
#if NETSTANDARD1_5
var
compareInfo
=
System
.
Globalization
.
CultureInfo
.
InvariantCulture
.
CompareInfo
;
return
compareInfo
.
Compare
((
string
)
this
,
(
string
)
other
,
System
.
Globalization
.
CompareOptions
.
Ordinal
);
#else
return
StringComparer
.
InvariantCulture
.
Compare
((
string
)
this
,
(
string
)
other
);
#endif
}
catch
(
Exception
ex
)
{
...
...
@@ -575,7 +566,7 @@ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
if
(
conversionType
==
null
)
throw
new
ArgumentNullException
(
nameof
(
conversionType
));
if
(
conversionType
==
typeof
(
byte
[]))
return
(
byte
[])
this
;
if
(
conversionType
==
typeof
(
RedisValue
))
return
this
;
switch
(
conversionType
.
GetTypeCode
(
))
switch
(
Type
.
GetTypeCode
(
conversionType
))
{
case
TypeCode
.
Boolean
:
return
(
bool
)
this
;
case
TypeCode
.
Byte
:
return
(
byte
)
this
;
...
...
@@ -669,47 +660,4 @@ public bool TryParse(out double val)
return
TryParseDouble
(
blob
,
out
val
);
}
}
internal
static
class
ReflectionExtensions
{
#if NETSTANDARD1_5
internal
static
TypeCode
GetTypeCode
(
this
Type
type
)
{
if
(
type
==
null
)
return
TypeCode
.
Empty
;
if
(
typeCodeLookup
.
TryGetValue
(
type
,
out
TypeCode
result
))
return
result
;
if
(
type
.
GetTypeInfo
().
IsEnum
)
{
type
=
Enum
.
GetUnderlyingType
(
type
);
if
(
typeCodeLookup
.
TryGetValue
(
type
,
out
result
))
return
result
;
}
return
TypeCode
.
Object
;
}
private
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
(
type
);
}
#endif
}
}
\ No newline at end of file
}
StackExchange.Redis/StackExchange/Redis/ResultBox.cs
View file @
c54c0671
...
...
@@ -97,9 +97,7 @@ public override bool TryComplete(bool isAsync)
{
if
(
stateOrCompletionSource
is
TaskCompletionSource
<
T
>
tcs
)
{
#if !PLAT_SAFE_CONTINUATIONS // we don't need to check in this scenario
if
(
isAsync
||
TaskSource
.
IsSyncSafe
(
tcs
.
Task
))
#endif
{
UnwrapAndRecycle
(
this
,
true
,
out
T
val
,
out
Exception
ex
);
...
...
@@ -117,12 +115,10 @@ public override bool TryComplete(bool isAsync)
}
return
true
;
}
#if !PLAT_SAFE_CONTINUATIONS
else
{
// looks like continuations; push to async to preserve the reader thread
return
false
;
}
#endif
}
else
{
...
...
StackExchange.Redis/StackExchange/Redis/ScriptParameterMapper.cs
View file @
c54c0671
...
...
@@ -316,11 +316,7 @@ private static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool,
LocalBuilder
redisKeyLoc
=
null
;
var
loc
=
il
.
DeclareLocal
(
t
);
il
.
Emit
(
OpCodes
.
Ldarg_0
);
// object
#if NETSTANDARD1_5
if
(
t
.
GetTypeInfo
().
IsValueType
)
#else
if
(
t
.
IsValueType
)
#endif
{
il
.
Emit
(
OpCodes
.
Unbox_Any
,
t
);
// T
}
...
...
@@ -351,11 +347,7 @@ private static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool,
{
il
.
Emit
(
OpCodes
.
Dup
);
// RedisKey[] RedisKey[]
il
.
Emit
(
OpCodes
.
Ldc_I4
,
i
);
// RedisKey[] RedisKey[] int
#if NETSTANDARD1_5
if
(
t
.
GetTypeInfo
().
IsValueType
)
#else
if
(
t
.
IsValueType
)
#endif
{
il
.
Emit
(
OpCodes
.
Ldloca
,
loc
);
// RedisKey[] RedisKey[] int T*
}
...
...
@@ -383,11 +375,7 @@ private static void PrefixIfNeeded(ILGenerator il, LocalBuilder needsPrefixBool,
{
il
.
Emit
(
OpCodes
.
Dup
);
// RedisKey[] RedisValue[] RedisValue[]
il
.
Emit
(
OpCodes
.
Ldc_I4
,
i
);
// RedisKey[] RedisValue[] RedisValue[] int
#if NETSTANDARD1_5
if
(
t
.
GetTypeInfo
().
IsValueType
)
#else
if
(
t
.
IsValueType
)
#endif
{
il
.
Emit
(
OpCodes
.
Ldloca
,
loc
);
// RedisKey[] RedisValue[] RedisValue[] int T*
}
...
...
StackExchange.Redis/StackExchange/Redis/ServerEndPoint.cs
View file @
c54c0671
...
...
@@ -483,7 +483,7 @@ internal void OnFullyEstablished(PhysicalConnection connection)
internal
int
LastInfoReplicationCheckSecondsAgo
{
get
{
return
unchecked
(
Environment
.
TickCount
-
VolatileWrapper
.
Read
(
ref
lastInfoReplicationCheckTicks
))
/
1000
;
}
get
{
return
unchecked
(
Environment
.
TickCount
-
Thread
.
Volatile
Read
(
ref
lastInfoReplicationCheckTicks
))
/
1000
;
}
}
private
EndPoint
masterEndPoint
;
...
...
StackExchange.Redis/StackExchange/Redis/SocketManager.cs
View file @
c54c0671
...
...
@@ -4,10 +4,6 @@
using
System.Net
;
using
System.Net.Sockets
;
using
System.Threading
;
#if NETSTANDARD1_5
using
System.Runtime.InteropServices
;
using
System.Threading.Tasks
;
#endif
namespace
StackExchange.Redis
{
...
...
@@ -146,12 +142,8 @@ public SocketManager(string name, bool useHighPrioritySocketThreads)
// we need a dedicated writer, because when under heavy ambient load
// (a busy asp.net site, for example), workers are not reliable enough
#if NETSTANDARD1_5
var
dedicatedWriter
=
new
Thread
(
writeAllQueues
);
#else
var
dedicatedWriter
=
new
Thread
(
writeAllQueues
,
32
*
1024
);
// don't need a huge stack;
dedicatedWriter
.
Priority
=
useHighPrioritySocketThreads
?
ThreadPriority
.
AboveNormal
:
ThreadPriority
.
Normal
;
#endif
dedicatedWriter
.
Name
=
name
+
":Write"
;
dedicatedWriter
.
IsBackground
=
true
;
// should not keep process alive
dedicatedWriter
.
Start
(
this
);
// will self-exit when disposed
...
...
@@ -179,7 +171,6 @@ public void Dispose()
internal
SocketToken
BeginConnect
(
EndPoint
endpoint
,
ISocketCallback
callback
,
ConnectionMultiplexer
multiplexer
,
TextWriter
log
)
{
#if !NETSTANDARD1_5
void
RunWithCompletionType
(
Func
<
AsyncCallback
,
IAsyncResult
>
beginAsync
,
AsyncCallback
asyncCallback
)
{
void
proxyCallback
(
IAsyncResult
ar
)
...
...
@@ -197,7 +188,6 @@ void proxyCallback(IAsyncResult ar)
asyncCallback
(
result
);
}
}
#endif
var
addressFamily
=
endpoint
.
AddressFamily
==
AddressFamily
.
Unspecified
?
AddressFamily
.
InterNetwork
:
endpoint
.
AddressFamily
;
var
socket
=
new
Socket
(
addressFamily
,
SocketType
.
Stream
,
ProtocolType
.
Tcp
);
...
...
@@ -211,14 +201,6 @@ void proxyCallback(IAsyncResult ar)
// A work-around for a Mono bug in BeginConnect(EndPoint endpoint, AsyncCallback callback, object state)
if
(
endpoint
is
DnsEndPoint
dnsEndpoint
)
{
#if NETSTANDARD1_5 // No BeginConnect there, because everything was an Async push...we should drop this
socket
.
ConnectAsync
(
dnsEndpoint
.
Host
,
dnsEndpoint
.
Port
).
ContinueWith
(
t
=>
{
multiplexer
.
LogLocked
(
log
,
"EndConnect: {0}"
,
formattedEndpoint
);
EndConnectImpl
(
t
,
multiplexer
,
log
,
tuple
);
multiplexer
.
LogLocked
(
log
,
"Connect complete: {0}"
,
formattedEndpoint
);
});
#else
RunWithCompletionType
(
cb
=>
socket
.
BeginConnect
(
dnsEndpoint
.
Host
,
dnsEndpoint
.
Port
,
cb
,
tuple
),
ar
=>
{
...
...
@@ -226,17 +208,9 @@ void proxyCallback(IAsyncResult ar)
EndConnectImpl
(
ar
,
multiplexer
,
log
,
tuple
);
multiplexer
.
LogLocked
(
log
,
"Connect complete: {0}"
,
formattedEndpoint
);
});
#endif
}
else
{
#if NETSTANDARD1_5 // No BeginConnect there, because everything was an Async push...we should drop this
socket
.
ConnectAsync
(
endpoint
).
ContinueWith
(
t
=>
{
multiplexer
.
LogLocked
(
log
,
"EndConnect: {0}"
,
formattedEndpoint
);
EndConnectImpl
(
t
,
multiplexer
,
log
,
tuple
);
});
#else
RunWithCompletionType
(
cb
=>
socket
.
BeginConnect
(
endpoint
,
cb
,
tuple
),
ar
=>
{
...
...
@@ -244,7 +218,6 @@ void proxyCallback(IAsyncResult ar)
EndConnectImpl
(
ar
,
multiplexer
,
log
,
tuple
);
multiplexer
.
LogLocked
(
log
,
"Connect complete: {0}"
,
formattedEndpoint
);
});
#endif
}
}
catch
(
NotImplementedException
ex
)
...
...
@@ -266,25 +239,6 @@ internal void SetFastLoopbackOption(Socket socket)
// or will be subject to WFP filtering.
const
int
SIO_LOOPBACK_FAST_PATH
=
-
1744830448
;
#if NETSTANDARD1_5
try
{
// Ioctl is not supported on other platforms at the moment
if
(
RuntimeInformation
.
IsOSPlatform
(
OSPlatform
.
Windows
))
{
byte
[]
optionInValue
=
BitConverter
.
GetBytes
(
1
);
socket
.
IOControl
(
SIO_LOOPBACK_FAST_PATH
,
optionInValue
,
null
);
}
}
catch
(
SocketException
)
{
}
catch
(
PlatformNotSupportedException
)
{
// Fix for https://github.com/StackExchange/StackExchange.Redis/issues/582
// Checking the platform can fail on some platforms. However, we don't
// care if the platform check fails because this is for a Windows
// optimization, and checking the platform will not fail on Windows.
}
#else
// windows only
if
(
Environment
.
OSVersion
.
Platform
==
PlatformID
.
Win32NT
)
{
...
...
@@ -296,7 +250,6 @@ internal void SetFastLoopbackOption(Socket socket)
socket
.
IOControl
(
SIO_LOOPBACK_FAST_PATH
,
optionInValue
,
null
);
}
}
#endif
}
internal
void
RequestWrite
(
PhysicalBridge
bridge
,
bool
forced
)
...
...
@@ -332,11 +285,7 @@ private void EndConnectImpl(IAsyncResult ar, ConnectionMultiplexer multiplexer,
if
(
ignoreConnect
)
return
;
var
socket
=
tuple
.
Item1
;
var
callback
=
tuple
.
Item2
;
#if NETSTANDARD1_5
multiplexer
.
Wait
((
Task
)
ar
);
// make it explode if invalid (note: already complete at this point)
#else
socket
.
EndConnect
(
ar
);
#endif
var
netStream
=
new
NetworkStream
(
socket
,
false
);
var
socketMode
=
callback
?.
Connected
(
netStream
,
log
)
??
SocketMode
.
Abort
;
switch
(
socketMode
)
...
...
@@ -401,9 +350,7 @@ private void Shutdown(Socket socket)
{
OnShutdown
(
socket
);
try
{
socket
.
Shutdown
(
SocketShutdown
.
Both
);
}
catch
{
}
#if !NETSTANDARD1_5
try
{
socket
.
Close
();
}
catch
{
}
#endif
try
{
socket
.
Dispose
();
}
catch
{
}
}
}
...
...
StackExchange.Redis/StackExchange/Redis/TaskSource.cs
View file @
c54c0671
using
System.Threading.Tasks
;
#if !PLAT_SAFE_CONTINUATIONS
using
System
;
using
System.Diagnostics
;
using
System.Reflection
;
using
System.Reflection.Emit
;
#endif
namespace
StackExchange.Redis
{
...
...
@@ -15,7 +12,6 @@ namespace StackExchange.Redis
/// </summary>
internal
static
class
TaskSource
{
#if !PLAT_SAFE_CONTINUATIONS
// on .NET < 4.6, it was possible to have threads hijacked; this is no longer a problem in 4.6 and core-clr 5,
// thanks to the new TaskCreationOptions.RunContinuationsAsynchronously, however we still need to be a little
// "test and react", as we could be targeting 4.5 but running on a 4.6 machine, in which case *it can still
...
...
@@ -80,7 +76,7 @@ static TaskSource()
IsSyncSafe
=
_
=>
false
;
// assume: not
}
}
#endif
/// <summary>
/// Create a new TaskCompletion source
/// </summary>
...
...
@@ -88,11 +84,7 @@ static TaskSource()
/// <param name="asyncState">The state for the created <see cref="TaskCompletionSource{TResult}"/>.</param>
public
static
TaskCompletionSource
<
T
>
Create
<
T
>(
object
asyncState
)
{
#if PLAT_SAFE_CONTINUATIONS
return
new
TaskCompletionSource
<
T
>(
asyncState
,
TaskCreationOptions
.
RunContinuationsAsynchronously
);
#else
return
new
TaskCompletionSource
<
T
>(
asyncState
,
TaskCreationOptions
.
None
);
#endif
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment