$this->maxLag = $params['maxLag'];
}
- if ( isset( $params['loadMonitor'] ) ) {
- $this->loadMonitorConfig = $params['loadMonitor'];
- } else {
- $this->loadMonitorConfig = [ 'class' => 'LoadMonitorNull' ];
- }
+ $this->loadMonitorConfig = $params['loadMonitor'] ?? [ 'class' => 'LoadMonitorNull' ];
$this->loadMonitorConfig += [ 'lagWarnThreshold' => $this->maxLag ];
foreach ( $params['servers'] as $i => $server ) {
}
}
- if ( isset( $params['srvCache'] ) ) {
- $this->srvCache = $params['srvCache'];
- } else {
- $this->srvCache = new EmptyBagOStuff();
- }
- if ( isset( $params['wanCache'] ) ) {
- $this->wanCache = $params['wanCache'];
- } else {
- $this->wanCache = WANObjectCache::newEmpty();
- }
+ $this->srvCache = $params['srvCache'] ?? new EmptyBagOStuff();
+ $this->wanCache = $params['wanCache'] ?? WANObjectCache::newEmpty();
$this->profiler = $params['profiler'] ?? null;
- if ( isset( $params['trxProfiler'] ) ) {
- $this->trxProfiler = $params['trxProfiler'];
- } else {
- $this->trxProfiler = new TransactionProfiler();
- }
+ $this->trxProfiler = $params['trxProfiler'] ?? new TransactionProfiler();
$this->errorLogger = $params['errorLogger'] ?? function ( Exception $e ) {
trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_USER_WARNING );
": 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 ]
}
/** @var Database $conn */
+ $conn = null;
+
if ( isset( $this->conns[$connInUseKey][$i][$domain] ) ) {
// Reuse an in-use connection for the same domain
$conn = $this->conns[$connInUseKey][$i][$domain];
$this->conns[$connInUseKey][$i][$domain] = $conn;
$this->connLogger->debug( __METHOD__ . ": reusing free connection $i/$domain" );
} elseif ( !empty( $this->conns[$connFreeKey][$i] ) ) {
- // Reuse a free connection from another domain
- $conn = reset( $this->conns[$connFreeKey][$i] );
- $oldDomain = key( $this->conns[$connFreeKey][$i] );
- if ( $domainInstance->getDatabase() !== null ) {
- $conn->selectDomain( $domainInstance );
- } else {
- // Stay on the current database, but update the schema/prefix
- $conn->dbSchema( $domainInstance->getSchema() );
- $conn->tablePrefix( $domainInstance->getTablePrefix() );
+ // Reuse a free connection from another domain if possible
+ foreach ( $this->conns[$connFreeKey][$i] as $oldDomain => $conn ) {
+ if ( $domainInstance->getDatabase() !== null ) {
+ // Check if changing the database will require a new connection.
+ // In that case, leave the connection handle alone and keep looking.
+ // This prevents connections from being closed mid-transaction and can
+ // also avoid overhead if the same database will later be requested.
+ if (
+ $conn->databasesAreIndependent() &&
+ $conn->getDBname() !== $domainInstance->getDatabase()
+ ) {
+ continue;
+ }
+ // Select the new database, schema, and prefix
+ $conn->selectDomain( $domainInstance );
+ } else {
+ // Stay on the current database, but update the schema/prefix
+ $conn->dbSchema( $domainInstance->getSchema() );
+ $conn->tablePrefix( $domainInstance->getTablePrefix() );
+ }
+ unset( $this->conns[$connFreeKey][$i][$oldDomain] );
+ // Note that if $domain is an empty string, getDomainID() might not match it
+ $this->conns[$connInUseKey][$i][$conn->getDomainId()] = $conn;
+ $this->connLogger->debug( __METHOD__ .
+ ": reusing free connection from $oldDomain for $domain" );
+ break;
}
- unset( $this->conns[$connFreeKey][$i][$oldDomain] );
- // Note that if $domain is an empty string, getDomainID() might not match it
- $this->conns[$connInUseKey][$i][$conn->getDomainId()] = $conn;
- $this->connLogger->debug( __METHOD__ .
- ": reusing free connection from $oldDomain for $domain" );
- } else {
+ }
+
+ if ( !$conn ) {
if ( !isset( $this->servers[$i] ) || !is_array( $this->servers[$i] ) ) {
throw new InvalidArgumentException( "No server with index '$i'." );
}
}
public function getServerName( $i ) {
- if ( isset( $this->servers[$i]['hostName'] ) ) {
- $name = $this->servers[$i]['hostName'];
- } elseif ( isset( $this->servers[$i]['host'] ) ) {
- $name = $this->servers[$i]['host'];
- } else {
- $name = '';
- }
+ $name = $this->servers[$i]['hostName'] ?? $this->servers[$i]['host'] ?? '';
return ( $name != '' ) ? $name : 'localhost';
}
public function getServerInfo( $i ) {
- if ( isset( $this->servers[$i] ) ) {
- return $this->servers[$i];
- } else {
- return false;
- }
+ return $this->servers[$i] ?? false;
}
public function getServerType( $i ) {
}
public function closeConnection( IDatabase $conn ) {
+ if ( $conn instanceof DBConnRef ) {
+ // Avoid calling close() but still leaving the handle in the pool
+ throw new RuntimeException( __METHOD__ . ': got DBConnRef instance.' );
+ }
+
$serverIndex = $conn->getLBInfo( 'serverIndex' );
foreach ( $this->conns as $type => $connsByServer ) {
if ( !isset( $connsByServer[$serverIndex] ) ) {
$failures = [];
/** @noinspection PhpUnusedLocalVariableInspection */
- $scope = $this->getScopedPHPBehaviorForCommit(); // try to ignore client aborts
+ $scope = ScopedCallback::newScopedIgnoreUserAbort(); // try to ignore client aborts
$restore = ( $this->trxRoundId !== false );
$this->trxRoundId = false;
$this->indexAliases = $aliases;
}
+ /**
+ * @param string $prefix
+ * @deprecated Since 1.33
+ */
public function setDomainPrefix( $prefix ) {
+ $this->setLocalDomainPrefix( $prefix );
+ }
+
+ public function setLocalDomainPrefix( $prefix ) {
// Find connections to explicit foreign domains still marked as in-use...
$domainsInUse = [];
$this->forEachOpenConnection( function ( IDatabase $conn ) use ( &$domainsInUse ) {
} );
}
+ public function redefineLocalDomain( $domain ) {
+ $this->closeAll();
+
+ $this->setLocalDomain( DatabaseDomain::newFromId( $domain ) );
+ }
+
/**
* @param DatabaseDomain $domain
*/
}
}
- /**
- * Make PHP ignore user aborts/disconnects until the returned
- * value leaves scope. This returns null and does nothing in CLI mode.
- *
- * @return ScopedCallback|null
- */
- final protected function getScopedPHPBehaviorForCommit() {
- if ( PHP_SAPI != 'cli' ) { // https://bugs.php.net/bug.php?id=47540
- $old = ignore_user_abort( true ); // avoid half-finished operations
- return new ScopedCallback( function () use ( $old ) {
- ignore_user_abort( $old );
- } );
- }
-
- return null;
- }
-
function __destruct() {
// Avoid connection leaks for sanity
$this->disable();