Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Added PoolBlockingPeriod connection property #29697

Merged
merged 22 commits into from
Jun 27, 2018
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6d9fe19
add Pool Blocking Period connection property
AfsanehR-zz May 14, 2018
b944ac6
update the assembly version
AfsanehR-zz May 14, 2018
d906f44
updated per review comments received and update assembly version
AfsanehR-zz May 14, 2018
9060418
Fixed an indentation
AfsanehR-zz May 14, 2018
a68899e
Fixed another indentation
AfsanehR-zz May 14, 2018
5777789
Fix for compilation issue
AfsanehR-zz May 14, 2018
47ac554
some review comments changes to make code cleaner
AfsanehR-zz May 15, 2018
c16c892
use other Assert methods in test and clear connection pool before eac…
AfsanehR-zz May 22, 2018
77fd936
Merge branch 'master' into PoolBlockingPeriod
AfsanehR-zz May 22, 2018
7e76fd8
Merge branch 'master' of https://github.com/dotnet/corefx into PoolBl…
AfsanehR-zz May 23, 2018
9590a9f
Merge branch 'master' of https://github.com/dotnet/corefx into PoolBl…
AfsanehR-zz May 23, 2018
83f124e
Merge branch 'master' of https://github.com/dotnet/corefx into PoolBl…
AfsanehR-zz May 23, 2018
563cb99
update version to 4.5.0.0
AfsanehR-zz May 23, 2018
3d592cd
Merge branch 'PoolBlockingPeriod' of https://github.com/v-afrafi/core…
AfsanehR-zz May 23, 2018
ec47490
make PoolBlockingPeriod to netcoreapp specific
AfsanehR-zz Jun 13, 2018
24bb30b
make PoolBlockingPeriod to netcoreapp specific
AfsanehR-zz Jun 13, 2018
edae126
Fixed System.Data.SqlClient.csproj file
AfsanehR-zz Jun 20, 2018
92c30d9
Fixed the double test file
AfsanehR-zz Jun 20, 2018
3551f7b
removed redundant test
AfsanehR-zz Jun 21, 2018
286eb8f
modified the test and addressed review comments
AfsanehR-zz Jun 26, 2018
365505a
updated test
AfsanehR-zz Jun 26, 2018
880e4f0
added a margin to test
AfsanehR-zz Jun 27, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions pkg/Microsoft.Private.PackageBaseline/packageIndex.json
Original file line number Diff line number Diff line change
Expand Up @@ -2444,7 +2444,6 @@
"System.Memory": {
"InboxOn": {
"netcoreapp2.1": "4.1.0.0",
"netcoreapp2.2": "4.1.0.0",
"monoandroid10": "Any",
"monotouch10": "Any",
"uap10.0.16300": "4.1.0.0",
Expand Down Expand Up @@ -4980,7 +4979,6 @@
"InboxOn": {
"netcoreapp2.0": "4.1.1.0",
"netcoreapp2.1": "4.3.0.0",
"netcoreapp2.2": "4.3.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this deleted ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why this got deleted. These changes appeared as I ran "msbuild /t:UpdatePackageIndex" command. Looking forward to @weshaggard for more guidance on this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect to see the SqlClient version bumped in this file. I'm not entirely sure why these 2 entries were removed but I suspect it was because they were redundant. @ericstj @joperezr?

Copy link
Member

@ericstj ericstj May 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, they are redundant. The actual data model should not write them but someone manually editing would. Is that what you did here @weshaggard? 2414032#diff-122916076db7087dbc454352fada61eeR2447

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that what you did here @weshaggard?

I did a couple iterations at one point I generated them with the package index update task but I may have manually changed them later for these too. At any rate @afsanehr these changes are safe but I still don't see the SqlClient version updated like I would expect. I would expect to see https://github.com/AfsanehR/corefx/blob/577778967bf657d325bd999d93dc62458e2dc0a8/pkg/Microsoft.Private.PackageBaseline/packageIndex.json#L1254 updated to the new version. Once you build the library with the new version can you again try to run the UpdatePackageIndex target on the pkgproj for it SqlClient?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weshaggard Running build -allConfigurations, I am getting this error:
D:\j\workspace\windows-TGrou---2a8f9c29\Tools\partialfacades.task.targets(64,5): error : Errors were encountered when generating facade(s). [D:\j\workspace\windows-TGrou---2a8f9c29\src\System.Data.SqlClient\src\System.Data.SqlClient.csproj] Do you have any suggestion how to fix this?

"uap10.0.16300": "4.3.0.0"
},
"AssemblyVersionInPackageVersion": {
Expand Down
2 changes: 1 addition & 1 deletion src/System.Data.SqlClient/dir.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.4.1.0</AssemblyVersion>
<AssemblyVersion>4.5.0.0</AssemblyVersion>
<AssemblyKey>MSFT</AssemblyKey>
<IsUAP>true</IsUAP>
</PropertyGroup>
Expand Down
7 changes: 7 additions & 0 deletions src/System.Data.SqlClient/ref/System.Data.SqlClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,12 @@ public enum SortOrder
Descending = 1,
Unspecified = -1,
}
public enum PoolBlockingPeriod
{
Auto = 0,
AlwaysBlock = 1,
NeverBlock = 2,
}
public sealed partial class SqlBulkCopy : System.IDisposable
{
public SqlBulkCopy(System.Data.SqlClient.SqlConnection connection) { }
Expand Down Expand Up @@ -538,6 +544,7 @@ public override void Clear() { }
public override bool Remove(string keyword) { throw null; }
public override bool ShouldSerialize(string keyword) { throw null; }
public override bool TryGetValue(string keyword, out object value) { throw null; }
public System.Data.SqlClient.PoolBlockingPeriod PoolBlockingPeriod { get { throw null; } set { } }
}
public sealed partial class SqlDataAdapter : System.Data.Common.DbDataAdapter, System.Data.IDbDataAdapter, System.ICloneable
{
Expand Down
1 change: 1 addition & 0 deletions src/System.Data.SqlClient/src/System.Data.SqlClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
<Compile Include="System\Data\SqlClient\ApplicationIntent.cs" />
<Compile Include="System\Data\SqlClient\LocalDBAPI.cs" />
<Compile Include="System\Data\SqlClient\ParameterPeekAheadValue.cs" />
<Compile Include="System\Data\SqlClient\PoolBlockingPeriod.cs" />
<Compile Include="System\Data\SqlClient\RowsCopiedEventArgs.cs" />
<Compile Include="System\Data\SqlClient\RowsCopiedEventHandler.cs" />
<Compile Include="System\Data\SqlClient\SortOrder.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,142 @@ internal static string ConvertToString(object value)
throw ADP.ConvertFailed(value.GetType(), typeof(String), e);
}
}
#region <<PoolBlockingPeriod Utility>>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: space above this region line

const string PoolBlockingPeriodAutoString = "Auto";
const string PoolBlockingPeriodAlwaysBlockString = "AlwaysBlock";
const string PoolBlockingPeriodNeverBlockString = "NeverBlock";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than naming these consts like this, could you just use nameof(PoolBlockingPeriod.Auto), etc., at the call sites where they're used?


internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result)
{
Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed");
Debug.Assert(null != value, "TryConvertToPoolBlockingPeriod(null,...)");

if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodAutoString))
{
result = PoolBlockingPeriod.Auto;
return true;
}
else if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodAlwaysBlockString))
{
result = PoolBlockingPeriod.AlwaysBlock;
return true;
}
else if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodNeverBlockString))
{
result = PoolBlockingPeriod.NeverBlock;
return true;
}
else
{
result = DbConnectionStringDefaults.PoolBlockingPeriod;
return false;
}
}

internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value)
{
Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed");
return value == PoolBlockingPeriod.Auto || value == PoolBlockingPeriod.AlwaysBlock || value == PoolBlockingPeriod.NeverBlock;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you have is fine, but this could also just be:

return (uint)value <= (uint)PoolBlockingPeriod.NeverBlock;

}

internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value)
{
Debug.Assert(IsValidPoolBlockingPeriodValue(value));

if (value == PoolBlockingPeriod.AlwaysBlock)
{
return PoolBlockingPeriodAlwaysBlockString;
}
if (value == PoolBlockingPeriod.NeverBlock)
{
return PoolBlockingPeriodNeverBlockString;
}
else
{
return PoolBlockingPeriodAutoString;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I think this would be cleaner as a switch:

switch (value)
{
    case PoolBlockingPeriod.AlwaysBlock: return nameof(PoolBlockingPeriod.AlwaysBlock);
    case PoolBlockingPeriod.NeverBlock: return nameof(PoolBlockingPeriod.NeverBlock);
    default: return nameof(PoolBlockingPeriod.Auto);
}

}

/// <summary>
/// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is:
/// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer
/// * if the value is from type PoolBlockingPeriod, it will be used as is
/// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum
/// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException
///
/// in any case above, if the conerted value is out of valid range, the method raises ArgumentOutOfRangeException.
/// </summary>
/// <returns>PoolBlockingPeriod value in the valid range</returns>
internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value)
{
Debug.Assert(null != value, "ConvertToPoolBlockingPeriod(null)");
string sValue = (value as string);
PoolBlockingPeriod result;
if (null != sValue)
{
// We could use Enum.TryParse<PoolBlockingPeriod> here, but it accepts value combinations like
// "ReadOnly, ReadWrite" which are unwelcome here
// Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used on a hot path?


if (TryConvertToPoolBlockingPeriod(sValue, out result))
{
return result;
}

// try again after remove leading & trailing whitespaces.
sValue = sValue.Trim();
if (TryConvertToPoolBlockingPeriod(sValue, out result))
{
return result;
}

// string values must be valid
throw ADP.InvalidConnectionOptionValue(keyword);
}
else
{
// the value is not string, try other options
PoolBlockingPeriod eValue;

if (value is PoolBlockingPeriod)
{
// quick path for the most common case
eValue = (PoolBlockingPeriod)value;
}
else if (value.GetType().IsEnum)
{
// explicitly block scenarios in which user tries to use wrong enum types, like:
// builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process;
// workaround: explicitly cast non-PoolBlockingPeriod enums to int
throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null);
}
else
{
try
{
// Enum.ToObject allows only integral and enum values (enums are blocked above), rasing ArgumentException for the rest
eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value);
}
catch (ArgumentException e)
{
// to be consistent with the messages we send in case of wrong type usage, replace
// the error with our exception, and keep the original one as inner one for troubleshooting
throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e);
}
}

