Skip to content

Commit 9b91aaf

Browse files
committed
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.
1 parent 607b8c9 commit 9b91aaf

File tree

8 files changed

+856
-67
lines changed

8 files changed

+856
-67
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
@@ -3623,7 +3623,7 @@ private void CheckNotificationStateAndAutoEnlist()
36233623
}
36243624

36253625
Notification.Options = SqlDependency.GetDefaultComposedOptions(_activeConnection.DataSource,
3626-
InternalTdsConnection.ServerProvidedFailOverPartner,
3626+
InternalTdsConnection.ServerProvidedFailoverPartner,
36273627
identityUserName, _activeConnection.Database);
36283628
}
36293629

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
@@ -310,7 +310,6 @@ internal SessionData CurrentSessionData
310310
// FOR CONNECTION RESET MANAGEMENT
311311
private bool _fResetConnection;
312312
private string _originalDatabase;
313-
private string _currentFailoverPartner; // only set by ENV change from server
314313
private string _originalLanguage;
315314
private string _currentLanguage;
316315
private int _currentPacketSize;
@@ -716,13 +715,7 @@ internal TdsParser Parser
716715
}
717716
}
718717

719-
internal string ServerProvidedFailOverPartner
720-
{
721-
get
722-
{
723-
return _currentFailoverPartner;
724-
}
725-
}
718+
internal string ServerProvidedFailoverPartner { get; set; }
726719

727720
internal SqlConnectionPoolGroupProviderInfo PoolGroupProviderInfo
728721
{
@@ -1515,7 +1508,7 @@ private void OpenLoginEnlist(TimeoutTimer timeout,
15151508
throw SQL.ROR_FailoverNotSupportedConnString();
15161509
}
15171510

1518-
if (ServerProvidedFailOverPartner != null)
1511+
if (ServerProvidedFailoverPartner != null)
15191512
{
15201513
throw SQL.ROR_FailoverNotSupportedServer(this);
15211514
}
@@ -1643,7 +1636,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
16431636
newSecurePassword,
16441637
attemptOneLoginTimeout);
16451638

1646-
if (connectionOptions.MultiSubnetFailover && ServerProvidedFailOverPartner != null)
1639+
if (connectionOptions.MultiSubnetFailover && ServerProvidedFailoverPartner != null)
16471640
{
16481641
// connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used
16491642
throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
@@ -1671,7 +1664,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
16711664
_currentPacketSize = ConnectionOptions.PacketSize;
16721665
_currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
16731666
CurrentDatabase = _originalDatabase = ConnectionOptions.InitialCatalog;
1674-
_currentFailoverPartner = null;
1667+
ServerProvidedFailoverPartner = null;
16751668
_instanceName = string.Empty;
16761669

16771670
routingAttempts++;
@@ -1710,7 +1703,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
17101703
// We only get here when we failed to connect, but are going to re-try
17111704

17121705
// Switch to failover logic if the server provided a partner
1713-
if (ServerProvidedFailOverPartner != null)
1706+
if (ServerProvidedFailoverPartner != null)
17141707
{
17151708
if (connectionOptions.MultiSubnetFailover)
17161709
{
@@ -1726,7 +1719,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
17261719
LoginWithFailover(
17271720
true, // start by using failover partner, since we already failed to connect to the primary
17281721
serverInfo,
1729-
ServerProvidedFailOverPartner,
1722+
ServerProvidedFailoverPartner,
17301723
newPassword,
17311724
newSecurePassword,
17321725
redirectedUserInstance,
@@ -1748,8 +1741,13 @@ private void LoginNoFailover(ServerInfo serverInfo,
17481741
{
17491742
// We must wait for CompleteLogin to finish for to have the
17501743
// env change from the server to know its designated failover
1751-
// partner; save this information in _currentFailoverPartner.
1752-
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, ServerProvidedFailOverPartner);
1744+
// partner; save this information in ServerProvidedFailoverPartner.
1745+
1746+
// When ignoring server provided failover partner, we must pass in the original failover partner from the connection string.
1747+
// Otherwise the pool group's failover partner designation will be updated to point to the server provided value.
1748+
string actualFailoverPartner = LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner ? "" : ServerProvidedFailoverPartner;
1749+
1750+
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, actualFailoverPartner);
17531751
}
17541752
CurrentDataSource = originalServerInfo.UserServerName;
17551753
}
@@ -1810,7 +1808,7 @@ TimeoutTimer timeout
18101808
ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost, connectionOptions.FailoverPartnerSPN);
18111809

18121810
ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions);
1813-
if (ServerProvidedFailOverPartner == null)
1811+
if (ServerProvidedFailoverPartner == null)
18141812
{
18151813
ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions);
18161814
}
@@ -1869,12 +1867,21 @@ TimeoutTimer timeout
18691867
failoverDemandDone = true;
18701868
}
18711869

