Skip to content

Commit 84d914c

Browse files
authored
[6.0] Backport BAG failover fix. Ignore server provided failover partner. (#3703)
* Backport fix. * Fix merge conflicts. * Add test case. Doesn't compile. * Adjust usage of test servers and app context. * Add failover and prelogin count capabilities to test server. Update test case. * Set backing field using reflection. * Try clearing pool to make test more reliable. * Use string.Empty * Review changes * Update app context switch reflection.
1 parent 1542afd commit 84d914c

File tree

8 files changed

+225
-57
lines changed

8 files changed

+225
-57
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3611,7 +3611,7 @@ private void CheckNotificationStateAndAutoEnlist()
36113611
}
36123612

36133613
Notification.Options = SqlDependency.GetDefaultComposedOptions(_activeConnection.DataSource,
3614-
InternalTdsConnection.ServerProvidedFailOverPartner,
3614+
InternalTdsConnection.ServerProvidedFailoverPartner,
36153615
identityUserName, _activeConnection.Database);
36163616
}
36173617

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

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ internal SessionData CurrentSessionData
307307
// FOR CONNECTION RESET MANAGEMENT
308308
private bool _fResetConnection;
309309
private string _originalDatabase;
310-
private string _currentFailoverPartner; // only set by ENV change from server
311310
private string _originalLanguage;
312311
private string _currentLanguage;
313312
private int _currentPacketSize;
@@ -676,13 +675,7 @@ internal TdsParser Parser
676675
}
677676
}
678677

679-
internal string ServerProvidedFailOverPartner
680-
{
681-
get
682-
{
683-
return _currentFailoverPartner;
684-
}
685-
}
678+
internal string ServerProvidedFailoverPartner { get; private set; }
686679

687680
internal SqlConnectionPoolGroupProviderInfo PoolGroupProviderInfo
688681
{
@@ -1461,7 +1454,7 @@ private void OpenLoginEnlist(TimeoutTimer timeout,
14611454
throw SQL.ROR_FailoverNotSupportedConnString();
14621455
}
14631456

1464-
if (ServerProvidedFailOverPartner != null)
1457+
if (ServerProvidedFailoverPartner != null)
14651458
{
14661459
throw SQL.ROR_FailoverNotSupportedServer(this);
14671460
}
@@ -1574,7 +1567,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
15741567
newSecurePassword,
15751568
connectionOptions.MultiSubnetFailover ? intervalTimer : timeout);
15761569

