* @ingroup Database
*/
class LoadBalancer implements ILoadBalancer {
- /** @var array[] Map of (server index => server config array) */
- private $servers;
+ /** @var ILoadMonitor */
+ private $loadMonitor;
+ /** @var callable|null Callback to run before the first connection attempt */
+ private $chronologyCallback;
+ /** @var BagOStuff */
+ private $srvCache;
+ /** @var WANObjectCache */
+ private $wanCache;
+ /** @var object|string Class name or object With profileIn/profileOut methods */
+ private $profiler;
+ /** @var TransactionProfiler */
+ private $trxProfiler;
+ /** @var LoggerInterface */
+ private $replLogger;
+ /** @var LoggerInterface */
+ private $connLogger;
+ /** @var LoggerInterface */
+ private $queryLogger;
+ /** @var LoggerInterface */
+ private $perfLogger;
+ /** @var callable Exception logger */
+ private $errorLogger;
+ /** @var callable Deprecation logger */
+ private $deprecationLogger;
+
+ /** @var DatabaseDomain Local Domain ID and default for selectDB() calls */
+ private $localDomain;
+
/** @var Database[][][] Map of (connection category => server index => IDatabase[]) */
private $conns;
+
+ /** @var array[] Map of (server index => server config array) */
+ private $servers;
/** @var float[] Map of (server index => weight) */
private $loads;
/** @var array[] Map of (group => server index => weight) */
private $waitTimeout;
/** @var array The LoadMonitor configuration */
private $loadMonitorConfig;
+ /** @var string Alternate ID string for the domain instead of DatabaseDomain::getId() */
+ private $localDomainIdAlias;
+ /** @var int */
+ private $maxLag = self::MAX_LAG_DEFAULT;
+
+ /** @var string Current server name */
+ private $hostname;
+ /** @var bool Whether this PHP instance is for a CLI script */
+ private $cliMode;
+ /** @var string Agent name for query profiling */
+ private $agent;
+
/** @var array[] $aliases Map of (table => (dbname, schema, prefix) map) */
private $tableAliases = [];
/** @var string[] Map of (index alias => index) */
private $indexAliases = [];
-
- /** @var ILoadMonitor */
- private $loadMonitor;
- /** @var callable|null Callback to run before the first connection attempt */
- private $chronologyCallback;
- /** @var BagOStuff */
- private $srvCache;
- /** @var WANObjectCache */
- private $wanCache;
- /** @var object|string Class name or object With profileIn/profileOut methods */
- protected $profiler;
- /** @var TransactionProfiler */
- protected $trxProfiler;
- /** @var LoggerInterface */
- protected $replLogger;
- /** @var LoggerInterface */
- protected $connLogger;
- /** @var LoggerInterface */
- protected $queryLogger;
- /** @var LoggerInterface */
- protected $perfLogger;
+ /** @var array[] Map of (name => callable) */
+ private $trxRecurringCallbacks = [];
/** @var Database DB connection object that caused a problem */
private $errorConnection;
private $readOnlyReason = false;
/** @var int Total connections opened */
private $connsOpened = 0;
- /** @var string|bool String if a requested DBO_TRX transaction round is active */
- private $trxRoundId = false;
- /** @var array[] Map of (name => callable) */
- private $trxRecurringCallbacks = [];
- /** @var DatabaseDomain Local Domain ID and default for selectDB() calls */
- private $localDomain;
- /** @var string Alternate ID string for the domain instead of DatabaseDomain::getId() */
- private $localDomainIdAlias;
- /** @var string Current server name */
- private $host;
- /** @var bool Whether this PHP instance is for a CLI script */
- protected $cliMode;
- /** @var string Agent name for query profiling */
- protected $agent;
-
- /** @var callable Exception logger */
- private $errorLogger;
- /** @var callable Deprecation logger */
- private $deprecationLogger;
-
/** @var bool */
private $disabled = false;
/** @var bool Whether any connection has been attempted yet */
private $connectionAttempted = false;
- /** @var int */
- private $maxLag = self::MAX_LAG_DEFAULT;
+
+ /** @var string|bool String if a requested DBO_TRX transaction round is active */
+ private $trxRoundId = false;
/** @var string Stage of the current transaction round in the transaction round life-cycle */
private $trxRoundStage = self::ROUND_CURSORY;
+ /** @var string|null */
+ private $defaultGroup = null;
+
/** @var int Warn when this many connection are held */
const CONN_HELD_WARN_THRESHOLD = 10;
$this->$key = $params[$key] ?? new NullLogger();
}
- $this->host = $params['hostname'] ?? ( gethostname() ?: 'unknown' );
+ $this->hostname = $params['hostname'] ?? ( gethostname() ?: 'unknown' );
$this->cliMode = $params['cliMode'] ?? ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' );
$this->agent = $params['agent'] ?? '';
$this->trxRoundStage = self::ROUND_ROLLBACK_CALLBACKS;
}
}
+
+ $this->defaultGroup = $params['defaultGroup'] ?? null;
}
- /**
- * Get the local (and default) database domain ID of connection handles
- *
- * @see DatabaseDomain
- * @return string Database domain ID; this specifies DB name, schema, and table prefix
- * @since 1.31
- */
public function getLocalDomainID() {
return $this->localDomain->getId();
}
+ public function resolveDomainID( $domain ) {
+ return ( $domain !== false ) ? (string)$domain : $this->getLocalDomainID();
+ }
+
/**
* Get a LoadMonitor instance
*
* Wait for a given replica DB to catch up to the master pos stored in $this
* @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 "waitTimeout" given to __construct()
+ * @param int|null $timeout Max seconds to wait; default is "waitTimeout" given to __construct()
* @return bool
*/
protected function doWait( $index, $open = false, $timeout = null ) {
}
}
+ // Check one "group" per default: the generic pool
+ $defaultGroups = $this->defaultGroup ? [ $this->defaultGroup ] : [ false ];
+
$groups = ( $groups === false || $groups === [] )
- ? [ false ] // check one "group": the generic pool
+ ? $defaultGroups
: (array)$groups;
$masterOnly = ( $i == self::DB_MASTER || $i == $this->getWriterIndex() );
}
public function getConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
- $domain = ( $domain !== false ) ? $domain : $this->localDomain;
+ $domain = $this->resolveDomainID( $domain );
return new DBConnRef( $this, $this->getConnection( $db, $groups, $domain, $flags ) );
}
public function getLazyConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
- $domain = ( $domain !== false ) ? $domain : $this->localDomain;
+ $domain = $this->resolveDomainID( $domain );
return new DBConnRef( $this, [ $db, $groups, $domain, $flags ] );
}
public function getMaintenanceConnectionRef( $db, $groups = [], $domain = false, $flags = 0 ) {
- $domain = ( $domain !== false ) ? $domain : $this->localDomain;
+ $domain = $this->resolveDomainID( $domain );
return new MaintainableDBConnRef(
$this, $this->getConnection( $db, $groups, $domain, $flags ) );
$this->connLogger->debug( __METHOD__ . ': calling initLB() before first connection.' );
// Load any "waitFor" positions before connecting so that doWait() is triggered
$this->connectionAttempted = true;
- call_user_func( $this->chronologyCallback, $this );
+ ( $this->chronologyCallback )( $this );
}
// Check if an auto-commit connection is being requested. If so, it will not reuse the
$oldDomain = key( $this->conns[$connFreeKey][$i] );
if ( strlen( $dbName ) && !$conn->selectDB( $dbName ) ) {
$this->lastError = "Error selecting database '$dbName' on server " .
- $conn->getServer() . " from client host {$this->host}";
+ $conn->getServer() . " from client host {$this->hostname}";
$this->errorConnection = $conn;
$conn = false;
} else {
try {
$conn->commit( $fname, $conn::FLUSHING_ALL_PEERS );
} catch ( DBError $e ) {
- call_user_func( $this->errorLogger, $e );
+ ( $this->errorLogger )( $e );
$failures[] = "{$conn->getServer()}: {$e->getMessage()}";
}
}
foreach ( $this->conns as $connsByServer ) {
foreach ( $connsByServer as $serverConns ) {
foreach ( $serverConns as $conn ) {
- $mergedParams = array_merge( [ $conn ], $params );
- call_user_func_array( $callback, $mergedParams );
+ $callback( $conn, ...$params );
}
}
}
if ( isset( $connsByServer[$masterIndex] ) ) {
/** @var IDatabase $conn */
foreach ( $connsByServer[$masterIndex] as $conn ) {
- $mergedParams = array_merge( [ $conn ], $params );
- call_user_func_array( $callback, $mergedParams );
+ $callback( $conn, ...$params );
}
}
}
continue; // skip master
}
foreach ( $serverConns as $conn ) {
- $mergedParams = array_merge( [ $conn ], $params );
- call_user_func_array( $callback, $mergedParams );
+ $callback( $conn, ...$params );
}
}
}