Beispiel #1
0
 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);
            }
        }
Beispiel #5
0
        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;
 }