1872-
// Primary server may give us a different failover partner than the connection string indicates. Update it
1873-
if (ServerProvidedFailOverPartner != null && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner)
1870+
// Primary server may give us a different failover partner than the connection string indicates.
1871+
// Update it only if we are respecting server-provided failover partner values.
1872+
if (ServerProvidedFailoverPartner != null && failoverServerInfo.ResolvedServerName != ServerProvidedFailoverPartner)
18741873
{
1875-
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, new failover partner={1}", ObjectID, ServerProvidedFailOverPartner);
1876-
failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailOverPartner);
1874+
if (LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner)
1875+
{
1876+
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, Ignoring server provided failover partner '{1}' due to IgnoreServerProvidedFailoverPartner AppContext switch.", ObjectID, ServerProvidedFailoverPartner);
1877+
}
1878+
else
1879+
{
1880+
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, new failover partner={1}", ObjectID, ServerProvidedFailoverPartner);
1881+
failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailoverPartner);
1882+
}
18771883
}
1884+
18781885
currentServerInfo = failoverServerInfo;
18791886
_timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
18801887
}
@@ -1924,7 +1931,7 @@ TimeoutTimer timeout
19241931
_currentPacketSize = connectionOptions.PacketSize;
19251932
_currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
19261933
CurrentDatabase = _originalDatabase = connectionOptions.InitialCatalog;
1927-
_currentFailoverPartner = null;
1934+
ServerProvidedFailoverPartner = null;
19281935
_instanceName = string.Empty;
19291936

19301937
AttemptOneLogin(
@@ -1986,7 +1993,7 @@ TimeoutTimer timeout
19861993
_activeDirectoryAuthTimeoutRetryHelper.State = ActiveDirectoryAuthenticationTimeoutRetryState.HasLoggedIn;
19871994

19881995
// if connected to failover host, but said host doesn't have DbMirroring set up, throw an error
1989-
if (useFailoverHost && ServerProvidedFailOverPartner == null)
1996+
if (useFailoverHost && ServerProvidedFailoverPartner == null)
19901997
{
19911998
throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase);
19921999
}
@@ -1995,8 +2002,13 @@ TimeoutTimer timeout
19952002
{
19962003
// We must wait for CompleteLogin to finish for to have the
19972004
// env change from the server to know its designated failover
1998-
// partner; save this information in _currentFailoverPartner.
1999-
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
2005+
// partner.
2006+
2007+
// When ignoring server provided failover partner, we must pass in the original failover partner from the connection string.
2008+
// Otherwise the pool group's failover partner designation will be updated to point to the server provided value.
2009+
string actualFailoverPartner = LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner ? failoverHost : ServerProvidedFailoverPartner;
2010+
2011+
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, actualFailoverPartner);
20002012
}
20012013
CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
20022014
}
@@ -2246,7 +2258,8 @@ internal void OnEnvChange(SqlEnvChange rec)
22462258
{
22472259
throw SQL.ROR_FailoverNotSupportedServer(this);
22482260
}
2249-
_currentFailoverPartner = rec._newValue;
2261+
2262+
ServerProvidedFailoverPartner = rec._newValue;
22502263
break;
22512264

22522265
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
@@ -3763,7 +3763,7 @@ private void CheckNotificationStateAndAutoEnlist()
37633763
}
37643764

37653765
Notification.Options = SqlDependency.GetDefaultComposedOptions(_activeConnection.DataSource,
3766-
InternalTdsConnection.ServerProvidedFailOverPartner,
3766+
InternalTdsConnection.ServerProvidedFailoverPartner,
37673767
identityUserName, _activeConnection.Database);
37683768
}
37693769

0 commit comments

Comments
 (0)