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 a309305dc3..018e1b9567 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -470,7 +470,9 @@ - + + Microsoft\Data\SqlClient\SqlConnectionTimeoutErrorInternal.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 914fe96939..091b655f6d 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -453,7 +453,9 @@ - + + Microsoft\Data\SqlClient\SqlConnectionTimeoutErrorInternal.cs + Microsoft\Data\SqlClient\SqlCredential.cs @@ -612,4 +614,4 @@ - \ No newline at end of file + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs deleted file mode 100644 index 992ba2f45d..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs +++ /dev/null @@ -1,229 +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; -using System.Diagnostics; -using System.Text; - -namespace Microsoft.Data.SqlClient -{ - // VSTFDevDiv# 643319 - Improve timeout error message reported when SqlConnection.Open fails - internal enum SqlConnectionTimeoutErrorPhase - { - Undefined = 0, - PreLoginBegin, // [PRE-LOGIN PHASE] Start of the pre-login phase; Initialize global variables; - InitializeConnection, // [PRE-LOGIN PHASE] Create and initialize socket. - SendPreLoginHandshake, // [PRE-LOGIN PHASE] Make pre-login handshake request. - ConsumePreLoginHandshake, // [PRE-LOGIN PHASE] Receive pre-login handshake response and consume it; Establish an SSL channel. - LoginBegin, // [LOGIN PHASE] End of the pre-login phase; Start of the login phase; - ProcessConnectionAuth, // [LOGIN PHASE] Process SSPI or SQL Authenticate. - PostLogin, // [POST-LOGIN PHASE] End of the login phase; And post-login phase; - Complete, // Marker for the succesful completion of the connection - Count // ** This is to track the length of the enum. ** Do not add any phase after this. ** - } - - internal enum SqlConnectionInternalSourceType - { - Principle, - Failover, - RoutingDestination - } - - // DEVNOTE: Class to capture the duration spent in each SqlConnectionTimeoutErrorPhase. - internal class SqlConnectionTimeoutPhaseDuration - { - Stopwatch swDuration = new Stopwatch(); - - internal void StartCapture() - { - Debug.Assert(swDuration != null, "Time capture stopwatch cannot be null."); - swDuration.Start(); - } - - internal void StopCapture() - { - //Debug.Assert(swDuration.IsRunning == true, "The stop opertaion of the stopwatch cannot be called when it is not running."); - if (swDuration.IsRunning == true) - swDuration.Stop(); - } - - internal long GetMilliSecondDuration() - { - // DEVNOTE: In a phase fails in between a phase, the stop watch may still be running. - // Hence the check to verify if the stop watch is running hasn't been added in. - return swDuration.ElapsedMilliseconds; - } - } - - internal class SqlConnectionTimeoutErrorInternal - { - SqlConnectionTimeoutPhaseDuration[] phaseDurations = null; - SqlConnectionTimeoutPhaseDuration[] originalPhaseDurations = null; - - SqlConnectionTimeoutErrorPhase currentPhase = SqlConnectionTimeoutErrorPhase.Undefined; - SqlConnectionInternalSourceType currentSourceType = SqlConnectionInternalSourceType.Principle; - bool isFailoverScenario = false; - - internal SqlConnectionTimeoutErrorPhase CurrentPhase - { - get { return currentPhase; } - } - - public SqlConnectionTimeoutErrorInternal() - { - phaseDurations = new SqlConnectionTimeoutPhaseDuration[(int)SqlConnectionTimeoutErrorPhase.Count]; - for (int i = 0; i < phaseDurations.Length; i++) - phaseDurations[i] = null; - } - - public void SetFailoverScenario(bool useFailoverServer) - { - isFailoverScenario = useFailoverServer; - } - - public void SetInternalSourceType(SqlConnectionInternalSourceType sourceType) - { - currentSourceType = sourceType; - - if (currentSourceType == SqlConnectionInternalSourceType.RoutingDestination) - { - // When we get routed, save the current phase durations so that we can use them in the error message later - Debug.Assert(currentPhase == SqlConnectionTimeoutErrorPhase.PostLogin, "Should not be switching to the routing destination until Post Login is completed"); - originalPhaseDurations = phaseDurations; - phaseDurations = new SqlConnectionTimeoutPhaseDuration[(int)SqlConnectionTimeoutErrorPhase.Count]; - SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin); - } - } - - internal void ResetAndRestartPhase() - { - currentPhase = SqlConnectionTimeoutErrorPhase.PreLoginBegin; - for (int i = 0; i < phaseDurations.Length; i++) - phaseDurations[i] = null; - } - - internal void SetAndBeginPhase(SqlConnectionTimeoutErrorPhase timeoutErrorPhase) - { - currentPhase = timeoutErrorPhase; - if (phaseDurations[(int)timeoutErrorPhase] == null) - { - phaseDurations[(int)timeoutErrorPhase] = new SqlConnectionTimeoutPhaseDuration(); - } - phaseDurations[(int)timeoutErrorPhase].StartCapture(); - } - - internal void EndPhase(SqlConnectionTimeoutErrorPhase timeoutErrorPhase) - { - Debug.Assert(phaseDurations[(int)timeoutErrorPhase] != null, "End phase capture cannot be invoked when the phase duration object is a null."); - phaseDurations[(int)timeoutErrorPhase].StopCapture(); - } - - internal void SetAllCompleteMarker() - { - currentPhase = SqlConnectionTimeoutErrorPhase.Complete; - } - - internal string GetErrorMessage() - { - StringBuilder errorBuilder; - string durationString; - switch (currentPhase) - { - case SqlConnectionTimeoutErrorPhase.PreLoginBegin: - errorBuilder = new StringBuilder(SQLMessage.Timeout_PreLogin_Begin()); - durationString = SQLMessage.Duration_PreLogin_Begin( - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration()); - break; - case SqlConnectionTimeoutErrorPhase.InitializeConnection: - errorBuilder = new StringBuilder(SQLMessage.Timeout_PreLogin_InitializeConnection()); - durationString = SQLMessage.Duration_PreLogin_Begin( - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration()); - break; - case SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake: - errorBuilder = new StringBuilder(SQLMessage.Timeout_PreLogin_SendHandshake()); - durationString = SQLMessage.Duration_PreLoginHandshake( - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration()); - break; - case SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake: - errorBuilder = new StringBuilder(SQLMessage.Timeout_PreLogin_ConsumeHandshake()); - durationString = SQLMessage.Duration_PreLoginHandshake( - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration()); - break; - case SqlConnectionTimeoutErrorPhase.LoginBegin: - errorBuilder = new StringBuilder(SQLMessage.Timeout_Login_Begin()); - durationString = SQLMessage.Duration_Login_Begin( - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration()); - break; - case SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth: - errorBuilder = new StringBuilder(SQLMessage.Timeout_Login_ProcessConnectionAuth()); - durationString = SQLMessage.Duration_Login_ProcessConnectionAuth( - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration()); - break; - case SqlConnectionTimeoutErrorPhase.PostLogin: - errorBuilder = new StringBuilder(SQLMessage.Timeout_PostLogin()); - durationString = SQLMessage.Duration_PostLogin( - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration(), - phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PostLogin].GetMilliSecondDuration()); - break; - default: - errorBuilder = new StringBuilder(SQLMessage.Timeout()); - durationString = null; - break; - } - - // This message is to be added only when within the various stages of a connection. - // In all other cases, it will default to the original error message. - if ((currentPhase != SqlConnectionTimeoutErrorPhase.Undefined) && (currentPhase != SqlConnectionTimeoutErrorPhase.Complete)) - { - // NOTE: In case of a failover scenario, add a string that this failure occurred as part of the primary or secondary server - if (isFailoverScenario) - { - errorBuilder.Append(" "); - errorBuilder.AppendFormat((IFormatProvider)null, SQLMessage.Timeout_FailoverInfo(), currentSourceType); - } - else if (currentSourceType == SqlConnectionInternalSourceType.RoutingDestination) - { - errorBuilder.Append(" "); - errorBuilder.AppendFormat((IFormatProvider)null, SQLMessage.Timeout_RoutingDestination(), - originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + - originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), - originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + - originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration(), - originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration(), - originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration(), - originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.PostLogin].GetMilliSecondDuration()); - } - } - - // NOTE: To display duration in each phase. - if (durationString != null) - { - errorBuilder.Append(" "); - errorBuilder.Append(durationString); - } - - return errorBuilder.ToString(); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs similarity index 93% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs index a6be1b2746..4e950a564c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionTimeoutErrorInternal.cs @@ -45,7 +45,9 @@ internal void StopCapture() { //Debug.Assert(swDuration.IsRunning == true, "The stop operation of the stopwatch cannot be called when it is not running."); if (_swDuration.IsRunning == true) + { _swDuration.Stop(); + } } internal long GetMilliSecondDuration() @@ -58,23 +60,21 @@ internal long GetMilliSecondDuration() internal class SqlConnectionTimeoutErrorInternal { - private SqlConnectionTimeoutPhaseDuration[] _phaseDurations = null; - private SqlConnectionTimeoutPhaseDuration[] _originalPhaseDurations = null; - - private SqlConnectionTimeoutErrorPhase _currentPhase = SqlConnectionTimeoutErrorPhase.Undefined; - private SqlConnectionInternalSourceType _currentSourceType = SqlConnectionInternalSourceType.Principle; - private bool _isFailoverScenario = false; + private SqlConnectionTimeoutPhaseDuration[] _phaseDurations; + private SqlConnectionTimeoutPhaseDuration[] _originalPhaseDurations; + private SqlConnectionTimeoutErrorPhase _currentPhase; + private SqlConnectionInternalSourceType _currentSourceType; + private bool _isFailoverScenario; - internal SqlConnectionTimeoutErrorPhase CurrentPhase - { - get { return _currentPhase; } - } + internal SqlConnectionTimeoutErrorPhase CurrentPhase => _currentPhase; public SqlConnectionTimeoutErrorInternal() { _phaseDurations = new SqlConnectionTimeoutPhaseDuration[(int)SqlConnectionTimeoutErrorPhase.Count]; for (int i = 0; i < _phaseDurations.Length; i++) + { _phaseDurations[i] = null; + } } public void SetFailoverScenario(bool useFailoverServer) @@ -100,7 +100,9 @@ internal void ResetAndRestartPhase() { _currentPhase = SqlConnectionTimeoutErrorPhase.PreLoginBegin; for (int i = 0; i < _phaseDurations.Length; i++) + { _phaseDurations[i] = null; + } } internal void SetAndBeginPhase(SqlConnectionTimeoutErrorPhase timeoutErrorPhase) @@ -133,20 +135,23 @@ internal string GetErrorMessage() case SqlConnectionTimeoutErrorPhase.PreLoginBegin: errorBuilder = new StringBuilder(SQLMessage.Timeout_PreLogin_Begin()); durationString = SQLMessage.Duration_PreLogin_Begin( - _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration()); + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + ); break; case SqlConnectionTimeoutErrorPhase.InitializeConnection: errorBuilder = new StringBuilder(SQLMessage.Timeout_PreLogin_InitializeConnection()); durationString = SQLMessage.Duration_PreLogin_Begin( _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + - _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration()); + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration() + ); break; case SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake: errorBuilder = new StringBuilder(SQLMessage.Timeout_PreLogin_SendHandshake()); durationString = SQLMessage.Duration_PreLoginHandshake( _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), - _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration()); + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + ); break; case SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake: errorBuilder = new StringBuilder(SQLMessage.Timeout_PreLogin_ConsumeHandshake()); @@ -154,7 +159,8 @@ internal string GetErrorMessage() _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PreLoginBegin].GetMilliSecondDuration() + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + - _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration()); + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration() + ); break; case SqlConnectionTimeoutErrorPhase.LoginBegin: errorBuilder = new StringBuilder(SQLMessage.Timeout_Login_Begin()); @@ -163,7 +169,8 @@ internal string GetErrorMessage() _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.InitializeConnection].GetMilliSecondDuration(), _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration(), - _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration()); + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration() + ); break; case SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth: errorBuilder = new StringBuilder(SQLMessage.Timeout_Login_ProcessConnectionAuth()); @@ -173,7 +180,8 @@ internal string GetErrorMessage() _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake].GetMilliSecondDuration() + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration(), _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration(), - _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration()); + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration() + ); break; case SqlConnectionTimeoutErrorPhase.PostLogin: errorBuilder = new StringBuilder(SQLMessage.Timeout_PostLogin()); @@ -184,7 +192,8 @@ internal string GetErrorMessage() _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration(), _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration(), _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration(), - _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PostLogin].GetMilliSecondDuration()); + _phaseDurations[(int)SqlConnectionTimeoutErrorPhase.PostLogin].GetMilliSecondDuration() + ); break; default: errorBuilder = new StringBuilder(SQLMessage.Timeout()); @@ -212,7 +221,8 @@ internal string GetErrorMessage() _originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake].GetMilliSecondDuration(), _originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.LoginBegin].GetMilliSecondDuration(), _originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth].GetMilliSecondDuration(), - _originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.PostLogin].GetMilliSecondDuration()); + _originalPhaseDurations[(int)SqlConnectionTimeoutErrorPhase.PostLogin].GetMilliSecondDuration() + ); } }