From cafcb6b2258a10746409135037baa9ac4ab6089e Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Thu, 31 Jul 2014 23:11:34 -0700 Subject: [PATCH] Vastly increase how long wfWaitForSlaves() can block in CLI mode * All maintenance scripts pretty much assumed this behavior, but it was not actually the case. This can avoid some massive lag problems. Change-Id: I5894409d6abade16afd8144f6689c2aff3fa7327 --- includes/GlobalFunctions.php | 9 ++++++--- includes/db/Database.php | 2 +- includes/db/LoadBalancer.php | 20 ++++++++++++++------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index 7d54dbcfa0..4c2b7725c6 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -3752,6 +3752,7 @@ function wfGetNull() { * @param float|null $ifWritesSince Only wait if writes were done since this UNIX timestamp * @param string|bool $wiki Wiki identifier accepted by wfGetLB * @param string|bool $cluster Cluster name accepted by LBFactory. Default: false. + * @return bool Success (able to connect and no timeouts reached) */ function wfWaitForSlaves( $ifWritesSince = false, $wiki = false, $cluster = false ) { // B/C: first argument used to be "max seconds of lag"; ignore such values @@ -3767,19 +3768,21 @@ function wfWaitForSlaves( $ifWritesSince = false, $wiki = false, $cluster = fals // Prevents permission error when getting master position if ( $lb->getServerCount() > 1 ) { if ( $ifWritesSince && !$lb->hasMasterConnection() ) { - return; // assume no writes done + return true; // assume no writes done } $dbw = $lb->getConnection( DB_MASTER, array(), $wiki ); if ( $ifWritesSince && $dbw->lastDoneWrites() < $ifWritesSince ) { - return; // no writes since the last wait + return true; // no writes since the last wait } $pos = $dbw->getMasterPos(); // The DBMS may not support getMasterPos() or the whole // load balancer might be fake (e.g. $wgAllDBsAreLocalhost). if ( $pos !== false ) { - $lb->waitForAll( $pos ); + return $lb->waitForAll( $pos, PHP_SAPI === 'cli' ? 86400 : null ); } } + + return true; } /** diff --git a/includes/db/Database.php b/includes/db/Database.php index 85f042007f..df19a499c2 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -3211,7 +3211,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType { * @param DBMasterPos $pos * @param int $timeout The maximum number of seconds to wait for * synchronisation - * @return int Zzero if the slave was past that position already, + * @return int Zero if the slave was past that position already, * greater than zero if we waited for some period of time, less than * zero if we timed out. */ diff --git a/includes/db/LoadBalancer.php b/includes/db/LoadBalancer.php index 0379e8627b..db4ed602b6 100644 --- a/includes/db/LoadBalancer.php +++ b/includes/db/LoadBalancer.php @@ -331,17 +331,23 @@ class LoadBalancer { /** * Set the master wait position and wait for ALL slaves to catch up to it * @param DBMasterPos $pos + * @param int $timeout Max seconds to wait; default is mWaitTimeout + * @return bool Success (able to connect and no timeouts reached) */ - public function waitForAll( $pos ) { + public function waitForAll( $pos, $timeout = null ) { wfProfileIn( __METHOD__ ); $this->mWaitForPos = $pos; $serverCount = count( $this->mServers ); + + $ok = true; for ( $i = 1; $i < $serverCount; $i++ ) { if ( $this->mLoads[$i] > 0 ) { - $this->doWait( $i, true ); + $ok = $this->doWait( $i, true, $timeout ) && $ok; } } wfProfileOut( __METHOD__ ); + + return $ok; } /** @@ -363,11 +369,12 @@ class LoadBalancer { /** * Wait for a given slave to catch up to the master pos stored in $this - * @param int $index - * @param bool $open + * @param int $index Server index + * @param bool $open Check the server even if a new connection has to be made + * @param int $timeout Max seconds to wait; default is mWaitTimeout * @return bool */ - protected function doWait( $index, $open = false ) { + protected function doWait( $index, $open = false, $timeout = null ) { # Find a connection to wait on $conn = $this->getAnyOpenConnection( $index ); if ( !$conn ) { @@ -386,7 +393,8 @@ class LoadBalancer { } wfDebug( __METHOD__ . ": Waiting for slave #$index to catch up...\n" ); - $result = $conn->masterPosWait( $this->mWaitForPos, $this->mWaitTimeout ); + $timeout = $timeout ?: $this->mWaitTimeout; + $result = $conn->masterPosWait( $this->mWaitForPos, $timeout ); if ( $result == -1 || is_null( $result ) ) { # Timed out waiting for slave, use master instead -- 2.20.1