Skip to content

Commit 11c1f15

Browse files
authored
[5.1] Backport BAG failover fix. Ignore server provided failover partner. (#3704)
* Fix #3400, ignore server-provided failover partner (#3625) * Add IgnoreServerProvidedFailoverPartner app context switch. * Add behavior skip to netfx. * Consolidate to single property for failover partner value. * Rework checks to preserve server provided value, but ignore it. * Fix import. * Skip server failover partner override in �LoginNoFailover method. Add simulated server test coverage. * Fix compilation issues. * Clean up duplicate line. Adjust app context switch logic to match existing. * Review changes. * 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
1 parent d6beb75 commit 11c1f15

File tree

8 files changed

+213
-55
lines changed

8 files changed

+213
-55
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
@@ -3431,7 +3431,7 @@ private void CheckNotificationStateAndAutoEnlist()
34313431
}
34323432

34333433
Notification.Options = SqlDependency.GetDefaultComposedOptions(_activeConnection.DataSource,
3434-
InternalTdsConnection.ServerProvidedFailOverPartner,
3434+
InternalTdsConnection.ServerProvidedFailoverPartner,
34353435
identityUserName, _activeConnection.Database);
34363436
}
34373437

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

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ internal SessionData CurrentSessionData
300300
// FOR CONNECTION RESET MANAGEMENT
301301
private bool _fResetConnection;
302302
private string _originalDatabase;
303-
private string _currentFailoverPartner; // only set by ENV change from server
304303
private string _originalLanguage;
305304
private string _currentLanguage;
306305
private int _currentPacketSize;
@@ -667,13 +666,7 @@ internal TdsParser Parser
667666
}
668667
}
669668

670-
internal string ServerProvidedFailOverPartner
671-
{
672-
get
673-
{
674-
return _currentFailoverPartner;
675-
}
676-
}
669+
internal string ServerProvidedFailoverPartner { get; private set; }
677670

678671
internal SqlConnectionPoolGroupProviderInfo PoolGroupProviderInfo
679672
{
@@ -1533,7 +1526,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
15331526
!connectionOptions.MultiSubnetFailover, // ignore timeout for SniOpen call unless MSF
15341527
connectionOptions.MultiSubnetFailover ? intervalTimer : timeout);
15351528

