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 all commits
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 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 @@ -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,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 @@ -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 @@ -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 @@ -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

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">
karinazhou marked this conversation as resolved.
Show resolved Hide resolved
<value>Server Process Id (SPID) of the active connection.</value>
</data>
</root>