X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Flibs%2Frdbms%2Floadbalancer%2FLoadBalancer.php;h=d5e65cdddf58894343904256f6054d35a485418a;hp=c587b4214f370019c53ea9f691ca04b1d0ddfe2a;hb=a3dcadab7b1e584254d72db95cc337ac1185cbbc;hpb=046250bfc357c3b4f5c5106aa223d608ce83c203 diff --git a/includes/libs/rdbms/loadbalancer/LoadBalancer.php b/includes/libs/rdbms/loadbalancer/LoadBalancer.php index c587b4214f..d5e65cdddf 100644 --- a/includes/libs/rdbms/loadbalancer/LoadBalancer.php +++ b/includes/libs/rdbms/loadbalancer/LoadBalancer.php @@ -59,8 +59,8 @@ class LoadBalancer implements ILoadBalancer { /** @var ILoadMonitor */ private $loadMonitor; - /** @var ChronologyProtector|null */ - private $chronProt; + /** @var callable|null Callback to run before the first connection attempt */ + private $chronologyCallback; /** @var BagOStuff */ private $srvCache; /** @var WANObjectCache */ @@ -116,8 +116,8 @@ class LoadBalancer implements ILoadBalancer { /** @var bool */ private $disabled = false; - /** @var bool */ - private $chronProtInitialized = false; + /** @var bool Whether any connection has been attempted yet */ + private $connectionAttempted = false; /** @var int */ private $maxLag = self::MAX_LAG_DEFAULT; @@ -243,8 +243,8 @@ class LoadBalancer implements ILoadBalancer { : ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ); $this->agent = isset( $params['agent'] ) ? $params['agent'] : ''; - if ( isset( $params['chronologyProtector'] ) ) { - $this->chronProt = $params['chronologyProtector']; + if ( isset( $params['chronologyCallback'] ) ) { + $this->chronologyCallback = $params['chronologyCallback']; } } @@ -311,7 +311,7 @@ class LoadBalancer implements ILoadBalancer { ": server {host} is not replicating?", [ 'host' => $host ] ); unset( $loads[$i] ); } elseif ( $lag > $maxServerLag ) { - $this->replLogger->info( + $this->replLogger->debug( __METHOD__ . ": server {host} has {lag} seconds of lag (>= {maxlag})", [ 'host' => $host, 'lag' => $lag, 'maxlag' => $maxServerLag ] @@ -369,7 +369,7 @@ class LoadBalancer implements ILoadBalancer { // Scale the configured load ratios according to each server's load and state $this->getLoadMonitor()->scaleLoads( $loads, $domain ); - // Pick a server to use, accounting for weights, load, lag, and mWaitForPos + // Pick a server to use, accounting for weights, load, lag, and "waitForPos" list( $i, $laggedReplicaMode ) = $this->pickReaderIndex( $loads, $domain ); if ( $i === false ) { // Replica DB connection unsuccessful @@ -379,7 +379,7 @@ class LoadBalancer implements ILoadBalancer { if ( $this->waitForPos && $i != $this->getWriterIndex() ) { // Before any data queries are run, wait for the server to catch up to the // specified position. This is used to improve session consistency. Note that - // when LoadBalancer::waitFor() sets mWaitForPos, the waiting triggers here, + // when LoadBalancer::waitFor() sets "waitForPos", the waiting triggers here, // so update laggedReplicaMode as needed for consistency. if ( !$this->doWait( $i ) ) { $laggedReplicaMode = true; @@ -424,7 +424,7 @@ class LoadBalancer implements ILoadBalancer { } else { $i = false; if ( $this->waitForPos && $this->waitForPos->asOfTime() ) { - // ChronologyProtecter sets mWaitForPos for session consistency. + // "chronologyCallback" sets "waitForPos" for session consistency. // This triggers doWait() after connect, so it's especially good to // avoid lagged servers so as to avoid excessive delay in that method. $ago = microtime( true ) - $this->waitForPos->asOfTime(); @@ -566,16 +566,17 @@ class LoadBalancer implements ILoadBalancer { } } - /** - * @param int $i - * @return IDatabase|bool - */ - public function getAnyOpenConnection( $i ) { + public function getAnyOpenConnection( $i, $flags = 0 ) { + $autocommit = ( ( $flags & self::CONN_TRX_AUTOCOMMIT ) == self::CONN_TRX_AUTOCOMMIT ); foreach ( $this->conns as $connsByServer ) { - if ( !empty( $connsByServer[$i] ) ) { - /** @var IDatabase[] $serverConns */ - $serverConns = $connsByServer[$i]; - return reset( $serverConns ); + if ( !isset( $connsByServer[$i] ) ) { + continue; + } + + foreach ( $connsByServer[$i] as $conn ) { + if ( !$autocommit || $conn->getLBInfo( 'autoCommitOnly' ) ) { + return $conn; + } } } @@ -590,7 +591,7 @@ class LoadBalancer implements ILoadBalancer { * @return bool */ protected function doWait( $index, $open = false, $timeout = null ) { - $timeout = max( 1, $timeout ?: $this->waitTimeout ); + $timeout = max( 1, intval( $timeout ?: $this->waitTimeout ) ); // Check if we already know that the DB has reached this point $server = $this->getServerName( $index ); @@ -714,7 +715,7 @@ class LoadBalancer implements ILoadBalancer { if ( $i == self::DB_MASTER ) { $i = $this->getWriterIndex(); - } else { + } elseif ( $i == self::DB_REPLICA ) { # Try to find an available server in any the query groups (in order) foreach ( $groups as $group ) { $groupIndex = $this->getReaderIndex( $group, $domain ); @@ -848,11 +849,11 @@ class LoadBalancer implements ILoadBalancer { $domain = false; // local connection requested } - if ( !$this->chronProtInitialized && $this->chronProt ) { + if ( !$this->connectionAttempted && $this->chronologyCallback ) { $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 ); + // Load any "waitFor" positions before connecting so that doWait() is triggered + $this->connectionAttempted = true; + call_user_func( $this->chronologyCallback, $this ); } // Check if an auto-commit connection is being requested. If so, it will not reuse the @@ -1139,7 +1140,7 @@ class LoadBalancer implements ILoadBalancer { $context ); - // If all servers were busy, mLastError will contain something sensible + // If all servers were busy, "lastError" will contain something sensible throw new DBConnectionError( null, $this->lastError ); } } @@ -1172,6 +1173,14 @@ class LoadBalancer implements ILoadBalancer { return ( $name != '' ) ? $name : 'localhost'; } + public function getServerInfo( $i ) { + if ( isset( $this->servers[$i] ) ) { + return $this->servers[$i]; + } else { + return false; + } + } + public function getServerType( $i ) { return isset( $this->servers[$i]['type'] ) ? $this->servers[$i]['type'] : 'unknown'; }