Skip to content

Commit

Permalink
Fix Async + Mars perf issue
Browse files Browse the repository at this point in the history
  • Loading branch information
cheenamalhotra committed Nov 15, 2020
1 parent 9ea1207 commit a6e8db2
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 83 deletions.
Expand Up @@ -189,39 +189,36 @@ public override uint Receive(out SNIPacket packet, int timeout)
try
{
SNIPacket errorPacket;
lock (this)
packet = null;
try
{
packet = null;
try
{
packet = RentPacket(headerSize: 0, dataSize: _bufferSize);
packet.ReadFromStream(_stream);
packet = RentPacket(headerSize: 0, dataSize: _bufferSize);
packet.ReadFromStream(_stream);

if (packet.Length == 0)
{
errorPacket = packet;
packet = null;
var e = new Win32Exception();
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.Receive |SNI|ERR> packet length is 0.");
return ReportErrorAndReleasePacket(errorPacket, (uint)e.NativeErrorCode, 0, e.Message);
}
}
catch (ObjectDisposedException ode)
if (packet.Length == 0)
{
errorPacket = packet;
packet = null;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.Receive |SNI|ERR> ObjectDisposedException message = {0}.", ode.Message);
return ReportErrorAndReleasePacket(errorPacket, ode);
var e = new Win32Exception();
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.Receive |SNI|ERR> packet length is 0.");
return ReportErrorAndReleasePacket(errorPacket, (uint)e.NativeErrorCode, 0, e.Message);
}
catch (IOException ioe)
{
errorPacket = packet;
packet = null;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.Receive |SNI|ERR> IOException message = {0}.", ioe.Message);
return ReportErrorAndReleasePacket(errorPacket, ioe);
}
return TdsEnums.SNI_SUCCESS;
}
catch (ObjectDisposedException ode)
{
errorPacket = packet;
packet = null;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.Receive |SNI|ERR> ObjectDisposedException message = {0}.", ode.Message);
return ReportErrorAndReleasePacket(errorPacket, ode);
}
catch (IOException ioe)
{
errorPacket = packet;
packet = null;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNINpHandle.Receive |SNI|ERR> IOException message = {0}.", ioe.Message);
return ReportErrorAndReleasePacket(errorPacket, ioe);
}
return TdsEnums.SNI_SUCCESS;
}
finally
{
Expand Down Expand Up @@ -286,7 +283,7 @@ public override uint Send(SNIPacket packet)
}

