Merge "Fix default handling in LoadBalancer::getRandomNonLagged()"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 6 Sep 2016 18:46:41 +0000 (18:46 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 6 Sep 2016 18:46:41 +0000 (18:46 +0000)
1  2 
includes/db/loadbalancer/LoadBalancer.php

@@@ -78,7 -78,7 +78,7 @@@ class LoadBalancer 
        /** @var integer Warn when this many connection are held */
        const CONN_HELD_WARN_THRESHOLD = 10;
        /** @var integer Default 'max lag' when unspecified */
-       const MAX_LAG = 10;
+       const MAX_LAG_DEFAULT = 10;
        /** @var integer Max time to wait for a replica DB to catch up (e.g. ChronologyProtector) */
        const POS_WAIT_TIMEOUT = 10;
        /** @var integer Seconds to cache master server read-only status */
         * @param int $maxLag Restrict the maximum allowed lag to this many seconds
         * @return bool|int|string
         */
-       private function getRandomNonLagged( array $loads, $wiki = false, $maxLag = self::MAX_LAG ) {
+       private function getRandomNonLagged( array $loads, $wiki = false, $maxLag = INF ) {
                $lags = $this->getLagTimes( $wiki );
  
                # Unset excessively lagged servers
                foreach ( $lags as $i => $lag ) {
                        if ( $i != 0 ) {
-                               $maxServerLag = $maxLag;
-                               if ( isset( $this->mServers[$i]['max lag'] ) ) {
-                                       $maxServerLag = min( $maxServerLag, $this->mServers[$i]['max lag'] );
-                               }
+                               # How much lag this server nominally is allowed to have
+                               $maxServerLag = isset( $this->mServers[$i]['max lag'] )
+                                       ? $this->mServers[$i]['max lag']
+                                       : self::MAX_LAG_DEFAULT; // default
+                               # Constrain that futher by $maxLag argument
+                               $maxServerLag = min( $maxServerLag, $maxLag );
  
                                $host = $this->getServerName( $i );
-                               if ( $lag === false ) {
+                               if ( $lag === false && !is_infinite( $maxServerLag ) ) {
                                        wfDebugLog( 'replication', "Server $host (#$i) is not replicating?" );
                                        unset( $loads[$i] );
                                } elseif ( $lag > $maxServerLag ) {
  
                # No server found yet
                $i = false;
 -              $conn = false;
                # First try quickly looking through the available servers for a server that
                # meets our criteria
                $currentLoads = $nonErrorLoads;
                        # Replica DB connection successful.
                        # Wait for the session master pos for a short time.
                        if ( $this->mWaitForPos && $i > 0 ) {
 -                              if ( !$this->doWait( $i ) ) {
 -                                      $this->mServers[$i]['slave pos'] = $conn->getSlavePos();
 -                              }
 +                              $this->doWait( $i );
                        }
                        if ( $this->mReadIndex <= 0 && $this->mLoads[$i] > 0 && $group === false ) {
                                $this->mReadIndex = $i;
  
        /**
         * Set the master wait position
 -       * If a DB_SLAVE connection has been opened already, waits
 +       * If a DB_REPLICA connection has been opened already, waits
         * Otherwise sets a variable telling it to wait if such a connection is opened
         * @param DBMasterPos $pos
         */
  
                if ( $i > 0 ) {
                        if ( !$this->doWait( $i ) ) {
 -                              $this->mServers[$i]['slave pos'] = $this->getAnyOpenConnection( $i )->getSlavePos();
                                $this->laggedReplicaMode = true;
                        }
                }
                }
  
                # Operation-based index
 -              if ( $i == DB_SLAVE ) {
 +              if ( $i == DB_REPLICA ) {
                        $this->mLastError = 'Unknown error'; // reset error string
                        # Try the general server pool if $groups are unavailable.
                        $i = in_array( false, $groups, true )
                        /**
                         * This can happen in code like:
                         *   foreach ( $dbs as $db ) {
 -                       *     $conn = $lb->getConnection( DB_SLAVE, [], $db );
 +                       *     $conn = $lb->getConnection( DB_REPLICA, [], $db );
                         *     ...
                         *     $lb->reuseConnection( $conn );
                         *   }
  
        /**
         * @note This method will trigger a DB connection if not yet done
 -       *
         * @param string|bool $wiki Wiki ID, or false for the current wiki
         * @return bool Whether the generic connection for reads is highly "lagged"
         */
 -      public function getLaggedSlaveMode( $wiki = false ) {
 +      public function getLaggedReplicaMode( $wiki = false ) {
                // No-op if there is only one DB (also avoids recursion)
                if ( !$this->laggedReplicaMode && $this->getServerCount() > 1 ) {
                        try {
                                // See if laggedReplicaMode gets set
 -                              $conn = $this->getConnection( DB_SLAVE, false, $wiki );
 +                              $conn = $this->getConnection( DB_REPLICA, false, $wiki );
                                $this->reuseConnection( $conn );
                        } catch ( DBConnectionError $e ) {
                                // Avoid expensive re-connect attempts and failures
                return $this->laggedReplicaMode;
        }
  
 +      /**
 +       * @param bool $wiki
 +       * @return bool
 +       * @deprecated 1.28; use getLaggedReplicaMode()
 +       */
 +      public function getLaggedSlaveMode( $wiki = false ) {
 +              return $this->getLaggedReplicaMode( $wiki );
 +      }
 +
        /**
         * @note This method will never cause a new DB connection
         * @return bool Whether any generic connection used for reads was highly "lagged"
 +       * @since 1.28
 +       */
 +      public function laggedReplicaUsed() {
 +              return $this->laggedReplicaMode;
 +      }
 +
 +      /**
 +       * @return bool
         * @since 1.27
 +       * @deprecated Since 1.28; use laggedReplicaUsed()
         */
        public function laggedSlaveUsed() {
 -              return $this->laggedReplicaMode;
 +              return $this->laggedReplicaUsed();
        }
  
        /**
        public function getReadOnlyReason( $wiki = false, DatabaseBase $conn = null ) {
                if ( $this->readOnlyReason !== false ) {
                        return $this->readOnlyReason;
 -              } elseif ( $this->getLaggedSlaveMode( $wiki ) ) {
 +              } elseif ( $this->getLaggedReplicaMode( $wiki ) ) {
                        if ( $this->allReplicasDownMode ) {
                                return 'The database has been automatically locked ' .
                                        'until the replica database servers become available';
         * @since 1.27
         */
        public function safeWaitForMasterPos( IDatabase $conn, $pos = false, $timeout = 10 ) {
 -              if ( $this->getServerCount() == 1 || !$conn->getLBInfo( 'slave' ) ) {
 +              if ( $this->getServerCount() == 1 || !$conn->getLBInfo( 'replica' ) ) {
                        return true; // server is not a replica DB
                }