Skip to content

Commit fa7132e

Browse files
authored
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 ff511ed commit fa7132e

File tree

8 files changed

+247
-83
lines changed

8 files changed

+247
-83
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2236,7 +2236,7 @@ private void CheckNotificationStateAndAutoEnlist()
22362236
}
22372237

22382238
Notification.Options = SqlDependency.GetDefaultComposedOptions(_activeConnection.DataSource,
2239-
InternalTdsConnection.ServerProvidedFailOverPartner,
2239+
InternalTdsConnection.ServerProvidedFailoverPartner,
22402240
identityUserName, _activeConnection.Database);
22412241
}
22422242

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
@@ -314,7 +314,6 @@ internal SessionData CurrentSessionData
314314
// FOR CONNECTION RESET MANAGEMENT
315315
private bool _fResetConnection;
316316
private string _originalDatabase;
317-
private string _currentFailoverPartner; // only set by ENV change from server
318317
private string _originalLanguage;
319318
private string _currentLanguage;
320319
private int _currentPacketSize;
@@ -704,13 +703,7 @@ internal TdsParser Parser
704703
}
705704
}
706705

707-
internal string ServerProvidedFailOverPartner
708-
{
709-
get
710-
{
711-
return _currentFailoverPartner;
712-
}
713-
}
706+
internal string ServerProvidedFailoverPartner { get; set; }
714707

715708
internal SqlConnectionPoolGroupProviderInfo PoolGroupProviderInfo
716709
{
@@ -1507,7 +1500,7 @@ private void OpenLoginEnlist(TimeoutTimer timeout,
15071500
throw SQL.ROR_FailoverNotSupportedConnString();
15081501
}
15091502

1510-
if (ServerProvidedFailOverPartner != null)
1503+
if (ServerProvidedFailoverPartner != null)
15111504
{
15121505
throw SQL.ROR_FailoverNotSupportedServer(this);
15131506
}
@@ -1635,7 +1628,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
16351628
newSecurePassword,
16361629
attemptOneLoginTimeout);
16371630

1638-
if (connectionOptions.MultiSubnetFailover && ServerProvidedFailOverPartner != null)
1631+
if (connectionOptions.MultiSubnetFailover && ServerProvidedFailoverPartner != null)
16391632
{
16401633
// connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used
16411634
throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
@@ -1663,7 +1656,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
16631656
_currentPacketSize = ConnectionOptions.PacketSize;
16641657
_currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
16651658
CurrentDatabase = _originalDatabase = ConnectionOptions.InitialCatalog;
1666-
_currentFailoverPartner = null;
1659+
ServerProvidedFailoverPartner = null;
16671660
_instanceName = string.Empty;
16681661

16691662
routingAttempts++;
@@ -1702,7 +1695,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
17021695
// We only get here when we failed to connect, but are going to re-try
17031696

17041697
// Switch to failover logic if the server provided a partner
1705-
if (ServerProvidedFailOverPartner != null)
1698+
if (ServerProvidedFailoverPartner != null)
17061699
{
17071700
if (connectionOptions.MultiSubnetFailover)
17081701
{
@@ -1718,7 +1711,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
17181711
LoginWithFailover(
17191712
true, // start by using failover partner, since we already failed to connect to the primary
17201713
serverInfo,
1721-
ServerProvidedFailOverPartner,
1714+
ServerProvidedFailoverPartner,
17221715
newPassword,
17231716
newSecurePassword,
17241717
redirectedUserInstance,
@@ -1740,8 +1733,13 @@ private void LoginNoFailover(ServerInfo serverInfo,
17401733
{
17411734
// We must wait for CompleteLogin to finish for to have the
17421735
// env change from the server to know its designated failover
1743-
// partner; save this information in _currentFailoverPartner.
1744-
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, ServerProvidedFailOverPartner);
1736+
// partner; save this information in ServerProvidedFailoverPartner.
1737+
1738+
// When ignoring server provided failover partner, we must pass in the original failover partner from the connection string.
1739+
// Otherwise the pool group's failover partner designation will be updated to point to the server provided value.
1740+
string actualFailoverPartner = LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner ? "" : ServerProvidedFailoverPartner;
1741+
1742+
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, actualFailoverPartner);
17451743
}
17461744
CurrentDataSource = originalServerInfo.UserServerName;
17471745
}
@@ -1802,7 +1800,7 @@ TimeoutTimer timeout
18021800
ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost, connectionOptions.FailoverPartnerSPN);
18031801

18041802
ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions);
1805-
if (ServerProvidedFailOverPartner == null)
1803+
if (ServerProvidedFailoverPartner == null)
18061804
{
18071805
ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions);
18081806
}
@@ -1861,12 +1859,21 @@ TimeoutTimer timeout
18611859
failoverDemandDone = true;
18621860
}
18631861

