From cc985543fa5d6573352024b09790405d0d4bdbbf Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 11 Apr 2021 17:45:29 +0100 Subject: [PATCH 1/5] move netcore SqlStatistics to shared --- .../src/Microsoft.Data.SqlClient.csproj | 4 +- .../netfx/src/Microsoft.Data.SqlClient.csproj | 4 +- .../Microsoft/Data/SqlClient/SqlStatistics.cs | 221 ------------------ .../Microsoft/Data/SqlClient/SqlStatistics.cs | 0 4 files changed, 6 insertions(+), 223 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlStatistics.cs rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/SqlStatistics.cs (100%) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index b5e1dc903c..1db7c3ab1d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -489,7 +489,9 @@ - + + Microsoft\Data\SqlClient\SqlStatistics.cs + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 2ceeed013b..e36768383b 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -477,7 +477,9 @@ - + + Microsoft\Data\SqlClient\SqlStatistics.cs + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlStatistics.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlStatistics.cs deleted file mode 100644 index 7c72711cd2..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlStatistics.cs +++ /dev/null @@ -1,221 +0,0 @@ -// 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. - -using System.Collections; -using System.Diagnostics; -using Microsoft.Data.Common; - -namespace Microsoft.Data.SqlClient -{ - internal sealed class SqlStatistics - { - - static internal SqlStatistics StartTimer(SqlStatistics statistics) - { - if ((null != statistics) && !statistics.RequestExecutionTimer()) - { - // we're re-entrant -- don't bother. - statistics = null; - } - return statistics; - } - - static internal void StopTimer(SqlStatistics statistics) - { - if (null != statistics) - { - statistics.ReleaseAndUpdateExecutionTimer(); - } - } - - // internal values that are not exposed through properties - internal long _closeTimestamp; - internal long _openTimestamp; - internal long _startExecutionTimestamp; - internal long _startFetchTimestamp; - internal long _startNetworkServerTimestamp; - - // internal values that are exposed through properties - internal long _buffersReceived; - internal long _buffersSent; - internal long _bytesReceived; - internal long _bytesSent; - internal long _connectionTime; - internal long _cursorOpens; - internal long _executionTime; - internal long _iduCount; - internal long _iduRows; - internal long _networkServerTime; - internal long _preparedExecs; - internal long _prepares; - internal long _selectCount; - internal long _selectRows; - internal long _serverRoundtrips; - internal long _sumResultSets; - internal long _transactions; - internal long _unpreparedExecs; - - // these flags are required if statistics is turned on/off in the middle of command execution - private bool _waitForDoneAfterRow; - private bool _waitForReply; - - - internal bool WaitForDoneAfterRow - { - get - { - return _waitForDoneAfterRow; - } - set - { - _waitForDoneAfterRow = value; - } - } - - internal bool WaitForReply - { - get - { - return _waitForReply; - } - } - - internal SqlStatistics() - { - } - - internal void ContinueOnNewConnection() - { - _startExecutionTimestamp = 0; - _startFetchTimestamp = 0; - _waitForDoneAfterRow = false; - _waitForReply = false; - } - - internal IDictionary GetHashtable() - { - Hashtable ht = new Hashtable(18); - - ht.Add("BuffersReceived", _buffersReceived); - ht.Add("BuffersSent", _buffersSent); - ht.Add("BytesReceived", _bytesReceived); - ht.Add("BytesSent", _bytesSent); - ht.Add("CursorOpens", _cursorOpens); - ht.Add("IduCount", _iduCount); - ht.Add("IduRows", _iduRows); - ht.Add("PreparedExecs", _preparedExecs); - ht.Add("Prepares", _prepares); - ht.Add("SelectCount", _selectCount); - ht.Add("SelectRows", _selectRows); - ht.Add("ServerRoundtrips", _serverRoundtrips); - ht.Add("SumResultSets", _sumResultSets); - ht.Add("Transactions", _transactions); - ht.Add("UnpreparedExecs", _unpreparedExecs); - - ht.Add("ConnectionTime", ADP.TimerToMilliseconds(_connectionTime)); - ht.Add("ExecutionTime", ADP.TimerToMilliseconds(_executionTime)); - ht.Add("NetworkServerTime", ADP.TimerToMilliseconds(_networkServerTime)); - - return ht; - } - - internal bool RequestExecutionTimer() - { - if (_startExecutionTimestamp == 0) - { - _startExecutionTimestamp = ADP.TimerCurrent(); - return true; - } - return false; - } - - internal void RequestNetworkServerTimer() - { - Debug.Assert(_startExecutionTimestamp != 0, "No network time expected outside execution period"); - if (_startNetworkServerTimestamp == 0) - { - _startNetworkServerTimestamp = ADP.TimerCurrent(); - } - _waitForReply = true; - } - - internal void ReleaseAndUpdateExecutionTimer() - { - if (_startExecutionTimestamp > 0) - { - _executionTime += (ADP.TimerCurrent() - _startExecutionTimestamp); - _startExecutionTimestamp = 0; - } - } - - internal void ReleaseAndUpdateNetworkServerTimer() - { - if (_waitForReply && _startNetworkServerTimestamp > 0) - { - _networkServerTime += (ADP.TimerCurrent() - _startNetworkServerTimestamp); - _startNetworkServerTimestamp = 0; - } - _waitForReply = false; - } - - internal void Reset() - { - _buffersReceived = 0; - _buffersSent = 0; - _bytesReceived = 0; - _bytesSent = 0; - _connectionTime = 0; - _cursorOpens = 0; - _executionTime = 0; - _iduCount = 0; - _iduRows = 0; - _networkServerTime = 0; - _preparedExecs = 0; - _prepares = 0; - _selectCount = 0; - _selectRows = 0; - _serverRoundtrips = 0; - _sumResultSets = 0; - _transactions = 0; - _unpreparedExecs = 0; - _waitForDoneAfterRow = false; - _waitForReply = false; - _startExecutionTimestamp = 0; - _startNetworkServerTimestamp = 0; - } - - internal void SafeAdd(ref long value, long summand) - { - if (long.MaxValue - value > summand) - { - value += summand; - } - else - { - value = long.MaxValue; - } - } - - internal long SafeIncrement(ref long value) - { - if (value < long.MaxValue) - value++; - return value; - } - - internal void UpdateStatistics() - { - // update connection time - if (_closeTimestamp >= _openTimestamp && long.MaxValue > _closeTimestamp - _openTimestamp) - { - _connectionTime = _closeTimestamp - _openTimestamp; - } - else - { - _connectionTime = long.MaxValue; - } - } - } -} - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlStatistics.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlStatistics.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs From ee5f24c2529391ced348f1e41136aa653b41035b Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 11 Apr 2021 18:04:47 +0100 Subject: [PATCH 2/5] add ValueSqlStatisticsScope and static factory method --- .../Microsoft/Data/SqlClient/SqlStatistics.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs index 4aeeb28322..117bf80e34 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs @@ -30,6 +30,11 @@ internal static void StopTimer(SqlStatistics statistics) } } + internal static ValueSqlStatisticsScope TimedScope(SqlStatistics statistics) + { + return new ValueSqlStatisticsScope(statistics); + } + // internal values that are not exposed through properties internal long _closeTimestamp; internal long _openTimestamp; @@ -335,4 +340,22 @@ void ICollection.CopyTo(Array array, int arrayIndex) } } } + + // This is a ref struct to prevent it being included in async closures accidentally. + // Async functions should manage the timer directly using the Start and Stop method + // in their invoke and completion functions + internal readonly ref struct ValueSqlStatisticsScope // : IDisposable // ref structs cannot implement interfaces but the compiler will use pattern matching to implement dispose on them + { + private readonly SqlStatistics _statistics; + + public ValueSqlStatisticsScope(SqlStatistics statistics) + { + _statistics = SqlStatistics.StartTimer(statistics); + } + + public void Dispose() + { + SqlStatistics.StopTimer(_statistics); + } + } } From f68f1f67d9f841bae96524110e704f9b9f49c7d8 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 11 Apr 2021 18:05:11 +0100 Subject: [PATCH 3/5] style cleanup and comment clarification --- .../Microsoft/Data/SqlClient/SqlStatistics.cs | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs index 117bf80e34..7a5e37198b 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlStatistics.cs @@ -66,30 +66,17 @@ internal static ValueSqlStatisticsScope TimedScope(SqlStatistics statistics) private bool _waitForDoneAfterRow; private bool _waitForReply; - - internal bool WaitForDoneAfterRow + internal SqlStatistics() { - get - { - return _waitForDoneAfterRow; - } - set - { - _waitForDoneAfterRow = value; - } } - internal bool WaitForReply + internal bool WaitForDoneAfterRow { - get - { - return _waitForReply; - } + get => _waitForDoneAfterRow; + set => _waitForDoneAfterRow = value; } - internal SqlStatistics() - { - } + internal bool WaitForReply => _waitForReply; internal void ContinueOnNewConnection() { @@ -208,7 +195,9 @@ internal void SafeAdd(ref long value, long summand) internal long SafeIncrement(ref long value) { if (value < long.MaxValue) + { value++; + } return value; } @@ -294,13 +283,21 @@ private void CopyValues(Array array, int arrayIndex) private void ValidateCopyToArguments(Array array, int arrayIndex) { if (array == null) + { throw new ArgumentNullException(nameof(array)); + } if (array.Rank != 1) + { throw new ArgumentException(Strings.Arg_RankMultiDimNotSupported); + } if (arrayIndex < 0) + { throw new ArgumentOutOfRangeException(nameof(arrayIndex), Strings.ArgumentOutOfRange_NeedNonNegNum); + } if (array.Length - arrayIndex < Count) + { throw new ArgumentException(Strings.Arg_ArrayPlusOffTooSmall); + } } private sealed class Collection : ICollection @@ -344,18 +341,12 @@ void ICollection.CopyTo(Array array, int arrayIndex) // This is a ref struct to prevent it being included in async closures accidentally. // Async functions should manage the timer directly using the Start and Stop method // in their invoke and completion functions - internal readonly ref struct ValueSqlStatisticsScope // : IDisposable // ref structs cannot implement interfaces but the compiler will use pattern matching to implement dispose on them + internal readonly ref struct ValueSqlStatisticsScope // : IDisposable // ref structs cannot implement interfaces but the compiler will use pattern matching to allow use of using on them { private readonly SqlStatistics _statistics; - public ValueSqlStatisticsScope(SqlStatistics statistics) - { - _statistics = SqlStatistics.StartTimer(statistics); - } + public ValueSqlStatisticsScope(SqlStatistics statistics) => _statistics = SqlStatistics.StartTimer(statistics); - public void Dispose() - { - SqlStatistics.StopTimer(_statistics); - } + public void Dispose() => SqlStatistics.StopTimer(_statistics); } } From d320c291565e401a1c55db8925dccd5e6180279c Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 11 Apr 2021 19:21:39 +0100 Subject: [PATCH 4/5] fixup netfx strings and GetHashcode() calls --- .../netfx/src/Microsoft.Data.SqlClient.csproj | 6 ++-- .../Microsoft/Data/SqlClient/SqlConnection.cs | 4 +-- .../netfx/src/Resources/Strings.Designer.cs | 36 +++++++++++++++++++ .../netfx/src/Resources/Strings.resx | 14 +++++++- 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index e36768383b..4a6a84e487 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -542,10 +542,10 @@ - + True True - $(ResxFileName).resx + Strings.resx @@ -604,4 +604,4 @@ - + \ No newline at end of file diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs index c0dd91e2d7..1116e94e8f 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -2869,11 +2869,11 @@ public IDictionary RetrieveStatistics() if (null != Statistics) { UpdateStatistics(); - return Statistics.GetHashtable(); + return Statistics.GetDictionary(); } else { - return new SqlStatistics().GetHashtable(); + return new SqlStatistics().GetDictionary(); } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs index af7390b2a9..d1cdf1157f 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs @@ -1824,6 +1824,42 @@ internal static string ADP_VersionDoesNotSupportDataType { } } + /// + /// Looks up a localized string similar to Destination array is not long enough to copy all the items in the collection. Check array index and length.. + /// + internal static string Arg_ArrayPlusOffTooSmall { + get { + return ResourceManager.GetString("Arg_ArrayPlusOffTooSmall", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only single dimensional arrays are supported for the requested action.. + /// + internal static string Arg_RankMultiDimNotSupported { + get { + return ResourceManager.GetString("Arg_RankMultiDimNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot remove the specified item because it was not found in the specified Collection.. + /// + internal static string Arg_RemoveArgNotFound { + get { + return ResourceManager.GetString("Arg_RemoveArgNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Non-negative number required.. + /// + internal static string ArgumentOutOfRange_NeedNonNegNum { + get { + return ResourceManager.GetString("ArgumentOutOfRange_NeedNonNegNum", resourceCulture); + } + } + /// /// Looks up a localized string similar to The validation of an attestation token failed. The token signature does not match the signature omputed using a public key retrieved from the attestation public key endpoint at '{0}'. Verify the DNS apping for the endpoint. If correct, contact Customer Support Services.. /// diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx index d1b907c6e9..bd8efd2529 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx +++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx @@ -4617,4 +4617,16 @@ '{0}' is not less than '{1}'; '{2}' cannot be greater than '{3}'. - + + Destination array is not long enough to copy all the items in the collection. Check array index and length. + + + Only single dimensional arrays are supported for the requested action. + + + Cannot remove the specified item because it was not found in the specified Collection. + + + Non-negative number required. + + \ No newline at end of file From 3fef92fd8e558b7b3d5a5d9bd823c9578a9498b4 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Wed, 28 Apr 2021 19:41:31 +0100 Subject: [PATCH 5/5] restore resx project settings --- .../netfx/src/Microsoft.Data.SqlClient.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 4a6a84e487..e36768383b 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -542,10 +542,10 @@ - + True True - Strings.resx + $(ResxFileName).resx @@ -604,4 +604,4 @@ - \ No newline at end of file +