You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,244 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="SqlConnectionTimeoutErrorInternal.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
// <owner current="true" primary="false">[....]</owner>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Data.SqlClient
|
||||
{
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Threading;
|
||||
using SysTx = System.Transactions;
|
||||
using System.Data.SqlClient;
|
||||
using System.Text;
|
||||
|
||||
// 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 occured 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();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user