Skip to content

Move to Shared for SqlConnectionPoolGroupProviderInfo.cs #1323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlCommandSet.cs">
<Link>Microsoft\Data\SqlClient\SqlCommandSet.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs">
<Link>Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlConnectionPoolProviderInfo.cs">
<Link>Microsoft\Data\SqlClient\SqlConnectionPoolProviderInfo.cs</Link>
</Compile>
Expand Down Expand Up @@ -504,7 +507,6 @@
<Compile Include="Microsoft\Data\SqlClient\SqlConnection.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionFactory.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionHelper.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionPoolKey.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionString.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionStringBuilder.cs" />
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -1635,7 +1635,7 @@ private void LoginNoFailover(ServerInfo serverInfo,
// We must wait for CompleteLogin to finish for to have the
// env change from the server to know its designated failover
// partner; save this information in _currentFailoverPartner.
PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, ServerProvidedFailOverPartner);
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, ServerProvidedFailOverPartner);
}
CurrentDataSource = originalServerInfo.UserServerName;
}
Expand Down Expand Up @@ -1841,7 +1841,7 @@ TimeoutTimer timeout
// We must wait for CompleteLogin to finish for to have the
// env change from the server to know its designated failover
// partner; save this information in _currentFailoverPartner.
PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
}
CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlCommandSet.cs">
<Link>Microsoft\Data\SqlClient\SqlCommandSet.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs">
<Link>Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlConnectionPoolProviderInfo.cs">
<Link>Microsoft\Data\SqlClient\SqlConnectionPoolProviderInfo.cs</Link>
</Compile>
Expand Down Expand Up @@ -471,7 +474,6 @@
<Compile Include="Microsoft\Data\SqlClient\SqlConnection.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionFactory.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionHelper.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionPoolKey.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionString.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionStringBuilder.cs" />
Expand Down Expand Up @@ -640,4 +642,4 @@
<Import Project="$(NetFxSource)tools\targets\GenerateThisAssemblyCs.targets" />
<Import Project="$(NetFxSource)tools\targets\GenerateAssemblyRef.targets" />
<Import Project="$(NetFxSource)tools\targets\GenerateAssemblyInfo.targets" />
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -1966,7 +1966,7 @@ private void LoginNoFailover(ServerInfo serverInfo, string newPassword, SecureSt
// We must wait for CompleteLogin to finish for to have the
// env change from the server to know its designated failover
// partner; save this information in _currentFailoverPartner.
PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, ServerProvidedFailOverPartner);
PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, ServerProvidedFailOverPartner);
}
CurrentDataSource = originalServerInfo.UserServerName;
}
Expand Down Expand Up @@ -2235,7 +2235,7 @@ TimeoutTimer timeout
// We must wait for CompleteLogin to finish for to have the
// env change from the server to know its designated failover
// partner; save this information in _currentFailoverPartner.
PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
}
CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,36 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Data.Common;
using System.Security;
using Microsoft.Data.ProviderBase;

namespace Microsoft.Data.SqlClient
{
sealed internal class SqlConnectionPoolGroupProviderInfo : DbConnectionPoolGroupProviderInfo
internal sealed class SqlConnectionPoolGroupProviderInfo : DbConnectionPoolGroupProviderInfo
{
private string _alias;
private System.Security.PermissionSet _failoverPermissionSet;
private string _failoverPartner;
private bool _useFailoverPartner;
#if NETFRAMEWORK
private PermissionSet _failoverPermissionSet;
#endif

internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions)
{
// This is for the case where the user specified the failover partner
// in the connection string and we have not yet connected to get the
// in the connection string and we have not yet connected to get the
// env change.
_failoverPartner = connectionOptions.FailoverPartner;

if (ADP.IsEmpty(_failoverPartner))
if (string.IsNullOrEmpty(_failoverPartner))
{
_failoverPartner = null;
}
}

internal string FailoverPartner
{
get
{
return _failoverPartner;
}
}
internal string FailoverPartner => _failoverPartner;

internal bool UseFailoverPartner
{
get
{
return _useFailoverPartner;
}
}
internal bool UseFailoverPartner => _useFailoverPartner;

internal void AliasCheck(string server)
{
Expand All @@ -55,15 +45,48 @@ internal void AliasCheck(string server)
}
else if (_alias != server)
{
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlConnectionPoolGroupProviderInfo|INFO> alias change detected. Clearing PoolGroup");
SqlClientEventSource.Log.TryTraceEvent("SqlConnectionPoolGroupProviderInfo.AliasCheck | Info | Alias change detected. Clearing PoolGroup.");
base.PoolGroup.Clear();
_alias = server;
}
}
}
}

private System.Security.PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner)
internal void FailoverCheck(bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner)
{
if (UseFailoverPartner != actualUseFailoverPartner)
{
SqlClientEventSource.Log.TryTraceEvent("SqlConnectionPoolGroupProviderInfo.FailoverCheck | Info | Failover detected. Failover partner '{0}'. Clearing PoolGroup", actualFailoverPartner);
base.PoolGroup.Clear();
_useFailoverPartner = actualUseFailoverPartner;
}
// Only construct a new permission set when we're connecting to the
// primary data source, not the failover partner.
if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner)
{
// NOTE: we optimistically generate the permission set to keep
// lock short, but we only do this when we get a new
// failover partner.

#if NETFRAMEWORK
PermissionSet failoverPermissionSet = CreateFailoverPermission(userConnectionOptions, actualFailoverPartner);
#endif
lock (this)
{
if (_failoverPartner != actualFailoverPartner)
{
_failoverPartner = actualFailoverPartner;
#if NETFRAMEWORK
_failoverPermissionSet = failoverPermissionSet;
#endif
}
}
}
}

#if NETFRAMEWORK
private PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner)
{
string keywordToReplace;

Expand Down Expand Up @@ -94,51 +117,20 @@ private System.Security.PermissionSet CreateFailoverPermission(SqlConnectionStri
return (new SqlConnectionString(failoverConnectionString)).CreatePermissionSet();
}

internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner)
{
if (UseFailoverPartner != actualUseFailoverPartner)
{
// TODO: will connections in progress somehow be active for two different datasources?
SqlClientEventSource.Log.TryTraceEvent("<sc.SqlConnectionPoolGroupProviderInfo|INFO> Failover detected. failover partner='{0}'. Clearing PoolGroup", actualFailoverPartner);

base.PoolGroup.Clear();
_useFailoverPartner = actualUseFailoverPartner;
}
// Only construct a new permission set when we're connecting to the
// primary data source, not the failover partner.
if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner)
{
// NOTE: we optimisitically generate the permission set to keep
// lock short, but we only do this when we get a new
// failover partner.
// TODO: it seems to me that being optimistic here may not be such a good idea; what if there are 100s of concurrent failovers?

System.Security.PermissionSet failoverPermissionSet = CreateFailoverPermission(userConnectionOptions, actualFailoverPartner);

lock (this)
{
if (_failoverPartner != actualFailoverPartner)
{
_failoverPartner = actualFailoverPartner;
_failoverPermissionSet = failoverPermissionSet;
}
}
}
}

internal void FailoverPermissionDemand()
{
if (_useFailoverPartner)
{
// Note that we only demand when there is a permission set, which only
// happens once we've identified a failover situation in FailoverCheck
System.Security.PermissionSet failoverPermissionSet = _failoverPermissionSet;
PermissionSet failoverPermissionSet = _failoverPermissionSet;
if (null != failoverPermissionSet)
{
// demand on pooled failover connections
failoverPermissionSet.Demand();
}
}
}
#endif
}
}