Made wfReadOnly() more robust at handling the lagged-slave case
authorAaron Schulz <aschulz@wikimedia.org>
Tue, 7 Apr 2015 18:04:17 +0000 (11:04 -0700)
committerOri.livneh <ori@wikimedia.org>
Wed, 8 Apr 2015 18:41:57 +0000 (18:41 +0000)
* Previously if it was called before a DB_SLAVE connection, it would not
  be set. This is fixed now.
* Also set mLaggedSlaveMode in LoadBalancer as appropriate. Before, it
  was only set in the "too lagged for ChronologyProtector" case.

Change-Id: Ic4dc555cf762653f157df1795f53f3577c1e587a

includes/GlobalFunctions.php
includes/db/LoadBalancer.php

index 7c4ebc2..3be43b3 100644 (file)
@@ -1344,6 +1344,12 @@ function wfReadOnlyReason() {
                } else {
                        $wgReadOnly = false;
                }
+               // Callers use this method to be aware that data presented to a user
+               // may be very stale and thus allowing submissions can be problematic.
+               if ( $wgReadOnly === false && wfGetLB()->getLaggedSlaveMode() ) {
+                       $wgReadOnly = 'The database has been automatically locked ' .
+                               'while the slave database servers catch up to the master';
+               }
        }
 
        return $wgReadOnly;
index d9584e1..bc17911 100644 (file)
@@ -214,7 +214,7 @@ class LoadBalancer {
         * @return bool|int|string
         */
        public function getReaderIndex( $group = false, $wiki = false ) {
-               global $wgReadOnly, $wgDBtype;
+               global $wgDBtype;
 
                # @todo FIXME: For now, only go through all this for mysql databases
                if ( $wgDBtype != 'mysql' ) {
@@ -258,7 +258,7 @@ class LoadBalancer {
                # meets our criteria
                $currentLoads = $nonErrorLoads;
                while ( count( $currentLoads ) ) {
-                       if ( $wgReadOnly || $this->mAllowLagged || $laggedSlaveMode ) {
+                       if ( $this->mAllowLagged || $laggedSlaveMode ) {
                                $i = ArrayUtils::pickRandom( $currentLoads );
                        } else {
                                $i = false;
@@ -277,8 +277,6 @@ class LoadBalancer {
                                if ( $i === false && count( $currentLoads ) != 0 ) {
                                        # All slaves lagged. Switch to read-only mode
                                        wfDebugLog( 'replication', "All slaves lagged. Switch to read-only mode" );
-                                       $wgReadOnly = 'The database has been automatically locked ' .
-                                               'while the slave database servers catch up to the master';
                                        $i = ArrayUtils::pickRandom( $currentLoads );
                                        $laggedSlaveMode = true;
                                }
@@ -330,6 +328,10 @@ class LoadBalancer {
                        }
                        if ( $this->mReadIndex <= 0 && $this->mLoads[$i] > 0 && $group === false ) {
                                $this->mReadIndex = $i;
+                               # Record if the generic reader index is in "lagged slave" mode
+                               if ( $laggedSlaveMode ) {
+                                       $this->mLaggedSlaveMode = true;
+                               }
                        }
                        $serverName = $this->getServerName( $i );
                        wfDebug( __METHOD__ . ": using server $serverName for group '$group'\n" );
@@ -1096,9 +1098,12 @@ class LoadBalancer {
        }
 
        /**
-        * @return bool
+        * @return bool Whether the generic connection for reads is highly "lagged"
         */
        public function getLaggedSlaveMode() {
+               # Get a generic reader connection
+               $this->getConnection( DB_SLAVE );
+
                return $this->mLaggedSlaveMode;
        }