// ensure value is in valid range
if (IsValidPoolBlockingPeriodValue(eValue))
{
return eValue;
}
else
{
throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue);
}
}
}
#endregion
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far all of the code has been about converting to/from this enum. I'm surprised all of that code is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate more on this? There is a similar method ConvertToApplicationIntent in here which is following the same steps . Should we create a method instead and call it inside ConvertToApplicationIntent and ConvertToPoolBlockingPeriod ? :https://github.com/dotnet/corefx/blob/master/src/System.Data.SqlClient/src/System/Data/Common/DbConnectionStringCommon.cs#L156


private const string ApplicationIntentReadWriteString = "ReadWrite";
private const string ApplicationIntentReadOnlyString = "ReadOnly";
Expand Down Expand Up @@ -259,6 +395,7 @@ internal static partial class DbConnectionStringDefaults
internal const string TransactionBinding = "Implicit Unbind";
internal const int ConnectRetryCount = 1;
internal const int ConnectRetryInterval = 10;
internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto;
}


Expand Down Expand Up @@ -306,6 +443,7 @@ internal static partial class DbConnectionStringKeywords
internal const string MaxPoolSize = "Max Pool Size";
internal const string Pooling = "Pooling";
internal const string MinPoolSize = "Min Pool Size";
internal const string PoolBlockingPeriod = "PoolBlockingPeriod";
}

internal static class DbConnectionStringSynonyms
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can get rid of this using statement from this file.

using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -668,6 +669,45 @@ private Timer CreateCleanupTimer() =>
_cleanupWait,
_cleanupWait);

private bool IsBlockingPeriodEnabled()
{
var poolGroupConnectionOptions = _connectionPoolGroup.ConnectionOptions as SqlConnectionString;
if (poolGroupConnectionOptions == null)
{
return true;
}
var policy = poolGroupConnectionOptions.PoolBlockingPeriod;

switch (policy)
{
case System.Data.SqlClient.PoolBlockingPeriod.Auto:
{
if (ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource))
{
return false; // in Azure it will be Disabled
}
else
{
return true; // in Non Azure, it will be Enabled
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

return !ADP.IsAzureSqlServerEndpoint(poolGroupConnectionOptions.DataSource);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
case System.Data.SqlClient.PoolBlockingPeriod.AlwaysBlock:
{
return true; //Enabled
}
case System.Data.SqlClient.PoolBlockingPeriod.NeverBlock:
{
return false; //Disabled
}
default:
{
//we should never get into this path.
Debug.Fail("Unknown PoolBlockingPeriod. Please specify explicit results in above switch case statement.");
return true;
}
}
}

private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
{
DbConnectionInternal newObj = null;
Expand Down Expand Up @@ -719,6 +759,10 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio
{
throw;
}
if (!IsBlockingPeriodEnabled())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am OK with this approach. However an alternative could have been to call a function here CheckPoolBlockingPeriod();
There there could have been a partial DbConectionPool for netstandard which leaves the function empty and another DbConnectionPool.netcoreapp.cs compiled when netcoreapp DLL is built, which implements

internal void CheckPoolBlockingPeriod() 
{ 
      if (!IsBlockingPeriodEnabled()) 
     {
               throw;
     } 

}

{
throw;
}
newObj = null; // set to null, so we do not return bad new object
// Failed to create instance
_resError = e;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


namespace System.Data.SqlClient
{
public enum PoolBlockingPeriod
{
Auto = 0, // Blocking period OFF for Azure SQL servers, but ON for all other SQL servers.
AlwaysBlock = 1, // Blocking period ON for all SQL servers including Azure SQL servers.
NeverBlock = 2, // Blocking period OFF for all SQL servers including Azure SQL servers.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@ internal Version TypeSystemAssemblyVersion
get => ((SqlConnectionString)ConnectionOptions).TypeSystemAssemblyVersion;
}

internal PoolBlockingPeriod PoolBlockingPeriod
{
get => ((SqlConnectionString)ConnectionOptions).PoolBlockingPeriod;
}

internal int ConnectRetryInterval
{
get => ((SqlConnectionString)ConnectionOptions).ConnectRetryInterval;
Expand Down
Loading