Merge "Add some common functions to BaseTemplate"
[lhc/web/wiklou.git] / includes / libs / rdbms / loadbalancer / LoadBalancer.php
index 6878712..d178657 100644 (file)
@@ -25,10 +25,7 @@ namespace Wikimedia\Rdbms;
 use Psr\Log\LoggerInterface;
 use Psr\Log\NullLogger;
 use Wikimedia\ScopedCallback;
-use IDatabase;
 use Database;
-use DBConnRef;
-use MaintainableDBConnRef;
 use BagOStuff;
 use EmptyBagOStuff;
 use WANObjectCache;
@@ -69,6 +66,8 @@ class LoadBalancer implements ILoadBalancer {
 
        /** @var ILoadMonitor */
        private $loadMonitor;
+       /** @var ChronologyProtector|null */
+       private $chronProt;
        /** @var BagOStuff */
        private $srvCache;
        /** @var BagOStuff */
@@ -124,6 +123,8 @@ class LoadBalancer implements ILoadBalancer {
 
        /** @var boolean */
        private $disabled = false;
+       /** @var boolean */
+       private $chronProtInitialized = false;
 
        /** @var integer Warn when this many connection are held */
        const CONN_HELD_WARN_THRESHOLD = 10;
@@ -222,6 +223,10 @@ class LoadBalancer implements ILoadBalancer {
                        : ( gethostname() ?: 'unknown' );
                $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : PHP_SAPI === 'cli';
                $this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
+
+               if ( isset( $params['chronologyProtector'] ) ) {
+                       $this->chronProt = $params['chronologyProtector'];
+               }
        }
 
        /**
@@ -424,21 +429,24 @@ class LoadBalancer implements ILoadBalancer {
                return $i;
        }
 
-       /**
-        * @param DBMasterPos|false $pos
-        */
        public function waitFor( $pos ) {
+               $oldPos = $this->mWaitForPos;
                $this->mWaitForPos = $pos;
-               $i = $this->mReadIndex;
 
+               // If a generic reader connection was already established, then wait now
+               $i = $this->mReadIndex;
                if ( $i > 0 ) {
                        if ( !$this->doWait( $i ) ) {
                                $this->laggedReplicaMode = true;
                        }
                }
+
+               // Restore the older position if it was higher
+               $this->setWaitForPositionIfHigher( $oldPos );
        }
 
        public function waitForOne( $pos, $timeout = null ) {
+               $oldPos = $this->mWaitForPos;
                $this->mWaitForPos = $pos;
 
                $i = $this->mReadIndex;
@@ -456,10 +464,14 @@ class LoadBalancer implements ILoadBalancer {
                        $ok = true; // no applicable loads
                }
 
+               // Restore the older position if it was higher
+               $this->setWaitForPositionIfHigher( $oldPos );
+
                return $ok;
        }
 
        public function waitForAll( $pos, $timeout = null ) {
+               $oldPos = $this->mWaitForPos;
                $this->mWaitForPos = $pos;
                $serverCount = count( $this->mServers );
 
@@ -470,9 +482,25 @@ class LoadBalancer implements ILoadBalancer {
                        }
                }
 
+               // Restore the older position if it was higher
+               $this->setWaitForPositionIfHigher( $oldPos );
+
                return $ok;
        }
 
+       /**
+        * @param DBMasterPos|bool $pos
+        */
+       private function setWaitForPositionIfHigher( $pos ) {
+               if ( !$pos ) {
+                       return;
+               }
+
+               if ( !$this->mWaitForPos || $pos->hasReached( $this->mWaitForPos ) ) {
+                       $this->mWaitForPos = $pos;
+               }
+       }
+
        /**
         * @param int $i
         * @return IDatabase|bool
@@ -718,6 +746,13 @@ class LoadBalancer implements ILoadBalancer {
                        $domain = false; // local connection requested
                }
 
+               if ( !$this->chronProtInitialized && $this->chronProt ) {
+                       $this->connLogger->debug( __METHOD__ . ': calling initLB() before first connection.' );
+                       // Load CP positions before connecting so that doWait() triggers later if needed
+                       $this->chronProtInitialized = true;
+                       $this->chronProt->initLB( $this );
+               }
+
                if ( $domain !== false ) {
                        $conn = $this->openForeignConnection( $i, $domain );
                } elseif ( isset( $this->mConns['local'][$i][0] ) ) {