Merge "Make server index validity checks in LoadBalancer actually work"
[lhc/web/wiklou.git] / includes / libs / rdbms / loadbalancer / LoadBalancer.php
index 0c82968..083dcd6 100644 (file)
@@ -105,10 +105,9 @@ class LoadBalancer implements ILoadBalancer {
 
        /** @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_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 */
        const TTL_CACHE_READONLY = 5;
 
@@ -130,9 +129,7 @@ class LoadBalancer implements ILoadBalancer {
                        $this->localDomainIdAlias = $this->localDomain->getDatabase();
                }
 
-               $this->mWaitTimeout = isset( $params['waitTimeout'] )
-                       ? $params['waitTimeout']
-                       : self::POS_WAIT_TIMEOUT;
+               $this->mWaitTimeout = isset( $params['waitTimeout'] ) ? $params['waitTimeout'] : 10;
 
                $this->mReadIndex = -1;
                $this->mConns = [
@@ -301,7 +298,7 @@ class LoadBalancer implements ILoadBalancer {
                }
 
                # Scale the configured load ratios according to the dynamic load if supported
-               $this->getLoadMonitor()->scaleLoads( $nonErrorLoads, $group, $domain );
+               $this->getLoadMonitor()->scaleLoads( $nonErrorLoads, $domain );
 
                $laggedReplicaMode = false;
 
@@ -477,7 +474,7 @@ class LoadBalancer implements ILoadBalancer {
 
                                return false;
                        } else {
-                               $conn = $this->openConnection( $index, '' );
+                               $conn = $this->openConnection( $index, self::DOMAIN_ANY );
                                if ( !$conn ) {
                                        $this->replLogger->warning( __METHOD__ . ": failed to connect to $server" );
 
@@ -614,10 +611,17 @@ class LoadBalancer implements ILoadBalancer {
                        return;
                }
 
+               if ( $this->disabled ) {
+                       return; // DBConnRef handle probably survived longer than the LoadBalancer
+               }
+
                $domain = $conn->getDomainID();
-               if ( $this->mConns['foreignUsed'][$serverIndex][$domain] !== $conn ) {
+               if ( !isset( $this->mConns['foreignUsed'][$serverIndex][$domain] ) ) {
+                       throw new InvalidArgumentException( __METHOD__ .
+                               ": connection $serverIndex/$domain not found; it may have already been freed." );
+               } elseif ( $this->mConns['foreignUsed'][$serverIndex][$domain] !== $conn ) {
                        throw new InvalidArgumentException( __METHOD__ .
-                               ": connection not found, has the connection been freed already?" );
+                               ": connection $serverIndex/$domain mismatched; it may have already been freed." );
                }
                $conn->setLBInfo( 'foreignPoolRefCount', --$refCount );
                if ( $refCount <= 0 ) {
@@ -1448,10 +1452,15 @@ class LoadBalancer implements ILoadBalancer {
                }
 
                if ( !$pos ) {
-                       // Get the current master position
-                       $dbw = $this->getConnection( self::DB_MASTER );
-                       $pos = $dbw->getMasterPos();
-                       $this->reuseConnection( $dbw );
+                       // Get the current master position, opening a connection if needed
+                       $masterConn = $this->getAnyOpenConnection( $this->getWriterIndex() );
+                       if ( $masterConn ) {
+                               $pos = $masterConn->getMasterPos();
+                       } else {
+                               $masterConn = $this->openConnection( $this->getWriterIndex(), self::DOMAIN_ANY );
+                               $pos = $masterConn->getMasterPos();
+                               $this->closeConnection( $masterConn );
+                       }
                }
 
                if ( $pos instanceof DBMasterPos ) {
@@ -1472,10 +1481,6 @@ class LoadBalancer implements ILoadBalancer {
                return $ok;
        }
 
-       public function clearLagTimeCache() {
-               $this->getLoadMonitor()->clearCaches();
-       }
-
        public function setTransactionListener( $name, callable $callback = null ) {
                if ( $callback ) {
                        $this->trxRecurringCallbacks[$name] = $callback;
@@ -1535,6 +1540,6 @@ class LoadBalancer implements ILoadBalancer {
 
        function __destruct() {
                // Avoid connection leaks for sanity
-               $this->closeAll();
+               $this->disable();
        }
 }