123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- <?php
- /**
- * Generator of database load balancing objects.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Database
- */
- use MediaWiki\Logger\LoggerFactory;
- use MediaWiki\MediaWikiServices;
- use Wikimedia\Rdbms\LBFactory;
- use Wikimedia\Rdbms\DatabaseDomain;
- /**
- * MediaWiki-specific class for generating database load balancers
- * @ingroup Database
- */
- abstract class MWLBFactory {
- /** @var array Cache of already-logged deprecation messages */
- private static $loggedDeprecations = [];
- /**
- * @param array $lbConf Config for LBFactory::__construct()
- * @param Config $mainConfig Main config object from MediaWikiServices
- * @param ConfiguredReadOnlyMode $readOnlyMode
- * @return array
- */
- public static function applyDefaultConfig( array $lbConf, Config $mainConfig,
- ConfiguredReadOnlyMode $readOnlyMode
- ) {
- global $wgCommandLineMode;
- static $typesWithSchema = [ 'postgres', 'msssql' ];
- $lbConf += [
- 'localDomain' => new DatabaseDomain(
- $mainConfig->get( 'DBname' ),
- $mainConfig->get( 'DBmwschema' ),
- $mainConfig->get( 'DBprefix' )
- ),
- 'profiler' => Profiler::instance(),
- 'trxProfiler' => Profiler::instance()->getTransactionProfiler(),
- 'replLogger' => LoggerFactory::getInstance( 'DBReplication' ),
- 'queryLogger' => LoggerFactory::getInstance( 'DBQuery' ),
- 'connLogger' => LoggerFactory::getInstance( 'DBConnection' ),
- 'perfLogger' => LoggerFactory::getInstance( 'DBPerformance' ),
- 'errorLogger' => [ MWExceptionHandler::class, 'logException' ],
- 'deprecationLogger' => [ static::class, 'logDeprecation' ],
- 'cliMode' => $wgCommandLineMode,
- 'hostname' => wfHostname(),
- 'readOnlyReason' => $readOnlyMode->getReason(),
- ];
- // When making changes here, remember to also specify MediaWiki-specific options
- // for Database classes in the relevant Installer subclass.
- // Such as MysqlInstaller::openConnection and PostgresInstaller::openConnectionWithParams.
- if ( $lbConf['class'] === Wikimedia\Rdbms\LBFactorySimple::class ) {
- if ( isset( $lbConf['servers'] ) ) {
- // Server array is already explicitly configured; leave alone
- } elseif ( is_array( $mainConfig->get( 'DBservers' ) ) ) {
- foreach ( $mainConfig->get( 'DBservers' ) as $i => $server ) {
- 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
- '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' ),
- 'utf8Mode' => $mainConfig->get( 'DBmysql5' )
- ];
- $lbConf['servers'][$i] = $server;
- }
- } 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' ),
- 'utf8Mode' => $mainConfig->get( 'DBmysql5' )
- ];
- 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' );
- }
- $lbConf['servers'] = [ $server ];
- }
- if ( !isset( $lbConf['externalClusters'] ) ) {
- $lbConf['externalClusters'] = $mainConfig->get( 'ExternalServers' );
- }
- } 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']['sqlMode'] = $mainConfig->get( 'SQLMode' );
- $lbConf['serverTemplate']['utf8Mode'] = $mainConfig->get( 'DBmysql5' );
- }
- }
- $services = MediaWikiServices::getInstance();
- // Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804)
- $sCache = $services->getLocalServerObjectCache();
- if ( $sCache->getQoS( $sCache::ATTR_EMULATION ) > $sCache::QOS_EMULATION_SQL ) {
- $lbConf['srvCache'] = $sCache;
- }
- $mStash = $services->getMainObjectStash();
- if ( $mStash->getQoS( $mStash::ATTR_EMULATION ) > $mStash::QOS_EMULATION_SQL ) {
- $lbConf['memStash'] = $mStash;
- }
- $wCache = $services->getMainWANObjectCache();
- if ( $wCache->getQoS( $wCache::ATTR_EMULATION ) > $wCache::QOS_EMULATION_SQL ) {
- $lbConf['wanCache'] = $wCache;
- }
- return $lbConf;
- }
- /**
- * Returns the LBFactory class to use and the load balancer configuration.
- *
- * @todo instead of this, use a ServiceContainer for managing the different implementations.
- *
- * @param array $config (e.g. $wgLBFactoryConf)
- * @return string Class name
- */
- public static function getLBFactoryClass( array $config ) {
- // For configuration backward compatibility after removing
- // underscores from class names in MediaWiki 1.23.
- $bcClasses = [
- 'LBFactory_Simple' => 'LBFactorySimple',
- 'LBFactory_Single' => 'LBFactorySingle',
- 'LBFactory_Multi' => 'LBFactoryMulti'
- ];
- $class = $config['class'];
- if ( isset( $bcClasses[$class] ) ) {
- $class = $bcClasses[$class];
- wfDeprecated(
- '$wgLBFactoryConf must be updated. See RELEASE-NOTES for details',
- '1.23'
- );
- }
- // For configuration backward compatibility after moving classes to namespaces (1.29)
- $compat = [
- 'LBFactorySingle' => Wikimedia\Rdbms\LBFactorySingle::class,
- 'LBFactorySimple' => Wikimedia\Rdbms\LBFactorySimple::class,
- 'LBFactoryMulti' => Wikimedia\Rdbms\LBFactoryMulti::class
- ];
- if ( isset( $compat[$class] ) ) {
- $class = $compat[$class];
- }
- return $class;
- }
- public static function setSchemaAliases( LBFactory $lbFactory, Config $config ) {
- if ( $config->get( 'DBtype' ) === 'mysql' ) {
- /**
- * When SQLite indexes were introduced in r45764, it was noted that
- * SQLite requires index names to be unique within the whole database,
- * not just within a schema. As discussed in CR r45819, to avoid the
- * need for a schema change on existing installations, the indexes
- * were implicitly mapped from the new names to the old names.
- *
- * This mapping can be removed if DB patches are introduced to alter
- * the relevant tables in existing installations. Note that because
- * this index mapping applies to table creation, even new installations
- * of MySQL have the old names (except for installations created during
- * a period where this mapping was inappropriately removed, see
- * T154872).
- */
- $lbFactory->setIndexAliases( [
- 'ar_usertext_timestamp' => 'usertext_timestamp',
- 'un_user_id' => 'user_id',
- 'un_user_ip' => 'user_ip',
- ] );
- }
- }
- /**
- * Log a database deprecation warning
- * @param string $msg Deprecation message
- */
- public static function logDeprecation( $msg ) {
- global $wgDevelopmentWarnings;
- if ( isset( self::$loggedDeprecations[$msg] ) ) {
- return;
- }
- self::$loggedDeprecations[$msg] = true;
- if ( $wgDevelopmentWarnings ) {
- trigger_error( $msg, E_USER_DEPRECATED );
- }
- wfDebugLog( 'deprecated', $msg, 'private' );
- }
- }
|