Skip to content

Commit

Permalink
Introduce SPID connection property (#660)
Browse files Browse the repository at this point in the history
  • Loading branch information
cheenamalhotra committed Jul 23, 2020
1 parent 7b82e07 commit 580b172
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 42 deletions.
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 the client side.</remarks>
</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 @@ -561,7 +561,7 @@ internal string SQLDNSCachingSupportedState

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

if (null != innerConnection)
{
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true": "false";
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true" : "false";
}
else
{
Expand Down Expand Up @@ -671,6 +671,13 @@ 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) | State.Equals(ConnectionState.Executing) | State.Equals(ConnectionState.Fetching) ?
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 @@ -692,6 +692,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 @@ -128,7 +128,7 @@
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\Server\ExtendedClrTypeCode.cs">
<Link>Microsoft\Data\SqlClient\Server\ExtendedClrTypeCode.cs</Link>
</Compile>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\Server\IBinarySerialize.cs">
<Link>Microsoft\Data\SqlClient\Server\IBinarySerialize.cs</Link>
</Compile>
Expand Down
Expand Up @@ -738,7 +738,7 @@ internal string SQLDNSCachingSupportedState

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

if (null != innerConnection)
{
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true": "false";
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true" : "false";
}
else
{
Expand Down Expand Up @@ -878,6 +878,18 @@ 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) | State.Equals(ConnectionState.Executing) | State.Equals(ConnectionState.Fetching) ?
GetOpenTdsConnection().ServerProcessId : 0;
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlConnection.xml' path='docs/members[@name="SqlConnection"]/State/*' />
[
Browsable(false),
Expand Down
Expand Up @@ -803,6 +803,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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx
Expand Up @@ -4560,4 +4560,7 @@
<data name="SQL_SettingCredentialWithInteractive" xml:space="preserve">
<value>Cannot set the Credential property if 'Authentication=Active Directory Interactive' has been specified in the connection string.</value>
</data>
<data name="SqlConnection_ServerProcessId" xml:space="preserve">
<value>Server Process Id (SPID) of the active connection.</value>
</data>
</root>

0 comments on commit 580b172

Please sign in to comment.