Skip to content
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

Add | Use Minimum Login Timeout as 1 sec in .NET Core and enable behavior by default #2012

Merged
merged 2 commits into from May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -1263,7 +1263,14 @@ private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword,
if (!timeout.IsInfinite)
{
long t = timeout.MillisecondsRemaining / 1000;
if ((long)int.MaxValue > t)
if (t == 0 && LocalAppContextSwitches.UseMinimumLoginTimeout)
{
// Take 1 as the minimum value, since 0 is treated as an infinite timeout
// to allow 1 second more for login to complete, since it should take only a few milliseconds.
t = 1;
}

if (int.MaxValue > t)
{
timeoutInSeconds = (int)t;
}
Expand All @@ -1279,7 +1286,8 @@ private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword,

login.language = _currentLanguage;
if (!login.userInstance)
{ // Do not send attachdbfilename or database to SSE primary instance
{
// Do not send attachdbfilename or database to SSE primary instance
login.database = CurrentDatabase;
login.attachDBFilename = ConnectionOptions.AttachDBFilename;
}
Expand Down
Expand Up @@ -621,7 +621,6 @@
<Compile Include="Microsoft\Data\RelationshipConverter.cs" />
<Compile Include="Microsoft\Data\SqlClient\AlwaysEncryptedKeyConverter.Cng.cs" />
<Compile Include="Microsoft\Data\SqlClient\assemblycache.cs" />
<Compile Include="Microsoft\Data\SqlClient\LocalAppContextSwitches.netfx.cs" />
<Compile Include="Microsoft\Data\SqlClient\LocalDBAPI.cs" />
<Compile Include="Microsoft\Data\SqlClient\LocalDBConfig.cs" />
<Compile Include="Microsoft\Data\SqlClient\Reliability\SqlConfigurableRetryLogicManager.LoadType.cs" />
Expand Down Expand Up @@ -735,4 +734,4 @@
<Import Project="$(NetFxSource)tools\targets\GenerateThisAssemblyCs.targets" />
<Import Project="$(NetFxSource)tools\targets\GenerateAssemblyRef.targets" />
<Import Project="$(NetFxSource)tools\targets\GenerateAssemblyInfo.targets" />
</Project>
</Project>

This file was deleted.

Expand Up @@ -1530,10 +1530,11 @@ private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword,
if (t == 0 && LocalAppContextSwitches.UseMinimumLoginTimeout)
{
// Take 1 as the minimum value, since 0 is treated as an infinite timeout
// to allow 1 second more for login to complete, since it should take only a few milliseconds.
t = 1;
}

if ((long)Int32.MaxValue > t)
if (int.MaxValue > t)
{
timeoutInSeconds = (int)t;
}
Expand Down
Expand Up @@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Microsoft.Data.SqlClient
{
Expand All @@ -13,10 +11,12 @@ internal static partial class LocalAppContextSwitches
internal const string MakeReadAsyncBlockingString = @"Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking";
internal const string LegacyRowVersionNullString = @"Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior";
internal const string SuppressInsecureTLSWarningString = @"Switch.Microsoft.Data.SqlClient.SuppressInsecureTLSWarning";
internal const string UseMinimumLoginTimeoutString = @"Switch.Microsoft.Data.SqlClient.UseOneSecFloorInTimeoutCalculationDuringLogin";

private static bool? s_legacyRowVersionNullBehavior;
private static bool? s_suppressInsecureTLSWarning;
private static bool s_makeReadAsyncBlocking;
private static bool? s_LegacyRowVersionNullBehavior;
private static bool? s_SuppressInsecureTLSWarning;
private static bool s_useMinimumLoginTimeout;

#if !NETFRAMEWORK
static LocalAppContextSwitches()
Expand All @@ -34,46 +34,81 @@ static LocalAppContextSwitches()
}
#endif

#if NETFRAMEWORK
internal const string DisableTNIRByDefaultString = @"Switch.Microsoft.Data.SqlClient.DisableTNIRByDefaultInConnectionString";
private static bool s_disableTNIRByDefault;

/// <summary>
/// Transparent Network IP Resolution (TNIR) is a revision of the existing MultiSubnetFailover feature.
/// TNIR affects the connection sequence of the driver in the case where the first resolved IP of the hostname
/// doesn't respond and there are multiple IPs associated with the hostname.
///
/// TNIR interacts with MultiSubnetFailover to provide the following three connection sequences:
/// 0: One IP is attempted, followed by all IPs in parallel
/// 1: All IPs are attempted in parallel
/// 2: All IPs are attempted one after another
///
/// TransparentNetworkIPResolution is enabled by default. MultiSubnetFailover is disabled by default.
/// To disable TNIR, you can enable the app context switch.
///
/// This app context switch defaults to 'false'.
/// </summary>
public static bool DisableTNIRByDefault
=> AppContext.TryGetSwitch(DisableTNIRByDefaultString, out s_disableTNIRByDefault) && s_disableTNIRByDefault;
#endif

/// <summary>
/// When using Encrypt=false in the connection string, a security warning is output to the console if the TLS version is 1.2 or lower.
/// This warning can be suppressed by enabling this AppContext switch.
/// This app context switch defaults to 'false'.
/// </summary>
public static bool SuppressInsecureTLSWarning
{
get
{
if (s_SuppressInsecureTLSWarning is null)
if (s_suppressInsecureTLSWarning is null)
{
bool result;
result = AppContext.TryGetSwitch(SuppressInsecureTLSWarningString, out result) ? result : false;
s_SuppressInsecureTLSWarning = result;
result = AppContext.TryGetSwitch(SuppressInsecureTLSWarningString, out result) && result;
s_suppressInsecureTLSWarning = result;
}
return s_SuppressInsecureTLSWarning.Value;
}
}

public static bool MakeReadAsyncBlocking
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return AppContext.TryGetSwitch(MakeReadAsyncBlockingString, out s_makeReadAsyncBlocking) ? s_makeReadAsyncBlocking : false;
return s_suppressInsecureTLSWarning.Value;
}
}