1536-
if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner)
1529+
if (connectionOptions.MultiSubnetFailover && ServerProvidedFailoverPartner != null)
15371530
{
15381531
// connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used
15391532
throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
@@ -1561,7 +1554,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
15611554
_currentPacketSize = ConnectionOptions.PacketSize;
15621555
_currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
15631556
CurrentDatabase = _originalDatabase = ConnectionOptions.InitialCatalog;
1564-
_currentFailoverPartner = null;
1557+
ServerProvidedFailoverPartner = null;
15651558
_instanceName = string.Empty;
15661559

15671560
routingAttempts++;
@@ -1599,7 +1592,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
15991592
// We only get here when we failed to connect, but are going to re-try
16001593

16011594
// Switch to failover logic if the server provided a partner
1602-
if (null != ServerProvidedFailOverPartner)
1595+
if (ServerProvidedFailoverPartner != null)
16031596
{
16041597
if (connectionOptions.MultiSubnetFailover)
16051598
{
@@ -1615,7 +1608,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
16151608
LoginWithFailover(
16161609
true, // start by using failover partner, since we already failed to connect to the primary
16171610
serverInfo,
1618-
ServerProvidedFailOverPartner,
1611+
ServerProvidedFailoverPartner,
16191612
newPassword,
16201613
newSecurePassword,
16211614
redirectedUserInstance,
@@ -1637,8 +1630,13 @@ private void LoginNoFailover(ServerInfo serverInfo,
16371630
{
16381631
// We must wait for CompleteLogin to finish for to have the
16391632
// env change from the server to know its designated failover
1640-
// partner; save this information in _currentFailoverPartner.
1641-
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, ServerProvidedFailOverPartner);
1633+
// partner; save this information in ServerProvidedFailoverPartner.
1634+
1635+
// When ignoring server provided failover partner, we must pass in the original failover partner from the connection string.
1636+
// Otherwise the pool group's failover partner designation will be updated to point to the server provided value.
1637+
string actualFailoverPartner = LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner ? string.Empty : ServerProvidedFailoverPartner;
1638+
1639+
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, actualFailoverPartner);
16421640
}
16431641
CurrentDataSource = originalServerInfo.UserServerName;
16441642
}
@@ -1699,7 +1697,7 @@ TimeoutTimer timeout
16991697
ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost, connectionOptions.FailoverPartnerSPN);
17001698

17011699
ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions);
1702-
if (null == ServerProvidedFailOverPartner)
1700+
if (ServerProvidedFailoverPartner == null)
17031701
{
17041702
ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions);
17051703
}
@@ -1747,12 +1745,21 @@ TimeoutTimer timeout
17471745
ServerInfo currentServerInfo;
17481746
if (useFailoverHost)
17491747
{
1750-
// Primary server may give us a different failover partner than the connection string indicates. Update it
1751-
if (null != ServerProvidedFailOverPartner && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner)
1748+
// Primary server may give us a different failover partner than the connection string indicates.
1749+
// Update it only if we are respecting server-provided failover partner values.
1750+
if (ServerProvidedFailoverPartner != null && failoverServerInfo.ResolvedServerName != ServerProvidedFailoverPartner)
17521751
{
1753-
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, new failover partner={1}", ObjectID, ServerProvidedFailOverPartner);
1754-
failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailOverPartner);
1752+
if (LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner)
1753+
{
1754+
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, Ignoring server provided failover partner '{1}' due to IgnoreServerProvidedFailoverPartner AppContext switch.", ObjectID, ServerProvidedFailoverPartner);
1755+
}
1756+
else
1757+
{
1758+
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, new failover partner={1}", ObjectID, ServerProvidedFailoverPartner);
1759+
failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailoverPartner);
1760+
}
17551761
}
1762+
17561763
currentServerInfo = failoverServerInfo;
17571764
_timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
17581765
}
@@ -1834,7 +1841,7 @@ TimeoutTimer timeout
18341841
_activeDirectoryAuthTimeoutRetryHelper.State = ActiveDirectoryAuthenticationTimeoutRetryState.HasLoggedIn;
18351842

18361843
// if connected to failover host, but said host doesn't have DbMirroring set up, throw an error
1837-
if (useFailoverHost && null == ServerProvidedFailOverPartner)
1844+
if (useFailoverHost && ServerProvidedFailoverPartner == null)
18381845
{
18391846
throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase);
18401847
}
@@ -1843,8 +1850,13 @@ TimeoutTimer timeout
18431850
{
18441851
// We must wait for CompleteLogin to finish for to have the
18451852
// env change from the server to know its designated failover
1846-
// partner; save this information in _currentFailoverPartner.
1847-
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
1853+
// partner.
1854+
1855+
// When ignoring server provided failover partner, we must pass in the original failover partner from the connection string.
1856+
// Otherwise the pool group's failover partner designation will be updated to point to the server provided value.
1857+
string actualFailoverPartner = LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner ? failoverHost : ServerProvidedFailoverPartner;
1858+
1859+
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, actualFailoverPartner);
18481860
}
18491861
CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
18501862
}
@@ -2068,7 +2080,8 @@ internal void OnEnvChange(SqlEnvChange rec)
20682080
{
20692081
throw SQL.ROR_FailoverNotSupportedServer(this);
20702082
}
2071-
_currentFailoverPartner = rec._newValue;
2083+
2084+
ServerProvidedFailoverPartner = rec._newValue;
20722085
break;
20732086

20742087
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
@@ -3814,7 +3814,7 @@ private void CheckNotificationStateAndAutoEnlist()
38143814
}
38153815

38163816
Notification.Options = SqlDependency.GetDefaultComposedOptions(_activeConnection.DataSource,
3817-
InternalTdsConnection.ServerProvidedFailOverPartner,
3817+
InternalTdsConnection.ServerProvidedFailoverPartner,
38183818
identityUserName, _activeConnection.Database);
38193819
}
38203820

0 commit comments

Comments
 (0)