From 48987576ce7d2434d7d202b879420c280126c16a Mon Sep 17 00:00:00 2001 From: Gene Lee Date: Tue, 19 Sep 2017 17:05:45 -0700 Subject: [PATCH 1/7] Fix for hanging connection to mirrored server --- .../SqlClient/SqlInternalConnectionTds.cs | 2 +- .../ConnectionOnMirroringTest.cs | 111 ++++++++++++++++++ ....Data.SqlClient.ManualTesting.Tests.csproj | 1 + 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs index 0bc0df2c97ac..f5c03bb81cf8 100644 --- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs @@ -1416,7 +1416,7 @@ TimeoutTimer timeout // Determine unit interval if (timeout.IsInfinite) { - timeoutUnitInterval = checked((long)ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout)); + timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout))); } else { diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs new file mode 100644 index 000000000000..6bbb53bb7929 --- /dev/null +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs @@ -0,0 +1,111 @@ +// 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.Generic; +using System.Diagnostics; +using System.Threading; + +namespace System.Data.SqlClient.ManualTesting.Tests +{ + public static class ConnectionOnMirroringTest + { + [CheckConnStrSetupFact] + public static void TestMultipleConnectionToMirroredServer() + { + string connectionString = DataTestUtility.TcpConnStr; + int mirroringState; + string failoverPartnerName; + bool isMirroring = GetMirroringInfo(connectionString, out mirroringState, out failoverPartnerName); + List list = new List(); + if (isMirroring && mirroringState == 4 && !string.IsNullOrEmpty(failoverPartnerName)) + { + Stopwatch stopWatch = new Stopwatch(); + TestWorker worker = new TestWorker(connectionString); + Thread childThread = new Thread(() => worker.TestMultipleConnection()); + + stopWatch.Start(); + childThread.Start(); + while (!worker.IsDone && stopWatch.ElapsedMilliseconds <= 10000); + stopWatch.Stop(); + + if (worker.IsDone) + { + childThread.Join(); + } + else + { + childThread.Interrupt(); + throw new Exception(); + } + } + } + + private static bool GetMirroringInfo(string connectionString, out int mirroringState, out string failoverPartnerName) + { + mirroringState = -1; + failoverPartnerName = null; + + SqlConnectionStringBuilder existingConnStrBuilder = new SqlConnectionStringBuilder(connectionString); + SqlConnectionStringBuilder newConnStrBuilder = new SqlConnectionStringBuilder(); + newConnStrBuilder.DataSource = existingConnStrBuilder.DataSource; + if (!string.IsNullOrEmpty(existingConnStrBuilder.UserID)) + { + newConnStrBuilder.UserID = existingConnStrBuilder.UserID; + } + if (!string.IsNullOrEmpty(existingConnStrBuilder.Password)) + { + newConnStrBuilder.Password = existingConnStrBuilder.Password; + } + if (existingConnStrBuilder.IntegratedSecurity) + { + newConnStrBuilder.IntegratedSecurity = true; + } + + string dbname = existingConnStrBuilder.InitialCatalog; + DataTable dt = DataTestUtility.RunQuery(newConnStrBuilder.ConnectionString, $"select mirroring_state from sys.database_mirroring where database_id = DB_ID('{dbname}')"); + bool isMirroring = Int32.TryParse(dt.Rows[0][0].ToString(), out mirroringState); + + if (isMirroring) + { + dt = DataTestUtility.RunQuery(newConnStrBuilder.ConnectionString, $"select mirroring_partner_name from sys.database_mirroring where database_id = DB_ID('{dbname}')"); + failoverPartnerName = dt.Rows[0][0].ToString(); + } + + return isMirroring; + } + + private class TestWorker + { + private string _connectionString; + private bool _isDone; + + public TestWorker(string connectionString) + { + _connectionString = connectionString; + _isDone = false; + } + + public bool IsDone { get => _isDone; } + + public void TestMultipleConnection() + { + List list = new List(); + + for (int i = 0; i < 10; ++i) + { + SqlConnection conn = new SqlConnection(_connectionString); + list.Add(conn); + conn.Open(); + } + + foreach (SqlConnection conn in list) + { + conn.Dispose(); + } + + _isDone = true; + } + } + } +} diff --git a/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj b/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj index 3805a80820b9..7a0e5419151a 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj @@ -56,6 +56,7 @@ + From e0a6d7e6b0858d8f07c092c98d73ca4914022df8 Mon Sep 17 00:00:00 2001 From: Gene Lee Date: Wed, 20 Sep 2017 13:58:33 -0700 Subject: [PATCH 2/7] added comment --- .../ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs index 6bbb53bb7929..5f92d4059b5e 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs @@ -35,6 +35,7 @@ public static void TestMultipleConnectionToMirroredServer() } else { + //thread.Abort() is not implemented yet in CoreFx. childThread.Interrupt(); throw new Exception(); } From e9c1fd6486ed3b4d20b87eed8d241643a6ad4540 Mon Sep 17 00:00:00 2001 From: Gene Lee Date: Wed, 20 Sep 2017 17:29:06 -0700 Subject: [PATCH 3/7] PR comment fix --- .../ConnectionOnMirroringTest.cs | 59 +++++++++---------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs index 5f92d4059b5e..cdd053317d8a 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs @@ -10,24 +10,28 @@ namespace System.Data.SqlClient.ManualTesting.Tests { public static class ConnectionOnMirroringTest { + private static ManualResetEvent mre = new ManualResetEvent(false); + [CheckConnStrSetupFact] public static void TestMultipleConnectionToMirroredServer() { - string connectionString = DataTestUtility.TcpConnStr; - int mirroringState; + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TcpConnStr); + builder.ConnectTimeout = 0; + string connectionString = builder.ConnectionString; + + string mirroringStateDesc; string failoverPartnerName; - bool isMirroring = GetMirroringInfo(connectionString, out mirroringState, out failoverPartnerName); + bool isMirroring = GetMirroringInfo(connectionString, out mirroringStateDesc, out failoverPartnerName); + bool isSynchronized = "SYNCHRONIZED".Equals(mirroringStateDesc, StringComparison.InvariantCultureIgnoreCase); List list = new List(); - if (isMirroring && mirroringState == 4 && !string.IsNullOrEmpty(failoverPartnerName)) + if (isMirroring && isSynchronized && !string.IsNullOrEmpty(failoverPartnerName)) { - Stopwatch stopWatch = new Stopwatch(); TestWorker worker = new TestWorker(connectionString); Thread childThread = new Thread(() => worker.TestMultipleConnection()); - - stopWatch.Start(); childThread.Start(); - while (!worker.IsDone && stopWatch.ElapsedMilliseconds <= 10000); - stopWatch.Stop(); + + mre.Reset(); + mre.WaitOne(10000); if (worker.IsDone) { @@ -35,41 +39,31 @@ public static void TestMultipleConnectionToMirroredServer() } else { - //thread.Abort() is not implemented yet in CoreFx. + // currently Thread.Abort() throws PlatformNotSupportedException in CoreFx. childThread.Interrupt(); - throw new Exception(); + throw new Exception("SqlConnection could not open and close successfully in timely manner. Possibly connection hangs."); } } } - private static bool GetMirroringInfo(string connectionString, out int mirroringState, out string failoverPartnerName) + private static bool GetMirroringInfo(string connectionString, out string mirroringStateDesc, out string failoverPartnerName) { - mirroringState = -1; + mirroringStateDesc = null; failoverPartnerName = null; - SqlConnectionStringBuilder existingConnStrBuilder = new SqlConnectionStringBuilder(connectionString); - SqlConnectionStringBuilder newConnStrBuilder = new SqlConnectionStringBuilder(); - newConnStrBuilder.DataSource = existingConnStrBuilder.DataSource; - if (!string.IsNullOrEmpty(existingConnStrBuilder.UserID)) - { - newConnStrBuilder.UserID = existingConnStrBuilder.UserID; - } - if (!string.IsNullOrEmpty(existingConnStrBuilder.Password)) - { - newConnStrBuilder.Password = existingConnStrBuilder.Password; - } - if (existingConnStrBuilder.IntegratedSecurity) - { - newConnStrBuilder.IntegratedSecurity = true; - } + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); + string dbname = builder.InitialCatalog; + + builder.Remove("Connection Timeout"); + connectionString = builder.ConnectionString; - string dbname = existingConnStrBuilder.InitialCatalog; - DataTable dt = DataTestUtility.RunQuery(newConnStrBuilder.ConnectionString, $"select mirroring_state from sys.database_mirroring where database_id = DB_ID('{dbname}')"); - bool isMirroring = Int32.TryParse(dt.Rows[0][0].ToString(), out mirroringState); + DataTable dt = DataTestUtility.RunQuery(connectionString, $"select mirroring_state_desc from sys.database_mirroring where database_id = DB_ID('{dbname}')"); + mirroringStateDesc = dt.Rows[0][0].ToString(); + bool isMirroring = !string.IsNullOrEmpty(mirroringStateDesc); if (isMirroring) { - dt = DataTestUtility.RunQuery(newConnStrBuilder.ConnectionString, $"select mirroring_partner_name from sys.database_mirroring where database_id = DB_ID('{dbname}')"); + dt = DataTestUtility.RunQuery(connectionString, $"select mirroring_partner_name from sys.database_mirroring where database_id = DB_ID('{dbname}')"); failoverPartnerName = dt.Rows[0][0].ToString(); } @@ -106,6 +100,7 @@ public void TestMultipleConnection() } _isDone = true; + mre.Set(); } } } From 2b10f94c33b17dd3efe9eec65ea730c145142e50 Mon Sep 17 00:00:00 2001 From: Gene Lee Date: Wed, 20 Sep 2017 17:39:44 -0700 Subject: [PATCH 4/7] PR comment fix --- .../MirroringTest/ConnectionOnMirroringTest.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs index cdd053317d8a..e9c27dbc58fd 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs @@ -10,7 +10,7 @@ namespace System.Data.SqlClient.ManualTesting.Tests { public static class ConnectionOnMirroringTest { - private static ManualResetEvent mre = new ManualResetEvent(false); + private static ManualResetEvent workerCompletedEvent = new ManualResetEvent(false); [CheckConnStrSetupFact] public static void TestMultipleConnectionToMirroredServer() @@ -23,17 +23,13 @@ public static void TestMultipleConnectionToMirroredServer() string failoverPartnerName; bool isMirroring = GetMirroringInfo(connectionString, out mirroringStateDesc, out failoverPartnerName); bool isSynchronized = "SYNCHRONIZED".Equals(mirroringStateDesc, StringComparison.InvariantCultureIgnoreCase); - List list = new List(); if (isMirroring && isSynchronized && !string.IsNullOrEmpty(failoverPartnerName)) { TestWorker worker = new TestWorker(connectionString); Thread childThread = new Thread(() => worker.TestMultipleConnection()); childThread.Start(); - mre.Reset(); - mre.WaitOne(10000); - - if (worker.IsDone) + if (workerCompletedEvent.WaitOne(10000)) { childThread.Join(); } @@ -73,16 +69,12 @@ private static bool GetMirroringInfo(string connectionString, out string mirrori private class TestWorker { private string _connectionString; - private bool _isDone; public TestWorker(string connectionString) { _connectionString = connectionString; - _isDone = false; } - public bool IsDone { get => _isDone; } - public void TestMultipleConnection() { List list = new List(); @@ -99,8 +91,7 @@ public void TestMultipleConnection() conn.Dispose(); } - _isDone = true; - mre.Set(); + workerCompletedEvent.Set(); } } } From 3cc1090d345863b9fdad4306d98d9205d3edf850 Mon Sep 17 00:00:00 2001 From: Gene Lee Date: Wed, 20 Sep 2017 17:56:40 -0700 Subject: [PATCH 5/7] PR comment fix --- .../ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs index e9c27dbc58fd..63ea505d0cd7 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs @@ -50,7 +50,7 @@ private static bool GetMirroringInfo(string connectionString, out string mirrori SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString); string dbname = builder.InitialCatalog; - builder.Remove("Connection Timeout"); + builder.ConnectTimeout = 5; connectionString = builder.ConnectionString; DataTable dt = DataTestUtility.RunQuery(connectionString, $"select mirroring_state_desc from sys.database_mirroring where database_id = DB_ID('{dbname}')"); From dc9c69bf2946f23690353490e4331af376e67675 Mon Sep 17 00:00:00 2001 From: Gene Lee Date: Wed, 20 Sep 2017 18:05:07 -0700 Subject: [PATCH 6/7] PR comment fix --- .../SQL/MirroringTest/ConnectionOnMirroringTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs index 63ea505d0cd7..fc8cd0823e71 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs @@ -15,16 +15,16 @@ public static class ConnectionOnMirroringTest [CheckConnStrSetupFact] public static void TestMultipleConnectionToMirroredServer() { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TcpConnStr); - builder.ConnectTimeout = 0; - string connectionString = builder.ConnectionString; - string mirroringStateDesc; string failoverPartnerName; - bool isMirroring = GetMirroringInfo(connectionString, out mirroringStateDesc, out failoverPartnerName); + bool isMirroring = GetMirroringInfo(DataTestUtility.TcpConnStr, out mirroringStateDesc, out failoverPartnerName); bool isSynchronized = "SYNCHRONIZED".Equals(mirroringStateDesc, StringComparison.InvariantCultureIgnoreCase); if (isMirroring && isSynchronized && !string.IsNullOrEmpty(failoverPartnerName)) { + SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TcpConnStr); + builder.ConnectTimeout = 0; + string connectionString = builder.ConnectionString; + TestWorker worker = new TestWorker(connectionString); Thread childThread = new Thread(() => worker.TestMultipleConnection()); childThread.Start(); From ec2f6a148b997165709b06dd8cda575c85f37e18 Mon Sep 17 00:00:00 2001 From: Gene Lee Date: Wed, 20 Sep 2017 18:07:29 -0700 Subject: [PATCH 7/7] PR comment fix --- .../ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs index fc8cd0823e71..ac72f03d1c0d 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/MirroringTest/ConnectionOnMirroringTest.cs @@ -23,9 +23,8 @@ public static void TestMultipleConnectionToMirroredServer() { SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(DataTestUtility.TcpConnStr); builder.ConnectTimeout = 0; - string connectionString = builder.ConnectionString; - TestWorker worker = new TestWorker(connectionString); + TestWorker worker = new TestWorker(builder.ConnectionString); Thread childThread = new Thread(() => worker.TestMultipleConnection()); childThread.Start();