// this lock ensures that two packets are not being written to the transport at the same time
// so that sending a standard and an out-of-band packet are both written atomically no data is
// so that sending a standard and an out-of-band packet are both written atomically no data is
// interleaved
lock (_sendSync)
{
Expand Down
Expand Up @@ -143,7 +143,7 @@ public SNITCPHandle(string serverName, int port, long timerExpire, object callba
bool reportError = true;

// We will always first try to connect with serverName as before and let the DNS server to resolve the serverName.
// If the DSN resolution fails, we will try with IPs in the DNS cache if existed. We try with IPv4 first and followed by IPv6 if
// If the DSN resolution fails, we will try with IPs in the DNS cache if existed. We try with IPv4 first and followed by IPv6 if
// IPv4 fails. The exceptions will be throw to upper level and be handled as before.
try
{
Expand Down Expand Up @@ -582,7 +582,7 @@ public override uint Send(SNIPacket packet)
}

// this lock ensures that two packets are not being written to the transport at the same time
// so that sending a standard and an out-of-band packet are both written atomically no data is
// so that sending a standard and an out-of-band packet are both written atomically no data is
// interleaved
lock (_sendSync)
{
Expand Down Expand Up @@ -623,67 +623,65 @@ public override uint Send(SNIPacket packet)
public override uint Receive(out SNIPacket packet, int timeoutInMilliseconds)
{
SNIPacket errorPacket;
lock (this)
packet = null;
try
{
packet = null;
try
if (timeoutInMilliseconds > 0)
{
if (timeoutInMilliseconds > 0)
{
_socket.ReceiveTimeout = timeoutInMilliseconds;
}
else if (timeoutInMilliseconds == -1)
{ // SqlCient internally represents infinite timeout by -1, and for TcpClient this is translated to a timeout of 0
_socket.ReceiveTimeout = 0;
}
else
{
// otherwise it is timeout for 0 or less than -1
ReportTcpSNIError(0, SNICommon.ConnTimeoutError, string.Empty);
return TdsEnums.SNI_WAIT_TIMEOUT;
}

packet = RentPacket(headerSize: 0, dataSize: _bufferSize);
packet.ReadFromStream(_stream);

if (packet.Length == 0)
{
errorPacket = packet;
packet = null;
var e = new Win32Exception();
return ReportErrorAndReleasePacket(errorPacket, (uint)e.NativeErrorCode, 0, e.Message);
}

return TdsEnums.SNI_SUCCESS;
_socket.ReceiveTimeout = timeoutInMilliseconds;
}
catch (ObjectDisposedException ode)
else if (timeoutInMilliseconds == -1)
{
errorPacket = packet;
packet = null;
return ReportErrorAndReleasePacket(errorPacket, ode);
// SqlClient internally represents infinite timeout by -1, and for TcpClient this is translated to a timeout of 0
_socket.ReceiveTimeout = 0;
}
catch (SocketException se)
else
{
errorPacket = packet;
packet = null;
return ReportErrorAndReleasePacket(errorPacket, se);
// otherwise it is timeout for 0 or less than -1
ReportTcpSNIError(0, SNICommon.ConnTimeoutError, string.Empty);
return TdsEnums.SNI_WAIT_TIMEOUT;
}
catch (IOException ioe)

packet = RentPacket(headerSize: 0, dataSize: _bufferSize);
packet.ReadFromStream(_stream);

if (packet.Length == 0)
{
errorPacket = packet;
packet = null;
uint errorCode = ReportErrorAndReleasePacket(errorPacket, ioe);
if (ioe.InnerException is SocketException socketException && socketException.SocketErrorCode == SocketError.TimedOut)
{
errorCode = TdsEnums.SNI_WAIT_TIMEOUT;
}

return errorCode;
var e = new Win32Exception();
return ReportErrorAndReleasePacket(errorPacket, (uint)e.NativeErrorCode, 0, e.Message);
}
finally

return TdsEnums.SNI_SUCCESS;
}
catch (ObjectDisposedException ode)
{
errorPacket = packet;
packet = null;
return ReportErrorAndReleasePacket(errorPacket, ode);
}
catch (SocketException se)
{
errorPacket = packet;
packet = null;
return ReportErrorAndReleasePacket(errorPacket, se);
}
catch (IOException ioe)
{
errorPacket = packet;
packet = null;
uint errorCode = ReportErrorAndReleasePacket(errorPacket, ioe);
if (ioe.InnerException is SocketException socketException && socketException.SocketErrorCode == SocketError.TimedOut)
{
_socket.ReceiveTimeout = 0;
errorCode = TdsEnums.SNI_WAIT_TIMEOUT;
}

return errorCode;
}
finally
{
_socket.ReceiveTimeout = 0;
}
}

Expand Down Expand Up @@ -750,15 +748,15 @@ public override uint CheckConnection()
{
try
{
// _socket.Poll method with argument SelectMode.SelectRead returns
// _socket.Poll method with argument SelectMode.SelectRead returns
// True : if Listen has been called and a connection is pending, or
// True : if data is available for reading, or
// True : if the connection has been closed, reset, or terminated, i.e no active connection.
// False : otherwise.
// _socket.Available property returns the number of bytes of data available to read.
//
// Since _socket.Connected alone doesn't guarantee if the connection is still active, we use it in
// combination with _socket.Poll method and _socket.Available == 0 check. When both of them
// Since _socket.Connected alone doesn't guarantee if the connection is still active, we use it in
// combination with _socket.Poll method and _socket.Available == 0 check. When both of them
// return true we can safely determine that the connection is no longer active.
if (!_socket.Connected || (_socket.Poll(100, SelectMode.SelectRead) && _socket.Available == 0))
{
Expand Down
Expand Up @@ -13,9 +13,7 @@ public class AsyncCancelledConnectionsTest
{
private readonly ITestOutputHelper _output;

// TODO: Set back the count to 100 tasks after fixing driver issue #422.
// Currently the count is reduced to 25 as we encounter error 258 for "Encrypted" connections.
private const int NumberOfTasks = 25; // How many attempts to poison the connection pool we will try
private const int NumberOfTasks = 100; // How many attempts to poison the connection pool we will try

private const int NumberOfNonPoisoned = 10; // Number of normal requests for each attempt

Expand Down

0 comments on commit a6e8db2

Please sign in to comment.