/// <summary>
/// In System.Data.SqlClient and Microsoft.Data.SqlClient prior to 3.0.0 a field with type Timestamp/RowVersion
/// would return an empty byte array. This switch contols whether to preserve that behaviour on newer versions
/// of Microsoft.Data.SqlClient, if this switch returns false an appropriate null value will be returned
/// of Microsoft.Data.SqlClient, if this switch returns false an appropriate null value will be returned.
/// This app context switch defaults to 'false'.
/// </summary>
public static bool LegacyRowVersionNullBehavior
{
get
{
if (s_LegacyRowVersionNullBehavior is null)
if (s_legacyRowVersionNullBehavior is null)
{
bool result;
result = AppContext.TryGetSwitch(LegacyRowVersionNullString, out result) ? result : false;
s_LegacyRowVersionNullBehavior = result;
result = AppContext.TryGetSwitch(LegacyRowVersionNullString, out result) && result;
s_legacyRowVersionNullBehavior = result;
}
return s_LegacyRowVersionNullBehavior.Value;
return s_legacyRowVersionNullBehavior.Value;
}
}

/// <summary>
/// When enabled, ReadAsync runs asynchronously and does not block the calling thread.
/// This app context switch defaults to 'false'.
/// </summary>
public static bool MakeReadAsyncBlocking
=> AppContext.TryGetSwitch(MakeReadAsyncBlockingString, out s_makeReadAsyncBlocking) && s_makeReadAsyncBlocking;

/// <summary>
/// Specifies minimum login timeout to be set to 1 second instead of 0 seconds,
/// to prevent a login attempt from waiting indefinitely.
/// This app context switch defaults to 'true'.
/// </summary>
public static bool UseMinimumLoginTimeout
=> !AppContext.TryGetSwitch(UseMinimumLoginTimeoutString, out s_useMinimumLoginTimeout) || s_useMinimumLoginTimeout;
}
}
Expand Up @@ -332,7 +332,7 @@ public static void CheckLegacyNullRowVersionIsEmptyArray()
private static bool? SetLegacyRowVersionNullBehavior(bool? value)
{
Type switchesType = typeof(SqlCommand).Assembly.GetType("Microsoft.Data.SqlClient.LocalAppContextSwitches");
FieldInfo switchField = switchesType.GetField("s_LegacyRowVersionNullBehavior", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
FieldInfo switchField = switchesType.GetField("s_legacyRowVersionNullBehavior", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
bool? originalValue = (bool?)switchField.GetValue(null);
switchField.SetValue(null, value);
return originalValue;
Expand Down