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
This commit is contained in:
Aaron Schulz 2014-07-31 23:11:34 -07:00
parent 5c74148ba3
commit cafcb6b225
3 changed files with 21 additions and 10 deletions

View file

@ -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;
}
/**

View file

@ -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.
*/

View file

@ -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