Merge "Fix 'Tags' padding to keep it farther from the edge and document the source...
[lhc/web/wiklou.git] / includes / libs / rdbms / loadbalancer / LoadBalancer.php
index 360be42..fe0c622 100644 (file)
@@ -38,10 +38,39 @@ use Exception;
  * @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) */
@@ -52,31 +81,24 @@ class LoadBalancer implements ILoadBalancer {
        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;
@@ -94,35 +116,19 @@ class LoadBalancer implements ILoadBalancer {
        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;
 
@@ -172,9 +178,7 @@ class LoadBalancer implements ILoadBalancer {
                        : DatabaseDomain::newUnspecified();
                $this->setLocalDomain( $localDomain );
 
-               $this->waitTimeout = isset( $params['waitTimeout'] )
-                       ? $params['waitTimeout']
-                       : self::MAX_WAIT_DEFAULT;
+               $this->waitTimeout = $params['waitTimeout'] ?? self::MAX_WAIT_DEFAULT;
 
                $this->readIndex = -1;
                $this->conns = [
@@ -228,35 +232,27 @@ class LoadBalancer implements ILoadBalancer {
                } else {
                        $this->wanCache = WANObjectCache::newEmpty();
                }
-               $this->profiler = isset( $params['profiler'] ) ? $params['profiler'] : null;
+               $this->profiler = $params['profiler'] ?? null;
                if ( isset( $params['trxProfiler'] ) ) {
                        $this->trxProfiler = $params['trxProfiler'];
                } else {
                        $this->trxProfiler = new TransactionProfiler();
                }
 
-               $this->errorLogger = isset( $params['errorLogger'] )
-                       ? $params['errorLogger']
-                       : function ( Exception $e ) {
-                               trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_USER_WARNING );
-                       };
-               $this->deprecationLogger = isset( $params['deprecationLogger'] )
-                       ? $params['deprecationLogger']
-                       : function ( $msg ) {
-                               trigger_error( $msg, E_USER_DEPRECATED );
-                       };
+               $this->errorLogger = $params['errorLogger'] ?? function ( Exception $e ) {
+                       trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_USER_WARNING );
+               };
+               $this->deprecationLogger = $params['deprecationLogger'] ?? function ( $msg ) {
+                       trigger_error( $msg, E_USER_DEPRECATED );
+               };
 
                foreach ( [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ] as $key ) {
-                       $this->$key = isset( $params[$key] ) ? $params[$key] : new NullLogger();
+                       $this->$key = $params[$key] ?? new NullLogger();
                }
 
-               $this->host = isset( $params['hostname'] )
-                       ? $params['hostname']
-                       : ( gethostname() ?: 'unknown' );
-               $this->cliMode = isset( $params['cliMode'] )
-                       ? $params['cliMode']
-                       : ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' );
-               $this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
+               $this->hostname = $params['hostname'] ?? ( gethostname() ?: 'unknown' );
+               $this->cliMode = $params['cliMode'] ?? ( PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' );
+               $this->agent = $params['agent'] ?? '';
 
                if ( isset( $params['chronologyCallback'] ) ) {
                        $this->chronologyCallback = $params['chronologyCallback'];
@@ -269,6 +265,8 @@ class LoadBalancer implements ILoadBalancer {
                                $this->trxRoundStage = self::ROUND_ROLLBACK_CALLBACKS;
                        }
                }
+
+               $this->defaultGroup = $params['defaultGroup'] ?? null;
        }
 
        /**
@@ -321,9 +319,7 @@ class LoadBalancer implements ILoadBalancer {
                foreach ( $lags as $i => $lag ) {
                        if ( $i != 0 ) {
                                # How much lag this server nominally is allowed to have
-                               $maxServerLag = isset( $this->servers[$i]['max lag'] )
-                                       ? $this->servers[$i]['max lag']
-                                       : $this->maxLag; // default
+                               $maxServerLag = $this->servers[$i]['max lag'] ?? $this->maxLag; // default
                                # Constrain that futher by $maxLag argument
                                $maxServerLag = min( $maxServerLag, $maxLag );
 
@@ -729,8 +725,11 @@ class LoadBalancer implements ILoadBalancer {
                        }
                }
 
+               // 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() );
@@ -876,7 +875,7 @@ class LoadBalancer implements ILoadBalancer {
                        $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
@@ -987,7 +986,7 @@ class LoadBalancer implements ILoadBalancer {
                        $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 {
@@ -1033,7 +1032,7 @@ class LoadBalancer implements ILoadBalancer {
        public function getServerAttributes( $i ) {
                return Database::attributesFromType(
                        $this->getServerType( $i ),
-                       isset( $this->servers[$i]['driver'] ) ? $this->servers[$i]['driver'] : null
+                       $this->servers[$i]['driver'] ?? null
                );
        }
 
@@ -1106,7 +1105,7 @@ class LoadBalancer implements ILoadBalancer {
                $server['agent'] = $this->agent;
                // Use DBO_DEFAULT flags by default for LoadBalancer managed databases. Assume that the
                // application calls LoadBalancer::commitMasterChanges() before the PHP script completes.
-               $server['flags'] = isset( $server['flags'] ) ? $server['flags'] : IDatabase::DBO_DEFAULT;
+               $server['flags'] = $server['flags'] ?? IDatabase::DBO_DEFAULT;
 
                // Create a live connection object
                try {
@@ -1195,8 +1194,16 @@ 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';
+               return $this->servers[$i]['type'] ?? 'unknown';
        }
 
        public function getMasterPos() {
@@ -1297,7 +1304,7 @@ class LoadBalancer implements ILoadBalancer {
        public function approveMasterChanges( array $options ) {
                $this->assertTransactionRoundStage( self::ROUND_FINALIZED );
 
-               $limit = isset( $options['maxWriteDuration'] ) ? $options['maxWriteDuration'] : 0;
+               $limit = $options['maxWriteDuration'] ?? 0;
 
                $this->trxRoundStage = self::ROUND_ERROR; // "failed" until proven otherwise
                $this->forEachOpenMasterConnection( function ( IDatabase $conn ) use ( $limit ) {
@@ -1374,7 +1381,7 @@ class LoadBalancer implements ILoadBalancer {
                                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()}";
                                }
                        }
@@ -1727,8 +1734,7 @@ class LoadBalancer implements ILoadBalancer {
                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 );
                                }
                        }
                }
@@ -1740,8 +1746,7 @@ class LoadBalancer implements ILoadBalancer {
                        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 );
                                }
                        }
                }
@@ -1754,8 +1759,7 @@ class LoadBalancer implements ILoadBalancer {
                                        continue; // skip master
                                }
                                foreach ( $serverConns as $conn ) {
-                                       $mergedParams = array_merge( [ $conn ], $params );
-                                       call_user_func_array( $callback, $mergedParams );
+                                       $callback( $conn, ...$params );
                                }
                        }
                }
@@ -1952,4 +1956,7 @@ class LoadBalancer implements ILoadBalancer {
        }
 }
 
+/**
+ * @deprecated since 1.29
+ */
 class_alias( LoadBalancer::class, 'LoadBalancer' );