1577-
if (connectionOptions.MultiSubnetFailover && ServerProvidedFailOverPartner != null)
1570+
if (connectionOptions.MultiSubnetFailover && ServerProvidedFailoverPartner != null)
15781571
{
15791572
// connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used
15801573
throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
@@ -1602,7 +1595,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
16021595
_currentPacketSize = ConnectionOptions.PacketSize;
16031596
_currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
16041597
CurrentDatabase = _originalDatabase = ConnectionOptions.InitialCatalog;
1605-
_currentFailoverPartner = null;
1598+
ServerProvidedFailoverPartner = null;
16061599
_instanceName = string.Empty;
16071600

16081601
routingAttempts++;
@@ -1641,7 +1634,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
16411634
// We only get here when we failed to connect, but are going to re-try
16421635

16431636
// Switch to failover logic if the server provided a partner
1644-
if (ServerProvidedFailOverPartner != null)
1637+
if (ServerProvidedFailoverPartner != null)
16451638
{
16461639
if (connectionOptions.MultiSubnetFailover)
16471640
{
@@ -1657,7 +1650,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
16571650
LoginWithFailover(
16581651
true, // start by using failover partner, since we already failed to connect to the primary
16591652
serverInfo,
1660-
ServerProvidedFailOverPartner,
1653+
ServerProvidedFailoverPartner,
16611654
newPassword,
16621655
newSecurePassword,
16631656
redirectedUserInstance,
@@ -1679,8 +1672,13 @@ private void LoginNoFailover(ServerInfo serverInfo,
16791672
{
16801673
// We must wait for CompleteLogin to finish for to have the
16811674
// env change from the server to know its designated failover
1682-
// partner; save this information in _currentFailoverPartner.
1683-
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, ServerProvidedFailOverPartner);
1675+
// partner; save this information in ServerProvidedFailoverPartner.
1676+
1677+
// When ignoring server provided failover partner, we must pass in the original failover partner from the connection string.
1678+
// Otherwise the pool group's failover partner designation will be updated to point to the server provided value.
1679+
string actualFailoverPartner = LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner ? string.Empty : ServerProvidedFailoverPartner;
1680+
1681+
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, actualFailoverPartner);
16841682
}
16851683
CurrentDataSource = originalServerInfo.UserServerName;
16861684
}
@@ -1741,7 +1739,7 @@ TimeoutTimer timeout
17411739
ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost, connectionOptions.FailoverPartnerSPN);
17421740

17431741
ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions);
1744-
if (ServerProvidedFailOverPartner == null)
1742+
if (ServerProvidedFailoverPartner == null)
17451743
{
17461744
ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions);
17471745
}
@@ -1791,12 +1789,21 @@ TimeoutTimer timeout
17911789
ServerInfo currentServerInfo;
17921790
if (useFailoverHost)
17931791
{
1794-
// Primary server may give us a different failover partner than the connection string indicates. Update it
1795-
if (ServerProvidedFailOverPartner != null && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner)
1792+
// Primary server may give us a different failover partner than the connection string indicates.
1793+
// Update it only if we are respecting server-provided failover partner values.
1794+
if (ServerProvidedFailoverPartner != null && failoverServerInfo.ResolvedServerName != ServerProvidedFailoverPartner)
17961795
{
1797-
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, new failover partner={1}", ObjectID, ServerProvidedFailOverPartner);
1798-
failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailOverPartner);
1796+
if (LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner)
1797+
{
1798+
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, Ignoring server provided failover partner '{1}' due to IgnoreServerProvidedFailoverPartner AppContext switch.", ObjectID, ServerProvidedFailoverPartner);
1799+
}
1800+
else
1801+
{
1802+
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, new failover partner={1}", ObjectID, ServerProvidedFailoverPartner);
1803+
failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailoverPartner);
1804+
}
17991805
}
1806+
18001807
currentServerInfo = failoverServerInfo;
18011808
_timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
18021809
}
@@ -1845,7 +1852,7 @@ TimeoutTimer timeout
18451852
_currentPacketSize = connectionOptions.PacketSize;
18461853
_currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
18471854
CurrentDatabase = _originalDatabase = connectionOptions.InitialCatalog;
1848-
_currentFailoverPartner = null;
1855+
ServerProvidedFailoverPartner = null;
18491856
_instanceName = string.Empty;
18501857

18511858
AttemptOneLogin(
@@ -1906,7 +1913,7 @@ TimeoutTimer timeout
19061913
_activeDirectoryAuthTimeoutRetryHelper.State = ActiveDirectoryAuthenticationTimeoutRetryState.HasLoggedIn;
19071914

19081915
// if connected to failover host, but said host doesn't have DbMirroring set up, throw an error
1909-
if (useFailoverHost && ServerProvidedFailOverPartner == null)
1916+
if (useFailoverHost && ServerProvidedFailoverPartner == null)
19101917
{
19111918
throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase);
19121919
}
@@ -1915,8 +1922,13 @@ TimeoutTimer timeout
19151922
{
19161923
// We must wait for CompleteLogin to finish for to have the
19171924
// env change from the server to know its designated failover
1918-
// partner; save this information in _currentFailoverPartner.
1919-
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
1925+
// partner.
1926+
1927+
// When ignoring server provided failover partner, we must pass in the original failover partner from the connection string.
1928+
// Otherwise the pool group's failover partner designation will be updated to point to the server provided value.
1929+
string actualFailoverPartner = LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner ? failoverHost : ServerProvidedFailoverPartner;
1930+
1931+
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, actualFailoverPartner);
19201932
}
19211933
CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
19221934
}
@@ -2138,7 +2150,8 @@ internal void OnEnvChange(SqlEnvChange rec)
21382150
{
21392151
throw SQL.ROR_FailoverNotSupportedServer(this);
21402152
}
2141-
_currentFailoverPartner = rec._newValue;
2153+
2154+
ServerProvidedFailoverPartner = rec._newValue;
21422155
break;
21432156

21442157
case TdsEnums.ENV_PROMOTETRANSACTION:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3899,7 +3899,7 @@ private void CheckNotificationStateAndAutoEnlist()
38993899
}
39003900

39013901
Notification.Options = SqlDependency.GetDefaultComposedOptions(_activeConnection.DataSource,
3902-
InternalTdsConnection.ServerProvidedFailOverPartner,
3902+
InternalTdsConnection.ServerProvidedFailoverPartner,
39033903
identityUserName, _activeConnection.Database);
39043904
}
39053905

0 commit comments

Comments
 (0)