Skip to content

Commit 580b172

Browse files
Introduce SPID connection property (#660)
1 parent 7b82e07 commit 580b172

File tree

13 files changed

+129
-42
lines changed

13 files changed

+129
-42
lines changed

doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,11 @@ GO
10961096

10971097
<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>
10981098
</ServerVersion>
1099+
<ServerProcessId>
1100+
<summary>Gets the server process Id (SPID) of the active connection.</summary>
1101+
<value>The server process Id (SPID) of the active connection.</value>
1102+
<remarks>Returns 0 if the connection is inactive on the client side.</remarks>
1103+
</ServerProcessId>
10991104
<State>
11001105
<summary>Indicates the state of the <see cref="T:Microsoft.Data.SqlClient.SqlConnection" /> during the most recent network operation performed on the connection.</summary>
11011106
<value>An <see cref="T:System.Data.ConnectionState" /> enumeration.</value>

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ internal string SQLDNSCachingSupportedState
561561

562562
if (null != innerConnection)
563563
{
564-
result = innerConnection.IsSQLDNSCachingSupported ? "true": "false";
564+
result = innerConnection.IsSQLDNSCachingSupported ? "true" : "false";
565565
}
566566
else
567567
{
@@ -584,7 +584,7 @@ internal string SQLDNSCachingSupportedStateBeforeRedirect
584584

585585
if (null != innerConnection)
586586
{
587-
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true": "false";
587+
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true" : "false";
588588
}
589589
else
590590
{
@@ -671,6 +671,13 @@ public override string ServerVersion
671671
get => GetOpenTdsConnection().ServerVersion;
672672
}
673673

674+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/ServerProcessId/*' />
675+
public int ServerProcessId
676+
{
677+
get => State.Equals(ConnectionState.Open) | State.Equals(ConnectionState.Executing) | State.Equals(ConnectionState.Fetching) ?
678+
GetOpenTdsConnection().ServerProcessId : 0;
679+
}
680+
674681
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/State/*' />
675682
public override ConnectionState State
676683
{

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,14 @@ public override string ServerVersion
692692
}
693693
}
694694

695+
public int ServerProcessId
696+
{
697+
get
698+
{
699+
return Parser._physicalStateObj._spid;
700+
}
701+
}
702+
695703
protected override bool UnbindOnTransactionCompletion
696704
{
697705
get

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsEnums.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ internal static class TdsEnums
5353
// header constants
5454
public const int HEADER_LEN = 8;
5555
public const int HEADER_LEN_FIELD_OFFSET = 2;
56+
public const int SPID_OFFSET = 4;
5657
public const int YUKON_HEADER_LEN = 12; //Yukon headers also include a MARS session id
5758
public const int MARS_ID_OFFSET = 8;
5859
public const int HEADERTYPE_QNOTIFICATION = 1;

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ internal enum SnapshottedStateFlags : byte
8989
/// </summary>
9090
internal int _inBytesPacket;
9191

92+
internal int _spid; // SPID of the current connection
93+
9294
// Packet state variables
9395
internal byte _outputMessageType; // tds header type
9496
internal byte _messageStatus; // tds header status
@@ -1019,6 +1021,8 @@ internal bool TryProcessHeader()
10191021
(int)_partialHeaderBuffer[TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
10201022

10211023
_messageStatus = _partialHeaderBuffer[1];
1024+
_spid = _partialHeaderBuffer[TdsEnums.SPID_OFFSET] << 8 |
1025+
_partialHeaderBuffer[TdsEnums.SPID_OFFSET + 1];
10221026
}
10231027
else
10241028
{
@@ -1052,8 +1056,10 @@ internal bool TryProcessHeader()
10521056
{
10531057
// normal header processing...
10541058
_messageStatus = _inBuff[_inBytesUsed + 1];
1055-
_inBytesPacket = ((int)_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8 |
1056-
(int)_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
1059+
_inBytesPacket = (_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8 |
1060+
_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
1061+
_spid = _inBuff[_inBytesUsed + TdsEnums.SPID_OFFSET] << 8 |
1062+
_inBuff[_inBytesUsed + TdsEnums.SPID_OFFSET + 1];
10571063
_inBytesUsed += _inputHeaderLen;
10581064

10591065
AssertValidState();
@@ -3481,35 +3487,35 @@ internal void SendAttention(bool mustTakeWriteLock = false)
34813487
if (!_skipSendAttention)
34823488
{
34833489
#endif
3484-
// Take lock and send attention
3485-
bool releaseLock = false;
3486-
if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose))
3490+
// Take lock and send attention
3491+
bool releaseLock = false;
3492+
if ((mustTakeWriteLock) && (!_parser.Connection.ThreadHasParserLockForClose))
3493+
{
3494+
releaseLock = true;
3495+
_parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false);
3496+
_parser.Connection.ThreadHasParserLockForClose = true;
3497+
}
3498+
try
3499+
{
3500+
// Check again (just in case the connection was closed while we were waiting)
3501+
if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken)
34873502
{
3488-
releaseLock = true;
3489-
_parser.Connection._parserLock.Wait(canReleaseFromAnyThread: false);
3490-
_parser.Connection.ThreadHasParserLockForClose = true;
3503+
return;
34913504
}
3492-
try
3493-
{
3494-
// Check again (just in case the connection was closed while we were waiting)
3495-
if (_parser.State == TdsParserState.Closed || _parser.State == TdsParserState.Broken)
3496-
{
3497-
return;
3498-
}
34993505

3500-
uint sniError;
3501-
_parser._asyncWrite = false; // stop async write
3502-
SNIWritePacket(attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false);
3503-
SqlClientEventSource.Log.TraceEvent("<sc.TdsParser.SendAttention|{0}> Send Attention ASync.", "Info");
3504-
}
3505-
finally
3506+
uint sniError;
3507+
_parser._asyncWrite = false; // stop async write
3508+
SNIWritePacket(attnPacket, out sniError, canAccumulate: false, callerHasConnectionLock: false);
3509+
SqlClientEventSource.Log.TraceEvent("<sc.TdsParser.SendAttention|{0}> Send Attention ASync.", "Info");
3510+
}
3511+
finally
3512+
{
3513+
if (releaseLock)
35063514
{
3507-
if (releaseLock)
3508-
{
3509-
_parser.Connection.ThreadHasParserLockForClose = false;
3510-
_parser.Connection._parserLock.Release();
3511-
}
3515+
_parser.Connection.ThreadHasParserLockForClose = false;
3516+
_parser.Connection._parserLock.Release();
35123517
}
3518+
}
35133519
#if DEBUG
35143520
}
35153521
#endif

src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@
128128
</Compile>
129129
<Compile Include="..\..\src\Microsoft\Data\SqlClient\Server\ExtendedClrTypeCode.cs">
130130
<Link>Microsoft\Data\SqlClient\Server\ExtendedClrTypeCode.cs</Link>
131-
</Compile>
131+
</Compile>
132132
<Compile Include="..\..\src\Microsoft\Data\SqlClient\Server\IBinarySerialize.cs">
133133
<Link>Microsoft\Data\SqlClient\Server\IBinarySerialize.cs</Link>
134134
</Compile>

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ internal string SQLDNSCachingSupportedState
738738

739739
if (null != innerConnection)
740740
{
741-
result = innerConnection.IsSQLDNSCachingSupported ? "true": "false";
741+
result = innerConnection.IsSQLDNSCachingSupported ? "true" : "false";
742742
}
743743
else
744744
{
@@ -762,7 +762,7 @@ internal string SQLDNSCachingSupportedStateBeforeRedirect
762762

763763
if (null != innerConnection)
764764
{
765-
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true": "false";
765+
result = innerConnection.IsDNSCachingBeforeRedirectSupported ? "true" : "false";
766766
}
767767
else
768768
{
@@ -878,6 +878,18 @@ override public string ServerVersion
878878
}
879879
}
880880

881+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/ServerProcessId/*' />
882+
[
883+
Browsable(false),
884+
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
885+
ResDescription(StringsHelper.ResourceNames.SqlConnection_ServerProcessId),
886+
]
887+
public int ServerProcessId
888+
{
889+
get => State.Equals(ConnectionState.Open) | State.Equals(ConnectionState.Executing) | State.Equals(ConnectionState.Fetching) ?
890+
GetOpenTdsConnection().ServerProcessId : 0;
891+
}
892+
881893
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlConnection.xml' path='docs/members[@name="SqlConnection"]/State/*' />
882894
[
883895
Browsable(false),

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,13 @@ override public string ServerVersion
803803
(short)_loginAck.minorVersion, _loginAck.buildNum));
804804
}
805805
}
806+
public int ServerProcessId
807+
{
808+
get
809+
{
810+
return Parser._physicalStateObj._spid;
811+
}
812+
}
806813

807814
/// <summary>
808815
/// Get boolean that specifies whether an enlisted transaction can be unbound from

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsEnums.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ internal static class TdsEnums
6767
// header constants
6868
public const int HEADER_LEN = 8;
6969
public const int HEADER_LEN_FIELD_OFFSET = 2;
70+
public const int SPID_OFFSET = 4;
7071
public const int YUKON_HEADER_LEN = 12; //Yukon headers also include a MARS session id
7172
public const int MARS_ID_OFFSET = 8;
7273
public const int HEADERTYPE_QNOTIFICATION = 1;

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ internal int ObjectID
7171
internal int _inBytesUsed = 0; // number of bytes used in internal read buffer
7272
internal int _inBytesRead = 0; // number of bytes read into internal read buffer
7373
internal int _inBytesPacket = 0; // number of bytes left in packet
74+
75+
internal int _spid; // SPID of the current connection
7476

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

11331135
_messageStatus = _partialHeaderBuffer[1];
1136+
_spid = _partialHeaderBuffer[TdsEnums.SPID_OFFSET] << 8 |
1137+
_partialHeaderBuffer[TdsEnums.SPID_OFFSET + 1];
11341138
}
11351139
else
11361140
{
@@ -1166,8 +1170,10 @@ internal bool TryProcessHeader()
11661170
{
11671171
// normal header processing...
11681172
_messageStatus = _inBuff[_inBytesUsed + 1];
1169-
_inBytesPacket = ((int)_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8 |
1170-
(int)_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
1173+
_inBytesPacket = (_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET] << 8 |
1174+
_inBuff[_inBytesUsed + TdsEnums.HEADER_LEN_FIELD_OFFSET + 1]) - _inputHeaderLen;
1175+
_spid = _inBuff[_inBytesUsed + TdsEnums.SPID_OFFSET] << 8 |
1176+
_inBuff[_inBytesUsed + TdsEnums.SPID_OFFSET + 1];
11711177
_inBytesUsed += _inputHeaderLen;
11721178

11731179
AssertValidState();

0 commit comments

Comments
 (0)