private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnection owningObject) { if (serverInfo.ExtendedServerName == null) { string userServerName = serverInfo.UserServerName; string userProtocol = serverInfo.UserProtocol; if (aliasLookup) { TdsParserStaticMethods.AliasRegistryLookup(ref userServerName, ref userProtocol); if ((owningObject != null) && ((SqlConnectionString)owningObject.UserConnectionOptions).EnforceLocalHost) { SqlConnectionString.VerifyLocalHostAndFixup(ref userServerName, true, true); } } serverInfo.SetDerivedNames(userProtocol, userServerName); } }
private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnectionString options) { if (serverInfo.ExtendedServerName == null) { string host = serverInfo.UserServerName; string protocol = serverInfo.UserProtocol; if (aliasLookup) { // We skip this for UserInstances... // Perform registry lookup to see if host is an alias. It will appropriately set host and protocol, if an Alias. // Check if it was already resolved, during CR reconnection _currentSessionData values will be copied from // _reconnectSessonData of the previous connection if (_currentSessionData != null && !string.IsNullOrEmpty(host)) { Tuple<string, string> hostPortPair; if (_currentSessionData._resolvedAliases.TryGetValue(host, out hostPortPair)) { host = hostPortPair.Item1; protocol = hostPortPair.Item2; } else { TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol); _currentSessionData._resolvedAliases.Add(serverInfo.UserServerName, new Tuple<string, string>(host, protocol)); } } else { TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol); } // if (options.EnforceLocalHost) { // verify LocalHost for |DataDirectory| usage SqlConnectionString.VerifyLocalHostAndFixup(ref host, true, true /*fix-up to "."*/); } } serverInfo.SetDerivedNames(protocol, host); } }
// Attempt to login to a host that has a failover partner // // Connection & timeout sequence is // First target, timeout = interval * 1 // second target, timeout = interval * 1 // sleep for 100ms // First target, timeout = interval * 2 // Second target, timeout = interval * 2 // sleep for 200ms // First Target, timeout = interval * 3 // etc. // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // DEVNOTE: The logic in this method is paralleled by the logic in LoginNoFailover. // Changes to either one should be examined to see if they need to be reflected in the other // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! private void LoginWithFailover( bool useFailoverHost, ServerInfo primaryServerInfo, string failoverHost, string newPassword, SecureString newSecurePassword, bool redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout ) { Debug.Assert(!connectionOptions.MultiSubnetFailover, "MultiSubnetFailover should not be set if failover partner is used"); if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", ObjectID, useFailoverHost); Bid.PutStr(primaryServerInfo.UserServerName); Bid.PutStr(", failover="); Bid.PutStr(failoverHost); Bid.PutStr("\n"); } int sleepInterval = 100; //milliseconds to sleep (back off) between attempts. long timeoutUnitInterval; string protocol = ConnectionOptions.NetworkLibrary; ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost); ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions); if (null == ServerProvidedFailOverPartner) {// No point in resolving the failover partner when we're going to override it below // Don't resolve aliases if failover == primary // ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions); } // Determine unit interval if (timeout.IsInfinite) { timeoutUnitInterval = checked((long) ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout)); } else { timeoutUnitInterval = checked((long) (ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining)); } // Initialize loop variables bool failoverDemandDone = false; // have we demanded for partner information yet (as necessary)? int attemptNumber = 0; // Only three ways out of this loop: // 1) Successfully connected // 2) Parser threw exception while main timer was expired // 3) Parser threw logon failure-related exception (LOGON_FAILED, PASSWORD_EXPIRED, etc) // // Of these methods, only #1 exits normally. This preserves the call stack on the exception // back into the parser for the error cases. while (true) { // Set timeout for this attempt, but don't exceed original timer long nextTimeoutInterval = checked(timeoutUnitInterval * ((attemptNumber / 2) + 1)); long milliseconds = timeout.MillisecondsRemaining; if (nextTimeoutInterval > milliseconds) { nextTimeoutInterval = milliseconds; } TimeoutTimer intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval); // Re-allocate parser each time to make sure state is known // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created if (_parser != null) _parser.Disconnect(); _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous); Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext)); ServerInfo currentServerInfo; if (useFailoverHost) { if (!failoverDemandDone) { FailoverPermissionDemand(); failoverDemandDone = true; } // Primary server may give us a different failover partner than the connection string indicates. Update it if (null != ServerProvidedFailOverPartner && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner) { if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", ObjectID, ServerProvidedFailOverPartner); } failoverServerInfo.SetDerivedNames(protocol, ServerProvidedFailOverPartner); } currentServerInfo = failoverServerInfo; timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover); } else { currentServerInfo = primaryServerInfo; timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Principle); } try { // Attempt login. Use timerInterval for attempt timeout unless infinite timeout was requested. AttemptOneLogin( currentServerInfo, newPassword, newSecurePassword, false, // Use timeout in SniOpen intervalTimer, withFailover:true ); if (_routingInfo != null) { // We are in login with failover scenation and server sent routing information // If it is read-only routing - we did not supply AppIntent=RO (it should be checked before) // If it is something else, not known yet (future server) - this client is not designed to support this. // In any case, server should not have sent the routing info. Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", _routingInfo.ServerName); throw SQL.ROR_UnexpectedRoutingInfo(this); } break; // leave the while loop -- we've successfully connected } catch (SqlException sqlex) { if (IsDoNotRetryConnectError(sqlex) || timeout.IsExpired) { // no more time to try again throw; // Caller will call LoginFailure() } if (IsConnectionDoomed) { throw; } if (1 == attemptNumber % 2) { // Check sleep interval to make sure we won't exceed the original timeout // Do this in the catch block so we can re-throw the current exception if (timeout.MillisecondsRemaining <= sleepInterval) { throw; } } // } // We only get here when we failed to connect, but are going to re-try // After trying to connect to both servers fails, sleep for a bit to prevent clogging // the network with requests, then update sleep interval for next iteration (max 1 second interval) if (1 == attemptNumber % 2) { if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval); } Thread.Sleep(sleepInterval); sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000; } // Update attempt number and target host attemptNumber++; useFailoverHost = !useFailoverHost; } // If we get here, connection/login succeeded! Just a few more checks & record-keeping // if connected to failover host, but said host doesn't have DbMirroring set up, throw an error if (useFailoverHost && null == ServerProvidedFailOverPartner) { throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase); } if (null != PoolGroupProviderInfo) { // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover // partner; save this information in _currentFailoverPartner. PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner); } CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName); }
private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnectionString options) { if (serverInfo.ExtendedServerName == null) { string host = serverInfo.UserServerName; string protocol = serverInfo.UserProtocol; serverInfo.SetDerivedNames(protocol, host); } }
private void LoginWithFailover(bool useFailoverHost, ServerInfo primaryServerInfo, string failoverHost, string newPassword, bool redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout) { long num5; if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", base.ObjectID, useFailoverHost); Bid.PutStr(primaryServerInfo.UserServerName); Bid.PutStr(", failover="); Bid.PutStr(failoverHost); Bid.PutStr("\n"); } int num = 100; string networkLibrary = base.ConnectionOptions.NetworkLibrary; ServerInfo serverInfo = new ServerInfo(connectionOptions, failoverHost); this.ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, owningObject); if (this.ServerProvidedFailOverPartner == null) { this.ResolveExtendedServerName(serverInfo, !redirectedUserInstance && (failoverHost != primaryServerInfo.UserServerName), owningObject); } if (timeout.IsInfinite) { ADP.TimerFromSeconds(15); num5 = 0L; } else { num5 = (long)(0.08f * timeout.MillisecondsRemaining); } bool flag = false; int num2 = 0; while (true) { ServerInfo info2; long milliseconds = num5 * ((num2 / 2) + 1); long millisecondsRemaining = timeout.MillisecondsRemaining; if (milliseconds > millisecondsRemaining) { milliseconds = millisecondsRemaining; } TimeoutTimer timer = TimeoutTimer.StartMillisecondsTimeout(milliseconds); if (this._parser != null) { this._parser.Disconnect(); } this._parser = new TdsParser(base.ConnectionOptions.MARS, base.ConnectionOptions.Asynchronous); if (useFailoverHost) { if (!flag) { this.FailoverPermissionDemand(); flag = true; } if ((this.ServerProvidedFailOverPartner != null) && (serverInfo.ResolvedServerName != this.ServerProvidedFailOverPartner)) { if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", base.ObjectID, this.ServerProvidedFailOverPartner); } serverInfo.SetDerivedNames(networkLibrary, this.ServerProvidedFailOverPartner); } info2 = serverInfo; } else { info2 = primaryServerInfo; } try { this.AttemptOneLogin(info2, newPassword, false, timer, owningObject); if (this._routingInfo != null) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", this._routingInfo.ServerName); throw SQL.ROR_UnexpectedRoutingInfo(); } break; } catch (SqlException exception) { if (this.IsDoNotRetryConnectError(exception) || timeout.IsExpired) { throw; } if (base.IsConnectionDoomed) { throw; } if ((1 == (num2 % 2)) && (timeout.MillisecondsRemaining <= num)) { throw; } } if (1 == (num2 % 2)) { if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", base.ObjectID, num); } Thread.Sleep(num); num = (num < 500) ? (num * 2) : 0x3e8; } num2++; useFailoverHost = !useFailoverHost; } if (useFailoverHost && (this.ServerProvidedFailOverPartner == null)) { throw SQL.InvalidPartnerConfiguration(failoverHost, base.CurrentDatabase); } if (this.PoolGroupProviderInfo != null) { this.PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, this.ServerProvidedFailOverPartner); } base.CurrentDataSource = useFailoverHost ? failoverHost : primaryServerInfo.UserServerName; }
private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnection owningObject) { if (serverInfo.ExtendedServerName == null) { string userServerName = serverInfo.UserServerName; string userProtocol = serverInfo.UserProtocol; if (aliasLookup) { TdsParserStaticMethods.AliasRegistryLookup(ref userServerName, ref userProtocol); if ((owningObject != null) && ((SqlConnectionString) owningObject.UserConnectionOptions).EnforceLocalHost) { SqlConnectionString.VerifyLocalHostAndFixup(ref userServerName, true, true); } } serverInfo.SetDerivedNames(userProtocol, userServerName); } }
private void LoginWithFailover(bool useFailoverHost, ServerInfo primaryServerInfo, string failoverHost, string newPassword, bool redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout) { long num5; if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", base.ObjectID, useFailoverHost); Bid.PutStr(primaryServerInfo.UserServerName); Bid.PutStr(", failover="); Bid.PutStr(failoverHost); Bid.PutStr("\n"); } int num = 100; string networkLibrary = base.ConnectionOptions.NetworkLibrary; ServerInfo serverInfo = new ServerInfo(connectionOptions, failoverHost); this.ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, owningObject); if (this.ServerProvidedFailOverPartner == null) { this.ResolveExtendedServerName(serverInfo, !redirectedUserInstance && (failoverHost != primaryServerInfo.UserServerName), owningObject); } if (timeout.IsInfinite) { ADP.TimerFromSeconds(15); num5 = 0L; } else { num5 = (long) (0.08f * timeout.MillisecondsRemaining); } bool flag = false; int num2 = 0; while (true) { ServerInfo info2; long milliseconds = num5 * ((num2 / 2) + 1); long millisecondsRemaining = timeout.MillisecondsRemaining; if (milliseconds > millisecondsRemaining) { milliseconds = millisecondsRemaining; } TimeoutTimer timer = TimeoutTimer.StartMillisecondsTimeout(milliseconds); if (this._parser != null) { this._parser.Disconnect(); } this._parser = new TdsParser(base.ConnectionOptions.MARS, base.ConnectionOptions.Asynchronous); if (useFailoverHost) { if (!flag) { this.FailoverPermissionDemand(); flag = true; } if ((this.ServerProvidedFailOverPartner != null) && (serverInfo.ResolvedServerName != this.ServerProvidedFailOverPartner)) { if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", base.ObjectID, this.ServerProvidedFailOverPartner); } serverInfo.SetDerivedNames(networkLibrary, this.ServerProvidedFailOverPartner); } info2 = serverInfo; } else { info2 = primaryServerInfo; } try { this.AttemptOneLogin(info2, newPassword, false, timer, owningObject); if (this._routingInfo != null) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", this._routingInfo.ServerName); throw SQL.ROR_UnexpectedRoutingInfo(); } break; } catch (SqlException exception) { if (this.IsDoNotRetryConnectError(exception) || timeout.IsExpired) { throw; } if (base.IsConnectionDoomed) { throw; } if ((1 == (num2 % 2)) && (timeout.MillisecondsRemaining <= num)) { throw; } } if (1 == (num2 % 2)) { if (Bid.AdvancedOn) { Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", base.ObjectID, num); } Thread.Sleep(num); num = (num < 500) ? (num * 2) : 0x3e8; } num2++; useFailoverHost = !useFailoverHost; } if (useFailoverHost && (this.ServerProvidedFailOverPartner == null)) { throw SQL.InvalidPartnerConfiguration(failoverHost, base.CurrentDatabase); } if (this.PoolGroupProviderInfo != null) { this.PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, this.ServerProvidedFailOverPartner); } base.CurrentDataSource = useFailoverHost ? failoverHost : primaryServerInfo.UserServerName; }