Skip to content

Commit dfa62a1

Browse files
authored
Parallelize SSRP requests when MSF is specified (#1578)
1 parent 3072fd6 commit dfa62a1

File tree

5 files changed

+321
-35
lines changed

5 files changed

+321
-35
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNICommon.cs

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ internal class SNICommon
108108
internal const int ConnTimeoutError = 11;
109109
internal const int ConnNotUsableError = 19;
110110
internal const int InvalidConnStringError = 25;
111+
internal const int ErrorLocatingServerInstance = 26;
111112
internal const int HandshakeFailureError = 31;
112113
internal const int InternalExceptionError = 35;
113114
internal const int ConnOpenFailedError = 40;

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNIProxy.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ private static bool IsErrorStatus(SecurityStatusPalErrorCode errorCode)
141141
/// <param name="isIntegratedSecurity"></param>
142142
/// <param name="ipPreference">IP address preference</param>
143143
/// <param name="cachedFQDN">Used for DNS Cache</param>
144-
/// <param name="pendingDNSInfo">Used for DNS Cache</param>
144+
/// <param name="pendingDNSInfo">Used for DNS Cache</param>
145145
/// <returns>SNI handle</returns>
146146
internal static SNIHandle CreateConnectionHandle(string fullServerName, bool ignoreSniOpenTimeout, long timerExpire, out byte[] instanceName, ref byte[][] spnBuffer,
147147
bool flushCache, bool async, bool parallel, bool isIntegratedSecurity, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
@@ -263,7 +263,7 @@ private static byte[][] GetSqlServerSPNs(string hostNameOrAddress, string portOr
263263
/// <param name="parallel">Should MultiSubnetFailover be used</param>
264264
/// <param name="ipPreference">IP address preference</param>
265265
/// <param name="cachedFQDN">Key for DNS Cache</param>
266-
/// <param name="pendingDNSInfo">Used for DNS Cache</param>
266+
/// <param name="pendingDNSInfo">Used for DNS Cache</param>
267267
/// <returns>SNITCPHandle</returns>
268268
private static SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire, bool parallel, SqlConnectionIPAddressPreference ipPreference, string cachedFQDN, ref SQLDNSInfo pendingDNSInfo)
269269
{
@@ -285,12 +285,12 @@ private static SNITCPHandle CreateTcpHandle(DataSource details, long timerExpire
285285
try
286286
{
287287
port = isAdminConnection ?
288-
SSRP.GetDacPortByInstanceName(hostName, details.InstanceName) :
289-
SSRP.GetPortByInstanceName(hostName, details.InstanceName);
288+
SSRP.GetDacPortByInstanceName(hostName, details.InstanceName, timerExpire, parallel, ipPreference) :
289+
SSRP.GetPortByInstanceName(hostName, details.InstanceName, timerExpire, parallel, ipPreference);
290290
}
291291
catch (SocketException se)
292292
{
293-
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.InvalidConnStringError, se);
293+
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.TCP_PROV, SNICommon.ErrorLocatingServerInstance, se);
294294
return null;
295295
}
296296
}

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SNI/SNITcpHandle.cs

+17-6
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ public SNITCPHandle(string serverName, int port, long timerExpire, bool parallel
146146
bool reportError = true;
147147

148148
SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "Connection Id {0}, Connecting to serverName {1} and port {2}", args0: _connectionId, args1: serverName, args2: port);
149-
// We will always first try to connect with serverName as before and let the DNS server to resolve the serverName.
150-
// If the DSN resolution fails, we will try with IPs in the DNS cache if existed. We try with cached IPs based on IPAddressPreference.
151-
// The exceptions will be throw to upper level and be handled as before.
149+
// We will always first try to connect with serverName as before and let DNS resolve the serverName.
150+
// If DNS resolution fails, we will try with IPs in the DNS cache if they exist. We try with cached IPs based on IPAddressPreference.
151+
// Exceptions will be thrown to the caller and be handled as before.
152152
try
153153
{
154154
if (parallel)
@@ -280,7 +280,12 @@ private Socket TryConnectParallel(string hostName, int port, TimeSpan ts, bool i
280280
Task<Socket> connectTask;
281281

282282
Task<IPAddress[]> serverAddrTask = Dns.GetHostAddressesAsync(hostName);
283-
serverAddrTask.Wait(ts);
283+
bool complete = serverAddrTask.Wait(ts);
284+
285+
// DNS timed out - don't block
286+
if (!complete)
287+
return null;
288+
284289
IPAddress[] serverAddresses = serverAddrTask.Result;
285290

286291
if (serverAddresses.Length > MaxParallelIpAddresses)
@@ -324,7 +329,6 @@ private Socket TryConnectParallel(string hostName, int port, TimeSpan ts, bool i
324329

325330
availableSocket = connectTask.Result;
326331
return availableSocket;
327-
328332
}
329333

330334
// Connect to server with hostName and port.
@@ -334,7 +338,14 @@ private static Socket Connect(string serverName, int port, TimeSpan timeout, boo
334338
{
335339
SqlClientEventSource.Log.TrySNITraceEvent(nameof(SNITCPHandle), EventType.INFO, "IP preference : {0}", Enum.GetName(typeof(SqlConnectionIPAddressPreference), ipPreference));
336340

337-
IPAddress[] ipAddresses = Dns.GetHostAddresses(serverName);
341+
Task<IPAddress[]> serverAddrTask = Dns.GetHostAddressesAsync(serverName);
342+
bool complete = serverAddrTask.Wait(timeout);
343+
344+
// DNS timed out - don't block
345+
if (!complete)
346+
return null;
347+
348+
IPAddress[] ipAddresses = serverAddrTask.Result;
338349

339350
string IPv4String = null;
340351
string IPv6String = null;

0 commit comments

Comments
 (0)