Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce SPID connection property #660

Merged
merged 5 commits into from Jul 23, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml
Expand Up @@ -1096,6 +1096,11 @@ GO

<see cref="P:Microsoft.Data.SqlClient.SqlConnection.ServerVersion" /> was called while the returned Task was not completed and the connection was not opened after a call to <see cref="M:Microsoft.Data.SqlClient.SqlConnection.OpenAsync(System.Threading.CancellationToken)" />.</exception>
</ServerVersion>
<ServerProcessId>
<summary>Gets the server process Id (SPID) of the active connection.</summary>
<value>The server process Id (SPID) of the active connection.</value>
<remarks>Returns 0 if the connection is inactive on client side.</remarks>
cheenamalhotra marked this conversation as resolved.
Show resolved Hide resolved
</ServerProcessId>
<State>
<summary>Indicates the state of the <see cref="T:Microsoft.Data.SqlClient.SqlConnection" /> during the most recent network operation performed on the connection.</summary>
<value>An <see cref="T:System.Data.ConnectionState" /> enumeration.</value>
Expand Down
Expand Up @@ -560,7 +560,7 @@ internal string SQLDNSCachingSupportedState

if (null != innerConnection)
{
result = innerConnection.IsSQLDNSCachingSupported ? "true": "false";
result = innerConnection.IsSQLDNSCachingSupported ? "true" : "false";
}
else
{
Expand All @@ -583,7 +583,7 @@ internal string SQLDNSCachingSupportedStateBeforeRedirect

if (null != innerConnection)
{
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true": "false";
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true" : "false";
}
else
{
Expand Down Expand Up @@ -670,6 +670,12 @@ public override string ServerVersion
get => GetOpenTdsConnection().ServerVersion;
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/ServerProcessId/*' />
public int ServerProcessId
{
get => State.Equals(ConnectionState.Open) ? GetOpenTdsConnection().ServerProcessId : 0;
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/State/*' />
public override ConnectionState State
{
Expand Down
Expand Up @@ -675,6 +675,14 @@ public override string ServerVersion
}
}

public int ServerProcessId
{
get
{
return Parser._physicalStateObj._spid;
}
}

protected override bool UnbindOnTransactionCompletion
{
get
Expand Down
Expand Up @@ -53,6 +53,7 @@ internal static class TdsEnums
// header constants
public const int HEADER_LEN = 8;
public const int HEADER_LEN_FIELD_OFFSET = 2;
public const int SPID_OFFSET = 4;
public const int YUKON_HEADER_LEN = 12; //Yukon headers also include a MARS session id
public const int MARS_ID_OFFSET = 8;
public const int HEADERTYPE_QNOTIFICATION = 1;
Expand Down
Expand Up @@ -89,6 +89,8 @@ internal enum SnapshottedStateFlags : byte
/// </summary>
internal int _inBytesPacket;

internal int _spid; // SPID of the current connection

// Packet state variables
internal byte _outputMessageType; // tds header type
internal byte _messageStatus; // tds header status
Expand Down Expand Up @@ -1019,6 +1021,8 @@ internal bool TryProcessHeader()
(int)_partialHeaderBuffer[TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;

_messageStatus = _partialHeaderBuffer[1];
_spid = _partialHeaderBuffer[TdsEnums.SPID_OFFSET] << 8 |
_partialHeaderBuffer[TdsEnums.SPID_OFFSET + 1];
}
else
{
Expand Down Expand Up @@ -1052,8 +1056,10 @@ internal bool TryProcessHeader()
{
// normal header processing...
_messageStatus = _inBuff[_inBytesUsed + 1];
_inBytesPacket = ((int)_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8 |
(int)_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
_inBytesPacket = (_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8 |
_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
_spid = _inBuff[_inBytesUsed + TdsEnums.SPID_OFFSET] << 8 |
_inBuff[_inBytesUsed + TdsEnums.SPID_OFFSET + 1];
_inBytesUsed += _inputHeaderLen;

AssertValidState();
Expand Down Expand Up @@ -3481,35 +3487,35 @@ internal void SendAttention(bool mustTakeWriteLock = false)
if (!_skipSendAttention)
{
#endif
// Take lock and send attention
bool releaseLock = false;
if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose))
// Take lock and send attention
bool releaseLock = false;
if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose))
{
releaseLock = true;
_parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false);
_parser.Connection.ThreadHasParserLockForClose = true;
}
try
{
// Check again (just in case the connection was closed while we were waiting)
if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken)
{
releaseLock = true;
_parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false);
_parser.Connection.ThreadHasParserLockForClose = true;
return;
}
try
{
// Check again (just in case the connection was closed while we were waiting)
if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken)
{
return;
}

uint sniError;
_parser._asyncWrite = false; // stop async write
SNIWritePacket(attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false);
SqlClientEventSource.Log.TraceEvent("<sc.TdsParser.SendAttention|{0}> Send Attention ASync.", "Info");
}
finally
uint sniError;
_parser._asyncWrite = false; // stop async write
SNIWritePacket(attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false);
SqlClientEventSource.Log.TraceEvent("<sc.TdsParser.SendAttention|{0}> Send Attention ASync.", "Info");
}
finally
{
if (releaseLock)
{
if (releaseLock)
{
_parser.Connection.ThreadHasParserLockForClose = false;
_parser.Connection._parserLock.Release();
}
_parser.Connection.ThreadHasParserLockForClose = false;
_parser.Connection._parserLock.Release();
}
}
#if DEBUG
}
#endif
Expand Down
Expand Up @@ -878,6 +878,17 @@ override public string ServerVersion
}
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/ServerProcessId/*' />
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
ResDescription(StringsHelper.ResourceNames.SqlConnection_ServerProcessId),
]
public int ServerProcessId
{
get => State.Equals(ConnectionState.Open) ? GetOpenTdsConnection().ServerProcessId : 0;
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlConnection.xml' path='docs/members[@name="SqlConnection"]/State/*' />
[
Browsable(false),
Expand Down
Expand Up @@ -788,6 +788,13 @@ override public string ServerVersion
(short)_loginAck.minorVersion, _loginAck.buildNum));
}
}
public int ServerProcessId
{
get
{
return Parser._physicalStateObj._spid;
}
}

/// <summary>
/// Get boolean that specifies whether an enlisted transaction can be unbound from
Expand Down
Expand Up @@ -67,6 +67,7 @@ internal static class TdsEnums
// header constants
public const int HEADER_LEN = 8;
public const int HEADER_LEN_FIELD_OFFSET = 2;
public const int SPID_OFFSET = 4;
public const int YUKON_HEADER_LEN = 12; //Yukon headers also include a MARS session id
public const int MARS_ID_OFFSET = 8;
public const int HEADERTYPE_QNOTIFICATION = 1;
Expand Down
Expand Up @@ -71,6 +71,8 @@ internal int ObjectID
internal int _inBytesUsed = 0; // number of bytes used in internal read buffer
internal int _inBytesRead = 0; // number of bytes read into internal read buffer
internal int _inBytesPacket = 0; // number of bytes left in packet

internal int _spid; // SPID of the current connection

// Packet state variables
internal byte _outputMessageType = 0; // tds header type
Expand Down Expand Up @@ -1131,6 +1133,8 @@ internal bool TryProcessHeader()
(int)_partialHeaderBuffer[TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;

_messageStatus = _partialHeaderBuffer[1];
_spid = _partialHeaderBuffer[TdsEnums.SPID_OFFSET] << 8 |
_partialHeaderBuffer[TdsEnums.SPID_OFFSET + 1];
}
else
{
Expand Down Expand Up @@ -1166,8 +1170,10 @@ internal bool TryProcessHeader()
{
// normal header processing...
_messageStatus = _inBuff[_inBytesUsed + 1];
_inBytesPacket = ((int)_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8 |
(int)_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
_inBytesPacket = (_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8 |
_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
_spid = _inBuff[_inBytesUsed + TdsEnums.SPID_OFFSET] << 8 |
_inBuff[_inBytesUsed + TdsEnums.SPID_OFFSET + 1];
_inBytesUsed += _inputHeaderLen;

AssertValidState();
Expand Down
Expand Up @@ -27,14 +27,15 @@ public static class ConnectivityTest
private static readonly string s_dropDatabaseCmd = $"DROP DATABASE {s_databaseName}";

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
public static void EnvironmentHostNameTest()
public static void EnvironmentHostNameSPIDTest()
{
SqlConnectionStringBuilder builder = (new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString) { Pooling = true });
builder.ApplicationName = "HostNameTest";

using (SqlConnection sqlConnection = new SqlConnection(builder.ConnectionString))
{
sqlConnection.Open();
int sqlclientSPID = sqlConnection.ServerProcessId;
cheenamalhotra marked this conversation as resolved.
Show resolved Hide resolved
int sessionSpid;

using (SqlCommand cmd = new SqlCommand("SELECT @@SPID", sqlConnection))
Expand All @@ -44,6 +45,8 @@ public static void EnvironmentHostNameTest()
sessionSpid = reader.GetInt16(0);
}

Assert.Equal(sqlclientSPID, sessionSpid);
cheenamalhotra marked this conversation as resolved.
Show resolved Hide resolved

using (SqlCommand command = new SqlCommand("sp_who2", sqlConnection))
using (SqlDataReader reader = command.ExecuteReader())
{
Expand All @@ -55,7 +58,7 @@ public static void EnvironmentHostNameTest()
int spidOrdinal = reader.GetOrdinal(COL_SPID);
string spid = reader.GetString(spidOrdinal);

if (programName != null && programName.Trim().Equals(builder.ApplicationName) && Int16.Parse(spid) == sessionSpid)
if (programName != null && programName.Trim().Equals(builder.ApplicationName) && short.Parse(spid) == sessionSpid)
{
// Get the hostname
int hostnameOrdinal = reader.GetOrdinal(COL_HOSTNAME);
Expand Down Expand Up @@ -106,11 +109,11 @@ public static void ConnectionTimeoutTestWithThread()
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))]
public static void ProcessIdTest()
public static void LocalProcessIdTest()
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TCPConnectionString);
string sqlProviderName = builder.ApplicationName;
string sqlProviderProcessID = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
string sqlProviderProcessID = Process.GetCurrentProcess().Id.ToString();

using (SqlConnection sqlConnection = new SqlConnection(builder.ConnectionString))
{
Expand Down