1864-
// Primary server may give us a different failover partner than the connection string indicates. Update it
1865-
if (ServerProvidedFailOverPartner != null && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner)
1862+
// Primary server may give us a different failover partner than the connection string indicates.
1863+
// Update it only if we are respecting server-provided failover partner values.
1864+
if (ServerProvidedFailoverPartner != null && failoverServerInfo.ResolvedServerName != ServerProvidedFailoverPartner)
18661865
{
1867-
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, new failover partner={1}", ObjectID, ServerProvidedFailOverPartner);
1868-
failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailOverPartner);
1866+
if (LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner)
1867+
{
1868+
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, Ignoring server provided failover partner '{1}' due to IgnoreServerProvidedFailoverPartner AppContext switch.", ObjectID, ServerProvidedFailoverPartner);
1869+
}
1870+
else
1871+
{
1872+
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> {0}, new failover partner={1}", ObjectID, ServerProvidedFailoverPartner);
1873+
failoverServerInfo.SetDerivedNames(string.Empty, ServerProvidedFailoverPartner);
1874+
}
18691875
}
1876+
18701877
currentServerInfo = failoverServerInfo;
18711878
_timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
18721879
}
@@ -1916,7 +1923,7 @@ TimeoutTimer timeout
19161923
_currentPacketSize = connectionOptions.PacketSize;
19171924
_currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
19181925
CurrentDatabase = _originalDatabase = connectionOptions.InitialCatalog;
1919-
_currentFailoverPartner = null;
1926+
ServerProvidedFailoverPartner = null;
19201927
_instanceName = string.Empty;
19211928

19221929
AttemptOneLogin(
@@ -1978,7 +1985,7 @@ TimeoutTimer timeout
19781985
_activeDirectoryAuthTimeoutRetryHelper.State = ActiveDirectoryAuthenticationTimeoutRetryState.HasLoggedIn;
19791986

19801987
// if connected to failover host, but said host doesn't have DbMirroring set up, throw an error
1981-
if (useFailoverHost && ServerProvidedFailOverPartner == null)
1988+
if (useFailoverHost && ServerProvidedFailoverPartner == null)
19821989
{
19831990
throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase);
19841991
}
@@ -1987,8 +1994,13 @@ TimeoutTimer timeout
19871994
{
19881995
// We must wait for CompleteLogin to finish for to have the
19891996
// env change from the server to know its designated failover
1990-
// partner; save this information in _currentFailoverPartner.
1991-
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
1997+
// partner.
1998+
1999+
// When ignoring server provided failover partner, we must pass in the original failover partner from the connection string.
2000+
// Otherwise the pool group's failover partner designation will be updated to point to the server provided value.
2001+
string actualFailoverPartner = LocalAppContextSwitches.IgnoreServerProvidedFailoverPartner ? failoverHost : ServerProvidedFailoverPartner;
2002+
2003+
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, actualFailoverPartner);
19922004
}
19932005
CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
19942006
}
@@ -2218,7 +2230,8 @@ internal void OnEnvChange(SqlEnvChange rec)
22182230
{
22192231
throw SQL.ROR_FailoverNotSupportedServer(this);
22202232
}
2221-
_currentFailoverPartner = rec._newValue;
2233+
2234+
ServerProvidedFailoverPartner = rec._newValue;
22222235
break;
22232236

22242237
case TdsEnums.ENV_PROMOTETRANSACTION:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2205,7 +2205,7 @@ private void CheckNotificationStateAndAutoEnlist()
22052205
}
22062206

22072207
Notification.Options = SqlDependency.GetDefaultComposedOptions(_activeConnection.DataSource,
2208-
InternalTdsConnection.ServerProvidedFailOverPartner,
2208+
InternalTdsConnection.ServerProvidedFailoverPartner,
22092209
identityUserName, _activeConnection.Database);
22102210
}
22112211

0 commit comments

Comments
 (0)