Commit 6af1811b authored by Marc Gravell's avatar Marc Gravell

all of the outbound changes

parent 5c31bb25
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<DefaultLanguage>en-US</DefaultLanguage> <DefaultLanguage>en-US</DefaultLanguage>
<IncludeSymbols>false</IncludeSymbols> <IncludeSymbols>false</IncludeSymbols>
<LibraryTargetFrameworks>net45;net46;netstandard2.0</LibraryTargetFrameworks> <LibraryTargetFrameworks>net46;netstandard2.0</LibraryTargetFrameworks>
<CoreFxVersion>4.5.0</CoreFxVersion> <CoreFxVersion>4.5.0</CoreFxVersion>
<xUnitVersion>2.4.0-beta.2.build3981</xUnitVersion> <xUnitVersion>2.4.0-beta.2.build3981</xUnitVersion>
</PropertyGroup> </PropertyGroup>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
</ItemGroup> </ItemGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net46'"> <PropertyGroup Condition=" '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net46'">
<DefineConstants>$(DefineConstants);FEATURE_SOCKET_MODE_POLL;FEATURE_PERFCOUNTER;</DefineConstants> <DefineConstants>$(DefineConstants);FEATURE_PERFCOUNTER;</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<PackageReference Include="System.Reflection.Emit.ILGeneration" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit.ILGeneration" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" /> <PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
<!--<PackageReference Include="System.Memory" Version="$(CoreFxVersion)" /> <PackageReference Include="System.Memory" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Buffers" Version="$(CoreFxVersion)" /> <PackageReference Include="System.Buffers" Version="$(CoreFxVersion)" />
<PackageReference Include="System.IO.Pipelines" Version="$(CoreFxVersion)" /> <PackageReference Include="System.IO.Pipelines" Version="$(CoreFxVersion)" />
<PackageReference Include="Pipelines.Sockets.Unofficial" Version="0.2.0-alpha-001" />--> <PackageReference Include="Pipelines.Sockets.Unofficial" Version="0.2.0-alpha-004" />
</ItemGroup> </ItemGroup>
</Project> </Project>
\ No newline at end of file
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
...@@ -267,21 +268,19 @@ internal void KeepAlive() ...@@ -267,21 +268,19 @@ internal void KeepAlive()
} }
} }
internal void OnConnected(PhysicalConnection connection, TextWriter log) internal async Task OnConnectedAsync(PhysicalConnection connection, TextWriter log)
{ {
Trace("OnConnected"); Trace("OnConnected");
if (physical == connection && !isDisposed && ChangeState(State.Connecting, State.ConnectedEstablishing)) if (physical == connection && !isDisposed && ChangeState(State.Connecting, State.ConnectedEstablishing))
{ {
ServerEndPoint.OnEstablishing(connection, log); await ServerEndPoint.OnEstablishingAsync(connection, log);
} }
else else
{ {
try try
{ {
connection.Dispose(); connection.Dispose();
} } catch { }
catch
{ }
} }
} }
...@@ -552,7 +551,10 @@ internal bool WriteMessageDirect(PhysicalConnection tmp, Message next) ...@@ -552,7 +551,10 @@ internal bool WriteMessageDirect(PhysicalConnection tmp, Message next)
} }
} }
internal WriteResult WriteQueue(int maxWork) [MethodImpl(MethodImplOptions.AggressiveInlining)]
static ValueTask<T> AsResult<T>(T value) => new ValueTask<T>(value);
internal async ValueTask<WriteResult> WriteQueueAsync(int maxWork)
{ {
bool weAreWriter = false; bool weAreWriter = false;
PhysicalConnection conn = null; PhysicalConnection conn = null;
...@@ -585,7 +587,7 @@ internal WriteResult WriteQueue(int maxWork) ...@@ -585,7 +587,7 @@ internal WriteResult WriteQueue(int maxWork)
Trace("Nothing to write; exiting"); Trace("Nothing to write; exiting");
if(count == 0) if(count == 0)
{ {
conn.Flush(); // only flush on an empty run await conn.FlushAsync(); // only flush on an empty run
return WriteResult.NothingToDo; return WriteResult.NothingToDo;
} }
return WriteResult.QueueEmptyAfterWrite; return WriteResult.QueueEmptyAfterWrite;
...@@ -604,7 +606,7 @@ internal WriteResult WriteQueue(int maxWork) ...@@ -604,7 +606,7 @@ internal WriteResult WriteQueue(int maxWork)
{ {
Trace("Work limit; exiting"); Trace("Work limit; exiting");
Trace(last != null, "Flushed up to: " + last); Trace(last != null, "Flushed up to: " + last);
conn.Flush(); await conn.FlushAsync();
break; break;
} }
} }
......
using System; //using System;
namespace StackExchange.Redis //namespace StackExchange.Redis
{ //{
internal static class PlatformHelper // internal static class PlatformHelper
{ // {
public static bool IsMono { get; } = Type.GetType("Mono.Runtime") != null; // public static bool IsMono { get; } = Type.GetType("Mono.Runtime") != null;
public static bool IsUnix { get; } = (int)Environment.OSVersion.Platform == 4 // public static bool IsUnix { get; } = (int)Environment.OSVersion.Platform == 4
|| (int)Environment.OSVersion.Platform == 6 // || (int)Environment.OSVersion.Platform == 6
|| (int)Environment.OSVersion.Platform == 128; // || (int)Environment.OSVersion.Platform == 128;
public static SocketMode DefaultSocketMode = IsMono && IsUnix ? SocketMode.Async : SocketMode.Poll; // public static SocketMode DefaultSocketMode = IsMono && IsUnix ? SocketMode.Async : SocketMode.Poll;
} // }
} //}
...@@ -2521,6 +2521,7 @@ public ScriptEvalMessage(int db, CommandFlags flags, byte[] hash, RedisKey[] key ...@@ -2521,6 +2521,7 @@ public ScriptEvalMessage(int db, CommandFlags flags, byte[] hash, RedisKey[] key
: this(db, flags, RedisCommand.EVAL, null, hash, keys, values) : this(db, flags, RedisCommand.EVAL, null, hash, keys, values)
{ {
if (hash == null) throw new ArgumentNullException(nameof(hash)); if (hash == null) throw new ArgumentNullException(nameof(hash));
if (hash.Length != ResultProcessor.ScriptLoadProcessor.Sha1HashLength) throw new ArgumentOutOfRangeException(nameof(hash), "Invalid hash length");
} }
private ScriptEvalMessage(int db, CommandFlags flags, RedisCommand command, string script, byte[] hexHash, RedisKey[] keys, RedisValue[] values) private ScriptEvalMessage(int db, CommandFlags flags, RedisCommand command, string script, byte[] hexHash, RedisKey[] keys, RedisValue[] values)
...@@ -2571,7 +2572,7 @@ internal override void WriteImpl(PhysicalConnection physical) ...@@ -2571,7 +2572,7 @@ internal override void WriteImpl(PhysicalConnection physical)
if (hexHash != null) if (hexHash != null)
{ {
physical.WriteHeader(RedisCommand.EVALSHA, 2 + keys.Length + values.Length); physical.WriteHeader(RedisCommand.EVALSHA, 2 + keys.Length + values.Length);
physical.WriteAsHex(hexHash); physical.WriteSha1AsHex(hexHash);
} }
else if (asciiHash != null) else if (asciiHash != null)
{ {
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
...@@ -250,7 +250,7 @@ public IEnumerable<Message> GetMessages(PhysicalConnection connection) ...@@ -250,7 +250,7 @@ public IEnumerable<Message> GetMessages(PhysicalConnection connection)
{ {
// need to get those sent ASAP; if they are stuck in the buffers, we die // need to get those sent ASAP; if they are stuck in the buffers, we die
multiplexer.Trace("Flushing and waiting for precondition responses"); multiplexer.Trace("Flushing and waiting for precondition responses");
connection.Flush(); connection.FlushAsync().Wait();
if (Monitor.Wait(lastBox, multiplexer.TimeoutMilliseconds)) if (Monitor.Wait(lastBox, multiplexer.TimeoutMilliseconds))
{ {
if (!AreAllConditionsSatisfied(multiplexer)) if (!AreAllConditionsSatisfied(multiplexer))
...@@ -297,7 +297,7 @@ public IEnumerable<Message> GetMessages(PhysicalConnection connection) ...@@ -297,7 +297,7 @@ public IEnumerable<Message> GetMessages(PhysicalConnection connection)
if (explicitCheckForQueued && lastBox != null) if (explicitCheckForQueued && lastBox != null)
{ {
multiplexer.Trace("Flushing and waiting for precondition+queued responses"); multiplexer.Trace("Flushing and waiting for precondition+queued responses");
connection.Flush(); // make sure they get sent, so we can check for QUEUED (and the pre-conditions if necessary) connection.FlushAsync().Wait(); // make sure they get sent, so we can check for QUEUED (and the pre-conditions if necessary)
if (Monitor.Wait(lastBox, multiplexer.TimeoutMilliseconds)) if (Monitor.Wait(lastBox, multiplexer.TimeoutMilliseconds))
{ {
if (!AreAllConditionsSatisfied(multiplexer)) if (!AreAllConditionsSatisfied(multiplexer))
......
...@@ -393,11 +393,13 @@ internal static bool IsSHA1(string script) ...@@ -393,11 +393,13 @@ internal static bool IsSHA1(string script)
return script != null && sha1.IsMatch(script); return script != null && sha1.IsMatch(script);
} }
internal const int Sha1HashLength = 20;
internal static byte[] ParseSHA1(byte[] value) internal static byte[] ParseSHA1(byte[] value)
{ {
if (value?.Length == 40) if (value?.Length == Sha1HashLength * 2)
{ {
var tmp = new byte[20]; var tmp = new byte[Sha1HashLength];
int charIndex = 0; int charIndex = 0;
for (int i = 0; i < tmp.Length; i++) for (int i = 0; i < tmp.Length; i++)
{ {
...@@ -412,9 +414,9 @@ internal static byte[] ParseSHA1(byte[] value) ...@@ -412,9 +414,9 @@ internal static byte[] ParseSHA1(byte[] value)
internal static byte[] ParseSHA1(string value) internal static byte[] ParseSHA1(string value)
{ {
if (value?.Length == 40 && sha1.IsMatch(value)) if (value?.Length == (Sha1HashLength * 2) && sha1.IsMatch(value))
{ {
var tmp = new byte[20]; var tmp = new byte[Sha1HashLength];
int charIndex = 0; int charIndex = 0;
for (int i = 0; i < tmp.Length; i++) for (int i = 0; i < tmp.Length; i++)
{ {
...@@ -442,7 +444,7 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes ...@@ -442,7 +444,7 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
{ {
case ResultType.BulkString: case ResultType.BulkString:
var asciiHash = result.GetBlob(); var asciiHash = result.GetBlob();
if (asciiHash == null || asciiHash.Length != 40) return false; if (asciiHash == null || asciiHash.Length != (Sha1HashLength * 2)) return false;
byte[] hash = null; byte[] hash = null;
if (!message.IsInternalCall) if (!message.IsInternalCall)
......
...@@ -450,19 +450,33 @@ internal bool IsSelectable(RedisCommand command) ...@@ -450,19 +450,33 @@ internal bool IsSelectable(RedisCommand command)
return bridge?.IsConnected == true; return bridge?.IsConnected == true;
} }
internal void OnEstablishing(PhysicalConnection connection, TextWriter log) internal Task OnEstablishingAsync(PhysicalConnection connection, TextWriter log)
{ {
try try
{ {
if (connection == null) return; if (connection == null) return Task.CompletedTask;
Handshake(connection, log); var handshake = HandshakeAsync(connection, log);
if (handshake.Status != TaskStatus.RanToCompletion)
return OnEstablishingAsyncAwaited(connection, handshake);
}
catch (Exception ex)
{
connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
}
return Task.CompletedTask;
}
async Task OnEstablishingAsyncAwaited(PhysicalConnection connection, Task handshake)
{
try
{
await handshake;
} }
catch (Exception ex) catch (Exception ex)
{ {
connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex); connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
} }
} }
internal void OnFullyEstablished(PhysicalConnection connection) internal void OnFullyEstablished(PhysicalConnection connection)
{ {
try try
...@@ -627,13 +641,13 @@ private PhysicalBridge CreateBridge(ConnectionType type, TextWriter log) ...@@ -627,13 +641,13 @@ private PhysicalBridge CreateBridge(ConnectionType type, TextWriter log)
return bridge; return bridge;
} }
private void Handshake(PhysicalConnection connection, TextWriter log) private Task HandshakeAsync(PhysicalConnection connection, TextWriter log)
{ {
Multiplexer.LogLocked(log, "Server handshake"); Multiplexer.LogLocked(log, "Server handshake");
if (connection == null) if (connection == null)
{ {
Multiplexer.Trace("No connection!?"); Multiplexer.Trace("No connection!?");
return; return Task.CompletedTask;
} }
Message msg; Message msg;
string password = Multiplexer.RawConfig.Password; string password = Multiplexer.RawConfig.Password;
...@@ -684,7 +698,7 @@ private void Handshake(PhysicalConnection connection, TextWriter log) ...@@ -684,7 +698,7 @@ private void Handshake(PhysicalConnection connection, TextWriter log)
} }
} }
Multiplexer.LogLocked(log, "Flushing outbound buffer"); Multiplexer.LogLocked(log, "Flushing outbound buffer");
connection.Flush(); return connection.FlushAsync();
} }
private void SetConfig<T>(ref T field, T value, [CallerMemberName] string caller = null) private void SetConfig<T>(ref T field, T value, [CallerMemberName] string caller = null)
......
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