Skip to content

Commit

Permalink
Fix ConnectionTime and ClientConnectionId reported by SqlStatistics (#…
Browse files Browse the repository at this point in the history
…341)

* fix sqlstatistics

* add test

* remove excess using

* remove setting closeTimestamp

* rename directory to be case sensitive

* add error message to test
  • Loading branch information
yukiwongky authored Dec 5, 2019
1 parent 0e97cac commit 6ade367
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,9 @@ public Guid ClientConnectionId
else
{
Task reconnectTask = _currentReconnectionTask;
if (reconnectTask != null && !reconnectTask.IsCompleted)
// Connection closed but previously open should return the correct ClientConnectionId
DbConnectionClosedPreviouslyOpened innerConnectionClosed = (InnerConnection as DbConnectionClosedPreviouslyOpened);
if ((reconnectTask != null && !reconnectTask.IsCompleted) || null != innerConnectionClosed)
{
return _originalConnectionId;
}
Expand Down Expand Up @@ -856,6 +858,7 @@ private void CloseInnerConnection()
// The SqlInternalConnectionTds is set to OpenBusy during close, once this happens the cast below will fail and
// the command will no longer be cancelable. It might be desirable to be able to cancel the close operation, but this is
// outside of the scope of Whidbey RTM. See (SqlCommand::Cancel) for other lock.
_originalConnectionId = ClientConnectionId;
InnerConnection.CloseConnection(this, ConnectionFactory);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,9 @@ internal long SafeIncrement(ref long value)
internal void UpdateStatistics()
{
// update connection time
if (_closeTimestamp >= _openTimestamp)
if (_closeTimestamp >= _openTimestamp && long.MaxValue > _closeTimestamp - _openTimestamp)
{
SafeAdd(ref _connectionTime, _closeTimestamp - _openTimestamp);
_connectionTime = _closeTimestamp - _openTimestamp;
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,9 @@ public Guid ClientConnectionId
else
{
Task reconnectTask = _currentReconnectionTask;
if (reconnectTask != null && !reconnectTask.IsCompleted)
// Connection closed but previously open should return the correct ClientConnectionId
DbConnectionClosedPreviouslyOpened innerConnectionClosed = (InnerConnection as DbConnectionClosedPreviouslyOpened);
if ((reconnectTask != null && !reconnectTask.IsCompleted) || null != innerConnectionClosed)
{
return _originalConnectionId;
}
Expand Down Expand Up @@ -1253,6 +1255,7 @@ void CloseInnerConnection()
// The SqlInternalConnectionTds is set to OpenBusy during close, once this happens the cast below will fail and
// the command will no longer be cancelable. It might be desirable to be able to cancel the close opperation, but this is
// outside of the scope of Whidbey RTM. See (SqlCommand::Cancel) for other lock.
_originalConnectionId = ClientConnectionId;
InnerConnection.CloseConnection(this, ConnectionFactory);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,9 @@ internal long SafeIncrement(ref long value)
internal void UpdateStatistics()
{
// update connection time
if (_closeTimestamp >= _openTimestamp)
if (_closeTimestamp >= _openTimestamp && long.MaxValue > _closeTimestamp - _openTimestamp)
{
SafeAdd(ref _connectionTime, _closeTimestamp - _openTimestamp);
_connectionTime = _closeTimestamp - _openTimestamp;
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
<Compile Include="SQL\SqlBulkCopyTest\CopyWidenNullInexactNumerics.cs" />
<Compile Include="SQL\SqlCredentialTest\SqlCredentialTest.cs" />
<Compile Include="SQL\SqlSchemaInfoTest\SqlSchemaInfoTest.cs" />
<Compile Include="SQL\SqlStatisticsTest\SqlStatisticsTest.cs" />
<Compile Include="SQL\SqlBulkCopyTest\AdjustPrecScaleForBulkCopy.cs" />
<Compile Include="SQL\SqlBulkCopyTest\AzureDistributedTransaction.cs" />
<Compile Include="SQL\SqlBulkCopyTest\ErrorOnRowsMarkedAsDeleted.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Data;
using System.Data.Common;
using System.Collections;
using Xunit;

namespace Microsoft.Data.SqlClient.ManualTesting.Tests
{
public class SqlStatisticsTest
{
private static DateTime startTime = new DateTime();
private static Guid clientConnectionId = Guid.Empty;

[CheckConnStrSetupFact]
public static void TestRetrieveStatistics()
{
startTime = DateTime.Now;
SqlConnection connection = new SqlConnection(DataTestUtility.TCPConnectionString);
string text = "SELECT TOP 2000 * from [dbo].[Order Details]";
using (SqlCommand command = new SqlCommand(text))
{
connection.StatisticsEnabled = true;
connection.Open();
connection.StateChange += new StateChangeEventHandler(HandleStateChange);

command.Connection = connection;
using (SqlDataReader dr = command.ExecuteReader())
{
IDictionary stats1 = connection.RetrieveStatistics();

// Ensure ConnectionTime is within a reasonable range
Assert.True((long)stats1["ConnectionTime"] < DateTime.Now.Subtract(startTime).TotalMilliseconds + 1000, "Unexpected ConnectionTime: " + stats1["ConnectionTime"]);
clientConnectionId = connection.ClientConnectionId;
Assert.True(clientConnectionId != Guid.Empty);

int row = 0;
while (dr.Read())
{
row++;
}
}
}
// Ensure calling RetrieveStatistics multiple times do not affect the ConnectionTime
connection.RetrieveStatistics();
connection.RetrieveStatistics();
connection.RetrieveStatistics();
connection.RetrieveStatistics();
connection.RetrieveStatistics();
connection.RetrieveStatistics();
connection.Close();
IDictionary stats2 = connection.RetrieveStatistics();
Assert.True((long)stats2["ConnectionTime"] < DateTime.Now.Subtract(startTime).TotalMilliseconds + 1000, "Unexpected ConnectionTime: " + stats2["ConnectionTime"]);
// Ensure ClientConnectionId remains available even after the connection is closed
Assert.True(connection.ClientConnectionId == clientConnectionId);
}

private static void HandleStateChange(object sender, StateChangeEventArgs args)
{
if (args.CurrentState == ConnectionState.Closed)
{
System.Collections.IDictionary stats = ((SqlConnection)sender).RetrieveStatistics();
Assert.True((long)stats["ConnectionTime"] < DateTime.Now.Subtract(startTime).TotalMilliseconds + 1000, "Unexpected ConnectionTime: " + stats["ConnectionTime"]);
Assert.True(((SqlConnection)sender).ClientConnectionId == clientConnectionId);
}
}
}
}

0 comments on commit 6ade367

Please sign in to comment.