X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Fdb%2FMWLBFactory.php;h=27695cc98450669c3e23bfb7526e117f57eb21d5;hp=bbb3d2f7b75adc02307991397b994be4991217bf;hb=5ecb8b3ac68de658e65fe69c6b6a1c2d8b14605f;hpb=a38af7ba26579bb3004f673e44d39710887763aa diff --git a/includes/db/MWLBFactory.php b/includes/db/MWLBFactory.php index bbb3d2f7b7..27695cc984 100644 --- a/includes/db/MWLBFactory.php +++ b/includes/db/MWLBFactory.php @@ -21,6 +21,7 @@ * @ingroup Database */ +use MediaWiki\Config\ServiceOptions; use MediaWiki\Logger\LoggerFactory; use Wikimedia\Rdbms\LBFactory; use Wikimedia\Rdbms\DatabaseDomain; @@ -34,9 +35,36 @@ abstract class MWLBFactory { /** @var array Cache of already-logged deprecation messages */ private static $loggedDeprecations = []; + /** + * TODO Make this a const when HHVM support is dropped (T192166) + * + * @var array + * @since 1.34 + */ + public static $applyDefaultConfigOptions = [ + 'DBcompress', + 'DBDefaultGroup', + 'DBmwschema', + 'DBname', + 'DBpassword', + 'DBport', + 'DBprefix', + 'DBserver', + 'DBservers', + 'DBssl', + 'DBtype', + 'DBuser', + 'DBWindowsAuthentication', + 'DebugDumpSql', + 'DebugLogFile', + 'ExternalServers', + 'SQLiteDataDir', + 'SQLMode', + ]; + /** * @param array $lbConf Config for LBFactory::__construct() - * @param Config $mainConfig Main config object from MediaWikiServices + * @param ServiceOptions $options * @param ConfiguredReadOnlyMode $readOnlyMode * @param BagOStuff $srvCace * @param BagOStuff $mainStash @@ -45,21 +73,23 @@ abstract class MWLBFactory { */ public static function applyDefaultConfig( array $lbConf, - Config $mainConfig, + ServiceOptions $options, ConfiguredReadOnlyMode $readOnlyMode, BagOStuff $srvCace, BagOStuff $mainStash, WANObjectCache $wanCache ) { + $options->assertRequiredOptions( self::$applyDefaultConfigOptions ); + global $wgCommandLineMode; - static $typesWithSchema = [ 'postgres', 'msssql' ]; + $typesWithSchema = self::getDbTypesWithSchemas(); $lbConf += [ 'localDomain' => new DatabaseDomain( - $mainConfig->get( 'DBname' ), - $mainConfig->get( 'DBmwschema' ), - $mainConfig->get( 'DBprefix' ) + $options->get( 'DBname' ), + $options->get( 'DBmwschema' ), + $options->get( 'DBprefix' ) ), 'profiler' => function ( $section ) { return Profiler::instance()->scopedProfileIn( $section ); @@ -74,7 +104,7 @@ abstract class MWLBFactory { 'cliMode' => $wgCommandLineMode, 'hostname' => wfHostname(), 'readOnlyReason' => $readOnlyMode->getReason(), - 'defaultGroup' => $mainConfig->get( 'DBDefaultGroup' ), + 'defaultGroup' => $options->get( 'DBDefaultGroup' ), ]; $serversCheck = []; @@ -82,100 +112,115 @@ abstract class MWLBFactory { // for Database classes in the relevant Installer subclass. // Such as MysqlInstaller::openConnection and PostgresInstaller::openConnectionWithParams. if ( $lbConf['class'] === Wikimedia\Rdbms\LBFactorySimple::class ) { - $httpMethod = $_SERVER['REQUEST_METHOD'] ?? null; - // T93097: hint for how file-based databases (e.g. sqlite) should go about locking. - // See https://www.sqlite.org/lang_transaction.html - // See https://www.sqlite.org/lockingv3.html#shared_lock - $isReadRequest = in_array( $httpMethod, [ 'GET', 'HEAD', 'OPTIONS', 'TRACE' ] ); - if ( isset( $lbConf['servers'] ) ) { - // Server array is already explicitly configured; leave alone - } elseif ( is_array( $mainConfig->get( 'DBservers' ) ) ) { + // Server array is already explicitly configured + } elseif ( is_array( $options->get( 'DBservers' ) ) ) { $lbConf['servers'] = []; - foreach ( $mainConfig->get( 'DBservers' ) as $i => $server ) { - if ( $server['type'] === 'sqlite' ) { - $server += [ - 'dbDirectory' => $mainConfig->get( 'SQLiteDataDir' ), - 'trxMode' => $isReadRequest ? 'DEFERRED' : 'IMMEDIATE' - ]; - } elseif ( $server['type'] === 'postgres' ) { - $server += [ - 'port' => $mainConfig->get( 'DBport' ), - // Work around the reserved word usage in MediaWiki schema - 'keywordTableMap' => [ 'user' => 'mwuser', 'text' => 'pagecontent' ] - ]; - } elseif ( $server['type'] === 'mssql' ) { - $server += [ - 'port' => $mainConfig->get( 'DBport' ), - 'useWindowsAuth' => $mainConfig->get( 'DBWindowsAuthentication' ) - ]; - } - - if ( in_array( $server['type'], $typesWithSchema, true ) ) { - $server += [ 'schema' => $mainConfig->get( 'DBmwschema' ) ]; - } - - $server += [ - 'tablePrefix' => $mainConfig->get( 'DBprefix' ), - 'flags' => DBO_DEFAULT, - 'sqlMode' => $mainConfig->get( 'SQLMode' ), - ]; - - $lbConf['servers'][$i] = $server; + foreach ( $options->get( 'DBservers' ) as $i => $server ) { + $lbConf['servers'][$i] = self::initServerInfo( $server, $options ); } } else { - $flags = DBO_DEFAULT; - $flags |= $mainConfig->get( 'DebugDumpSql' ) ? DBO_DEBUG : 0; - $flags |= $mainConfig->get( 'DBssl' ) ? DBO_SSL : 0; - $flags |= $mainConfig->get( 'DBcompress' ) ? DBO_COMPRESS : 0; - $server = [ - 'host' => $mainConfig->get( 'DBserver' ), - 'user' => $mainConfig->get( 'DBuser' ), - 'password' => $mainConfig->get( 'DBpassword' ), - 'dbname' => $mainConfig->get( 'DBname' ), - 'tablePrefix' => $mainConfig->get( 'DBprefix' ), - 'type' => $mainConfig->get( 'DBtype' ), - 'load' => 1, - 'flags' => $flags, - 'sqlMode' => $mainConfig->get( 'SQLMode' ), - 'trxMode' => $isReadRequest ? 'DEFERRED' : 'IMMEDIATE' - ]; - if ( in_array( $server['type'], $typesWithSchema, true ) ) { - $server += [ 'schema' => $mainConfig->get( 'DBmwschema' ) ]; - } - if ( $server['type'] === 'sqlite' ) { - $server[ 'dbDirectory'] = $mainConfig->get( 'SQLiteDataDir' ); - } elseif ( $server['type'] === 'postgres' ) { - $server['port'] = $mainConfig->get( 'DBport' ); - // Work around the reserved word usage in MediaWiki schema - $server['keywordTableMap'] = [ 'user' => 'mwuser', 'text' => 'pagecontent' ]; - } elseif ( $server['type'] === 'mssql' ) { - $server['port'] = $mainConfig->get( 'DBport' ); - $server['useWindowsAuth'] = $mainConfig->get( 'DBWindowsAuthentication' ); - } + $server = self::initServerInfo( + [ + 'host' => $options->get( 'DBserver' ), + 'user' => $options->get( 'DBuser' ), + 'password' => $options->get( 'DBpassword' ), + 'dbname' => $options->get( 'DBname' ), + 'type' => $options->get( 'DBtype' ), + 'load' => 1 + ], + $options + ); + + $server['flags'] |= $options->get( 'DBssl' ) ? DBO_SSL : 0; + $server['flags'] |= $options->get( 'DBcompress' ) ? DBO_COMPRESS : 0; + $lbConf['servers'] = [ $server ]; } if ( !isset( $lbConf['externalClusters'] ) ) { - $lbConf['externalClusters'] = $mainConfig->get( 'ExternalServers' ); + $lbConf['externalClusters'] = $options->get( 'ExternalServers' ); } $serversCheck = $lbConf['servers']; } elseif ( $lbConf['class'] === Wikimedia\Rdbms\LBFactoryMulti::class ) { if ( isset( $lbConf['serverTemplate'] ) ) { if ( in_array( $lbConf['serverTemplate']['type'], $typesWithSchema, true ) ) { - $lbConf['serverTemplate']['schema'] = $mainConfig->get( 'DBmwschema' ); + $lbConf['serverTemplate']['schema'] = $options->get( 'DBmwschema' ); } - $lbConf['serverTemplate']['sqlMode'] = $mainConfig->get( 'SQLMode' ); + $lbConf['serverTemplate']['sqlMode'] = $options->get( 'SQLMode' ); } - $serversCheck = $lbConf['serverTemplate'] ?? []; + $serversCheck = [ $lbConf['serverTemplate'] ] ?? []; } - self::sanityCheckServerConfig( $serversCheck, $mainConfig ); - $lbConf = self::applyDefaultCaching( $lbConf, $srvCace, $mainStash, $wanCache ); + self::assertValidServerConfigs( $serversCheck, $options->get( 'DBname' ), + $options->get( 'DBprefix' ) ); + + $lbConf = self::injectObjectCaches( $lbConf, $srvCace, $mainStash, $wanCache ); return $lbConf; } + /** + * @return array + */ + private static function getDbTypesWithSchemas() { + return [ 'postgres', 'msssql' ]; + } + + /** + * @param array $server + * @param ServiceOptions $options + * @return array + */ + private static function initServerInfo( array $server, ServiceOptions $options ) { + if ( $server['type'] === 'sqlite' ) { + $httpMethod = $_SERVER['REQUEST_METHOD'] ?? null; + // T93097: hint for how file-based databases (e.g. sqlite) should go about locking. + // See https://www.sqlite.org/lang_transaction.html + // See https://www.sqlite.org/lockingv3.html#shared_lock + $isHttpRead = in_array( $httpMethod, [ 'GET', 'HEAD', 'OPTIONS', 'TRACE' ] ); + $server += [ + 'dbDirectory' => $options->get( 'SQLiteDataDir' ), + 'trxMode' => $isHttpRead ? 'DEFERRED' : 'IMMEDIATE' + ]; + } elseif ( $server['type'] === 'postgres' ) { + $server += [ + 'port' => $options->get( 'DBport' ), + // Work around the reserved word usage in MediaWiki schema + 'keywordTableMap' => [ 'user' => 'mwuser', 'text' => 'pagecontent' ] + ]; + } elseif ( $server['type'] === 'oracle' ) { + $server += [ + // Work around the reserved word usage in MediaWiki schema + 'keywordTableMap' => [ 'user' => 'mwuser', 'text' => 'pagecontent' ] + ]; + } elseif ( $server['type'] === 'mssql' ) { + $server += [ + 'port' => $options->get( 'DBport' ), + 'useWindowsAuth' => $options->get( 'DBWindowsAuthentication' ) + ]; + } + + if ( in_array( $server['type'], self::getDbTypesWithSchemas(), true ) ) { + $server += [ 'schema' => $options->get( 'DBmwschema' ) ]; + } + + $flags = DBO_DEFAULT; + $flags |= $options->get( 'DebugDumpSql' ) ? DBO_DEBUG : 0; + $flags |= $options->get( 'DebugLogFile' ) ? DBO_DEBUG : 0; + if ( $server['type'] === 'oracle' ) { + $flags |= $options->get( 'DBOracleDRCP' ) ? DBO_PERSISTENT : 0; + } + + $server += [ + 'tablePrefix' => $options->get( 'DBprefix' ), + 'flags' => $flags, + 'sqlMode' => $options->get( 'SQLMode' ), + ]; + + return $server; + } + /** * @param array $lbConf * @param BagOStuff $sCache @@ -183,7 +228,7 @@ abstract class MWLBFactory { * @param WANObjectCache $wCache * @return array */ - private static function applyDefaultCaching( + private static function injectObjectCaches( array $lbConf, BagOStuff $sCache, BagOStuff $mStash, WANObjectCache $wCache ) { // Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804) @@ -202,12 +247,10 @@ abstract class MWLBFactory { /** * @param array $servers - * @param Config $mainConfig + * @param string $ldDB Local domain database name + * @param string $ldTP Local domain prefix */ - private static function sanityCheckServerConfig( array $servers, Config $mainConfig ) { - $ldDB = $mainConfig->get( 'DBname' ); // local domain DB - $ldTP = $mainConfig->get( 'DBprefix' ); // local domain prefix - + private static function assertValidServerConfigs( array $servers, $ldDB, $ldTP ) { foreach ( $servers as $server ) { $type = $server['type'] ?? null; $srvDB = $server['dbname'] ?? null; // server DB @@ -319,8 +362,17 @@ abstract class MWLBFactory { return $class; } - public static function setSchemaAliases( LBFactory $lbFactory, Config $config ) { - if ( $config->get( 'DBtype' ) === 'mysql' ) { + /** + * @param LBFactory $lbFactory + * @param string $dbType 'mysql', 'sqlite', etc. + */ + public static function setSchemaAliases( LBFactory $lbFactory, $dbType ) { + if ( $dbType instanceof Config ) { + // Before 1.34 this took a whole Config just to get $dbType + wfDeprecated( __METHOD__ . ' with Config argument', '1.34' ); + $dbType = $dbType->get( 'DBtype' ); + } + if ( $dbType === 'mysql' ) { /** * When SQLite indexes were introduced in r45764, it was noted that * SQLite requires index names to be unique within the whole database,