From: Aaron Schulz Date: Fri, 16 Sep 2016 02:17:22 +0000 (-0700) Subject: Move LBFactoryMulti to /libs/rdbms X-Git-Tag: 1.31.0-rc.0~5501^2 X-Git-Url: http://git.cyclocoop.org/%24self?a=commitdiff_plain;h=57ba462e4bc38bb6a75bdb7eef5cb7d27df59729;p=lhc%2Fweb%2Fwiklou.git Move LBFactoryMulti to /libs/rdbms Also rename $wiki => $domain and lastWiki => lastDomain. Change-Id: I2a30f42721715c56f5cddf9f07c10e8de70addd1 --- diff --git a/autoload.php b/autoload.php index 52c929a56f..4a72799c46 100644 --- a/autoload.php +++ b/autoload.php @@ -659,7 +659,7 @@ $wgAutoloadLocalClasses = [ 'KuConverter' => __DIR__ . '/languages/classes/LanguageKu.php', 'LBFactory' => __DIR__ . '/includes/libs/rdbms/lbfactory/LBFactory.php', 'LBFactoryMW' => __DIR__ . '/includes/db/loadbalancer/LBFactoryMW.php', - 'LBFactoryMulti' => __DIR__ . '/includes/db/loadbalancer/LBFactoryMulti.php', + 'LBFactoryMulti' => __DIR__ . '/includes/libs/rdbms/lbfactory/LBFactoryMulti.php', 'LBFactorySimple' => __DIR__ . '/includes/libs/rdbms/lbfactory/LBFactorySimple.php', 'LBFactorySingle' => __DIR__ . '/includes/db/loadbalancer/LBFactorySingle.php', 'LCStore' => __DIR__ . '/includes/cache/localisation/LCStore.php', diff --git a/includes/db/loadbalancer/LBFactoryMulti.php b/includes/db/loadbalancer/LBFactoryMulti.php deleted file mode 100644 index 1f7f528ab1..0000000000 --- a/includes/db/loadbalancer/LBFactoryMulti.php +++ /dev/null @@ -1,422 +0,0 @@ - lowest): - * - templateOverridesByServer - * - masterTemplateOverrides - * - templateOverridesBySection/templateOverridesByCluster - * - externalTemplateOverrides - * - serverTemplate - * Overrides only work on top level keys (so nested values will not be merged). - * - * Configuration: - * sectionsByDB A map of database names to section names. - * - * sectionLoads A 2-d map. For each section, gives a map of server names to - * load ratios. For example: - * [ - * 'section1' => [ - * 'db1' => 100, - * 'db2' => 100 - * ] - * ] - * - * serverTemplate A server info associative array as documented for $wgDBservers. - * The host, hostName and load entries will be overridden. - * - * groupLoadsBySection A 3-d map giving server load ratios for each section and group. - * For example: - * [ - * 'section1' => [ - * 'group1' => [ - * 'db1' => 100, - * 'db2' => 100 - * ] - * ] - * ] - * - * groupLoadsByDB A 3-d map giving server load ratios by DB name. - * - * hostsByName A map of hostname to IP address. - * - * externalLoads A map of external storage cluster name to server load map. - * - * externalTemplateOverrides A set of server info keys overriding serverTemplate for external - * storage. - * - * templateOverridesByServer A 2-d map overriding serverTemplate and - * externalTemplateOverrides on a server-by-server basis. Applies - * to both core and external storage. - * templateOverridesBySection A 2-d map overriding the server info by section. - * templateOverridesByCluster A 2-d map overriding the server info by external storage cluster. - * - * masterTemplateOverrides An override array for all master servers. - * - * loadMonitorClass Name of the LoadMonitor class to always use. - * - * readOnlyBySection A map of section name to read-only message. - * Missing or false for read/write. - * - * @ingroup Database - */ -class LBFactoryMulti extends LBFactoryMW { - /** @var array A map of database names to section names */ - private $sectionsByDB; - - /** - * @var array A 2-d map. For each section, gives a map of server names to - * load ratios - */ - private $sectionLoads; - - /** - * @var array A server info associative array as documented for - * $wgDBservers. The host, hostName and load entries will be - * overridden - */ - private $serverTemplate; - - // Optional settings - - /** @var array A 3-d map giving server load ratios for each section and group */ - private $groupLoadsBySection = []; - - /** @var array A 3-d map giving server load ratios by DB name */ - private $groupLoadsByDB = []; - - /** @var array A map of hostname to IP address */ - private $hostsByName = []; - - /** @var array A map of external storage cluster name to server load map */ - private $externalLoads = []; - - /** - * @var array A set of server info keys overriding serverTemplate for - * external storage - */ - private $externalTemplateOverrides; - - /** - * @var array A 2-d map overriding serverTemplate and - * externalTemplateOverrides on a server-by-server basis. Applies to both - * core and external storage - */ - private $templateOverridesByServer; - - /** @var array A 2-d map overriding the server info by section */ - private $templateOverridesBySection; - - /** @var array A 2-d map overriding the server info by external storage cluster */ - private $templateOverridesByCluster; - - /** @var array An override array for all master servers */ - private $masterTemplateOverrides; - - /** - * @var array|bool A map of section name to read-only message. Missing or - * false for read/write - */ - private $readOnlyBySection = []; - - // Other stuff - - /** @var array Load balancer factory configuration */ - private $conf; - - /** @var LoadBalancer[] */ - private $mainLBs = []; - - /** @var LoadBalancer[] */ - private $extLBs = []; - - /** @var string */ - private $loadMonitorClass; - - /** @var string */ - private $lastWiki; - - /** @var string */ - private $lastSection; - - /** - * @param array $conf - * @throws InvalidArgumentException - */ - public function __construct( array $conf ) { - parent::__construct( $conf ); - - $this->conf = $conf; - $required = [ 'sectionsByDB', 'sectionLoads', 'serverTemplate' ]; - $optional = [ 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName', - 'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer', - 'templateOverridesByCluster', 'templateOverridesBySection', 'masterTemplateOverrides', - 'readOnlyBySection', 'loadMonitorClass' ]; - - foreach ( $required as $key ) { - if ( !isset( $conf[$key] ) ) { - throw new InvalidArgumentException( __CLASS__ . ": $key is required in configuration" ); - } - $this->$key = $conf[$key]; - } - - foreach ( $optional as $key ) { - if ( isset( $conf[$key] ) ) { - $this->$key = $conf[$key]; - } - } - } - - /** - * @param bool|string $wiki - * @return string - */ - private function getSectionForWiki( $wiki = false ) { - if ( $this->lastWiki === $wiki ) { - return $this->lastSection; - } - list( $dbName, ) = $this->getDBNameAndPrefix( $wiki ); - if ( isset( $this->sectionsByDB[$dbName] ) ) { - $section = $this->sectionsByDB[$dbName]; - } else { - $section = 'DEFAULT'; - } - $this->lastSection = $section; - $this->lastWiki = $wiki; - - return $section; - } - - /** - * @param bool|string $wiki - * @return LoadBalancer - */ - public function newMainLB( $wiki = false ) { - list( $dbName, ) = $this->getDBNameAndPrefix( $wiki ); - $section = $this->getSectionForWiki( $wiki ); - if ( isset( $this->groupLoadsByDB[$dbName] ) ) { - $groupLoads = $this->groupLoadsByDB[$dbName]; - } else { - $groupLoads = []; - } - - if ( isset( $this->groupLoadsBySection[$section] ) ) { - $groupLoads = array_merge_recursive( $groupLoads, $this->groupLoadsBySection[$section] ); - } - - $readOnlyReason = $this->readOnlyReason; - // Use the LB-specific read-only reason if everything isn't already read-only - if ( $readOnlyReason === false && isset( $this->readOnlyBySection[$section] ) ) { - $readOnlyReason = $this->readOnlyBySection[$section]; - } - - $template = $this->serverTemplate; - if ( isset( $this->templateOverridesBySection[$section] ) ) { - $template = $this->templateOverridesBySection[$section] + $template; - } - - return $this->newLoadBalancer( - $template, - $this->sectionLoads[$section], - $groupLoads, - $readOnlyReason - ); - } - - /** - * @param bool|string $wiki - * @return LoadBalancer - */ - public function getMainLB( $wiki = false ) { - $section = $this->getSectionForWiki( $wiki ); - if ( !isset( $this->mainLBs[$section] ) ) { - $lb = $this->newMainLB( $wiki ); - $this->getChronologyProtector()->initLB( $lb ); - $this->mainLBs[$section] = $lb; - } - - return $this->mainLBs[$section]; - } - - /** - * @param string $cluster - * @param bool|string $wiki - * @throws InvalidArgumentException - * @return LoadBalancer - */ - protected function newExternalLB( $cluster, $wiki = false ) { - if ( !isset( $this->externalLoads[$cluster] ) ) { - throw new InvalidArgumentException( __METHOD__ . ": Unknown cluster \"$cluster\"" ); - } - $template = $this->serverTemplate; - if ( isset( $this->externalTemplateOverrides ) ) { - $template = $this->externalTemplateOverrides + $template; - } - if ( isset( $this->templateOverridesByCluster[$cluster] ) ) { - $template = $this->templateOverridesByCluster[$cluster] + $template; - } - - return $this->newLoadBalancer( - $template, - $this->externalLoads[$cluster], - [], - $this->readOnlyReason - ); - } - - /** - * @param string $cluster External storage cluster, or false for core - * @param bool|string $wiki Wiki ID, or false for the current wiki - * @return LoadBalancer - */ - public function getExternalLB( $cluster, $wiki = false ) { - if ( !isset( $this->extLBs[$cluster] ) ) { - $this->extLBs[$cluster] = $this->newExternalLB( $cluster, $wiki ); - $this->getChronologyProtector()->initLB( $this->extLBs[$cluster] ); - } - - return $this->extLBs[$cluster]; - } - - /** - * Make a new load balancer object based on template and load array - * - * @param array $template - * @param array $loads - * @param array $groupLoads - * @param string|bool $readOnlyReason - * @return LoadBalancer - */ - private function newLoadBalancer( $template, $loads, $groupLoads, $readOnlyReason ) { - $lb = new LoadBalancer( array_merge( - $this->baseLoadBalancerParams(), - [ - 'servers' => $this->makeServerArray( $template, $loads, $groupLoads ), - 'loadMonitor' => $this->loadMonitorClass, - 'readOnlyReason' => $readOnlyReason - ] - ) ); - $this->initLoadBalancer( $lb ); - - return $lb; - } - - /** - * Make a server array as expected by LoadBalancer::__construct, using a template and load array - * - * @param array $template - * @param array $loads - * @param array $groupLoads - * @return array - */ - private function makeServerArray( $template, $loads, $groupLoads ) { - $servers = []; - $master = true; - $groupLoadsByServer = $this->reindexGroupLoads( $groupLoads ); - foreach ( $groupLoadsByServer as $server => $stuff ) { - if ( !isset( $loads[$server] ) ) { - $loads[$server] = 0; - } - } - foreach ( $loads as $serverName => $load ) { - $serverInfo = $template; - if ( $master ) { - $serverInfo['master'] = true; - if ( isset( $this->masterTemplateOverrides ) ) { - $serverInfo = $this->masterTemplateOverrides + $serverInfo; - } - $master = false; - } else { - $serverInfo['replica'] = true; - } - if ( isset( $this->templateOverridesByServer[$serverName] ) ) { - $serverInfo = $this->templateOverridesByServer[$serverName] + $serverInfo; - } - if ( isset( $groupLoadsByServer[$serverName] ) ) { - $serverInfo['groupLoads'] = $groupLoadsByServer[$serverName]; - } - if ( isset( $this->hostsByName[$serverName] ) ) { - $serverInfo['host'] = $this->hostsByName[$serverName]; - } else { - $serverInfo['host'] = $serverName; - } - $serverInfo['hostName'] = $serverName; - $serverInfo['load'] = $load; - $serverInfo += [ 'flags' => DBO_DEFAULT ]; - - $servers[] = $serverInfo; - } - - return $servers; - } - - /** - * Take a group load array indexed by group then server, and reindex it by server then group - * @param array $groupLoads - * @return array - */ - private function reindexGroupLoads( $groupLoads ) { - $reindexed = []; - foreach ( $groupLoads as $group => $loads ) { - foreach ( $loads as $server => $load ) { - $reindexed[$server][$group] = $load; - } - } - - return $reindexed; - } - - /** - * Get the database name and prefix based on the wiki ID - * @param bool|string $wiki - * @return array - */ - private function getDBNameAndPrefix( $wiki = false ) { - if ( $wiki === false ) { - global $wgDBname, $wgDBprefix; - - return [ $wgDBname, $wgDBprefix ]; - } else { - return wfSplitWikiID( $wiki ); - } - } - - /** - * Execute a function for each tracked load balancer - * The callback is called with the load balancer as the first parameter, - * and $params passed as the subsequent parameters. - * @param callable $callback - * @param array $params - */ - public function forEachLB( $callback, array $params = [] ) { - foreach ( $this->mainLBs as $lb ) { - call_user_func_array( $callback, array_merge( [ $lb ], $params ) ); - } - foreach ( $this->extLBs as $lb ) { - call_user_func_array( $callback, array_merge( [ $lb ], $params ) ); - } - } -} diff --git a/includes/libs/rdbms/lbfactory/LBFactory.php b/includes/libs/rdbms/lbfactory/LBFactory.php index 00474fe0bc..40ba458826 100644 --- a/includes/libs/rdbms/lbfactory/LBFactory.php +++ b/includes/libs/rdbms/lbfactory/LBFactory.php @@ -141,7 +141,7 @@ abstract class LBFactory { * Create a new load balancer object. The resulting object will be untracked, * not chronology-protected, and the caller is responsible for cleaning it up. * - * @param bool|string $domain Wiki ID, or false for the current wiki + * @param bool|string $domain Domain ID, or false for the current domain * @return ILoadBalancer */ abstract public function newMainLB( $domain = false ); @@ -149,7 +149,7 @@ abstract class LBFactory { /** * Get a cached (tracked) load balancer object. * - * @param bool|string $domain Wiki ID, or false for the current wiki + * @param bool|string $domain Domain ID, or false for the current domain * @return ILoadBalancer */ abstract public function getMainLB( $domain = false ); @@ -160,7 +160,7 @@ abstract class LBFactory { * cleaning it up. * * @param string $cluster External storage cluster, or false for core - * @param bool|string $domain Wiki ID, or false for the current wiki + * @param bool|string $domain Domain ID, or false for the current domain * @return ILoadBalancer */ abstract protected function newExternalLB( $cluster, $domain = false ); @@ -169,7 +169,7 @@ abstract class LBFactory { * Get a cached (tracked) load balancer for external storage * * @param string $cluster External storage cluster, or false for core - * @param bool|string $domain Wiki ID, or false for the current wiki + * @param bool|string $domain Domain ID, or false for the current domain * @return ILoadBalancer */ abstract public function getExternalLB( $cluster, $domain = false ); diff --git a/includes/libs/rdbms/lbfactory/LBFactoryMulti.php b/includes/libs/rdbms/lbfactory/LBFactoryMulti.php new file mode 100644 index 0000000000..0f1493a82b --- /dev/null +++ b/includes/libs/rdbms/lbfactory/LBFactoryMulti.php @@ -0,0 +1,419 @@ + lowest): + * - templateOverridesByServer + * - masterTemplateOverrides + * - templateOverridesBySection/templateOverridesByCluster + * - externalTemplateOverrides + * - serverTemplate + * Overrides only work on top level keys (so nested values will not be merged). + * + * Configuration: + * sectionsByDB A map of database names to section names. + * + * sectionLoads A 2-d map. For each section, gives a map of server names to + * load ratios. For example: + * [ + * 'section1' => [ + * 'db1' => 100, + * 'db2' => 100 + * ] + * ] + * + * serverTemplate A server info associative array as documented for $wgDBservers. + * The host, hostName and load entries will be overridden. + * + * groupLoadsBySection A 3-d map giving server load ratios for each section and group. + * For example: + * [ + * 'section1' => [ + * 'group1' => [ + * 'db1' => 100, + * 'db2' => 100 + * ] + * ] + * ] + * + * groupLoadsByDB A 3-d map giving server load ratios by DB name. + * + * hostsByName A map of hostname to IP address. + * + * externalLoads A map of external storage cluster name to server load map. + * + * externalTemplateOverrides A set of server info keys overriding serverTemplate for external + * storage. + * + * templateOverridesByServer A 2-d map overriding serverTemplate and + * externalTemplateOverrides on a server-by-server basis. Applies + * to both core and external storage. + * templateOverridesBySection A 2-d map overriding the server info by section. + * templateOverridesByCluster A 2-d map overriding the server info by external storage cluster. + * + * masterTemplateOverrides An override array for all master servers. + * + * loadMonitorClass Name of the LoadMonitor class to always use. + * + * readOnlyBySection A map of section name to read-only message. + * Missing or false for read/write. + * + * @ingroup Database + */ +class LBFactoryMulti extends LBFactory { + /** @var array A map of database names to section names */ + private $sectionsByDB; + + /** + * @var array A 2-d map. For each section, gives a map of server names to + * load ratios + */ + private $sectionLoads; + + /** + * @var array[] Server info associative array + * @note The host, hostName and load entries will be overridden + */ + private $serverTemplate; + + // Optional settings + + /** @var array A 3-d map giving server load ratios for each section and group */ + private $groupLoadsBySection = []; + + /** @var array A 3-d map giving server load ratios by DB name */ + private $groupLoadsByDB = []; + + /** @var array A map of hostname to IP address */ + private $hostsByName = []; + + /** @var array A map of external storage cluster name to server load map */ + private $externalLoads = []; + + /** + * @var array A set of server info keys overriding serverTemplate for + * external storage + */ + private $externalTemplateOverrides; + + /** + * @var array A 2-d map overriding serverTemplate and + * externalTemplateOverrides on a server-by-server basis. Applies to both + * core and external storage + */ + private $templateOverridesByServer; + + /** @var array A 2-d map overriding the server info by section */ + private $templateOverridesBySection; + + /** @var array A 2-d map overriding the server info by external storage cluster */ + private $templateOverridesByCluster; + + /** @var array An override array for all master servers */ + private $masterTemplateOverrides; + + /** + * @var array|bool A map of section name to read-only message. Missing or + * false for read/write + */ + private $readOnlyBySection = []; + + // Other stuff + + /** @var array Load balancer factory configuration */ + private $conf; + + /** @var LoadBalancer[] */ + private $mainLBs = []; + + /** @var LoadBalancer[] */ + private $extLBs = []; + + /** @var string */ + private $loadMonitorClass; + + /** @var string */ + private $lastDomain; + + /** @var string */ + private $lastSection; + + /** + * @param array $conf + * @throws InvalidArgumentException + */ + public function __construct( array $conf ) { + parent::__construct( $conf ); + + $this->conf = $conf; + $required = [ 'sectionsByDB', 'sectionLoads', 'serverTemplate' ]; + $optional = [ 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName', + 'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer', + 'templateOverridesByCluster', 'templateOverridesBySection', 'masterTemplateOverrides', + 'readOnlyBySection', 'loadMonitorClass' ]; + + foreach ( $required as $key ) { + if ( !isset( $conf[$key] ) ) { + throw new InvalidArgumentException( __CLASS__ . ": $key is required." ); + } + $this->$key = $conf[$key]; + } + + foreach ( $optional as $key ) { + if ( isset( $conf[$key] ) ) { + $this->$key = $conf[$key]; + } + } + } + + /** + * @param bool|string $domain + * @return string + */ + private function getSectionForDomain( $domain = false ) { + if ( $this->lastDomain === $domain ) { + return $this->lastSection; + } + list( $dbName, ) = $this->getDBNameAndPrefix( $domain ); + if ( isset( $this->sectionsByDB[$dbName] ) ) { + $section = $this->sectionsByDB[$dbName]; + } else { + $section = 'DEFAULT'; + } + $this->lastSection = $section; + $this->lastDomain = $domain; + + return $section; + } + + /** + * @param bool|string $domain + * @return LoadBalancer + */ + public function newMainLB( $domain = false ) { + list( $dbName, ) = $this->getDBNameAndPrefix( $domain ); + $section = $this->getSectionForDomain( $domain ); + if ( isset( $this->groupLoadsByDB[$dbName] ) ) { + $groupLoads = $this->groupLoadsByDB[$dbName]; + } else { + $groupLoads = []; + } + + if ( isset( $this->groupLoadsBySection[$section] ) ) { + $groupLoads = array_merge_recursive( + $groupLoads, $this->groupLoadsBySection[$section] ); + } + + $readOnlyReason = $this->readOnlyReason; + // Use the LB-specific read-only reason if everything isn't already read-only + if ( $readOnlyReason === false && isset( $this->readOnlyBySection[$section] ) ) { + $readOnlyReason = $this->readOnlyBySection[$section]; + } + + $template = $this->serverTemplate; + if ( isset( $this->templateOverridesBySection[$section] ) ) { + $template = $this->templateOverridesBySection[$section] + $template; + } + + return $this->newLoadBalancer( + $template, + $this->sectionLoads[$section], + $groupLoads, + $readOnlyReason + ); + } + + /** + * @param DatabaseDomain|string|bool $domain Domain ID, or false for the current domain + * @return LoadBalancer + */ + public function getMainLB( $domain = false ) { + $section = $this->getSectionForDomain( $domain ); + if ( !isset( $this->mainLBs[$section] ) ) { + $lb = $this->newMainLB( $domain ); + $this->getChronologyProtector()->initLB( $lb ); + $this->mainLBs[$section] = $lb; + } + + return $this->mainLBs[$section]; + } + + /** + * @param string $cluster + * @param DatabaseDomain|string|bool $domain Domain ID, or false for the current domain + * @throws InvalidArgumentException + * @return LoadBalancer + */ + protected function newExternalLB( $cluster, $domain = false ) { + if ( !isset( $this->externalLoads[$cluster] ) ) { + throw new InvalidArgumentException( __METHOD__ . ": Unknown cluster \"$cluster\"" ); + } + $template = $this->serverTemplate; + if ( isset( $this->externalTemplateOverrides ) ) { + $template = $this->externalTemplateOverrides + $template; + } + if ( isset( $this->templateOverridesByCluster[$cluster] ) ) { + $template = $this->templateOverridesByCluster[$cluster] + $template; + } + + return $this->newLoadBalancer( + $template, + $this->externalLoads[$cluster], + [], + $this->readOnlyReason + ); + } + + /** + * @param string $cluster External storage cluster, or false for core + * @param DatabaseDomain|string|bool $domain Domain ID, or false for the current domain + * @return LoadBalancer + */ + public function getExternalLB( $cluster, $domain = false ) { + if ( !isset( $this->extLBs[$cluster] ) ) { + $this->extLBs[$cluster] = $this->newExternalLB( $cluster, $domain ); + $this->getChronologyProtector()->initLB( $this->extLBs[$cluster] ); + } + + return $this->extLBs[$cluster]; + } + + /** + * Make a new load balancer object based on template and load array + * + * @param array $template + * @param array $loads + * @param array $groupLoads + * @param string|bool $readOnlyReason + * @return LoadBalancer + */ + private function newLoadBalancer( $template, $loads, $groupLoads, $readOnlyReason ) { + $lb = new LoadBalancer( array_merge( + $this->baseLoadBalancerParams(), + [ + 'servers' => $this->makeServerArray( $template, $loads, $groupLoads ), + 'loadMonitor' => $this->loadMonitorClass, + 'readOnlyReason' => $readOnlyReason + ] + ) ); + $this->initLoadBalancer( $lb ); + + return $lb; + } + + /** + * Make a server array as expected by LoadBalancer::__construct, using a template and load array + * + * @param array $template + * @param array $loads + * @param array $groupLoads + * @return array + */ + private function makeServerArray( $template, $loads, $groupLoads ) { + $servers = []; + $master = true; + $groupLoadsByServer = $this->reindexGroupLoads( $groupLoads ); + foreach ( $groupLoadsByServer as $server => $stuff ) { + if ( !isset( $loads[$server] ) ) { + $loads[$server] = 0; + } + } + foreach ( $loads as $serverName => $load ) { + $serverInfo = $template; + if ( $master ) { + $serverInfo['master'] = true; + if ( isset( $this->masterTemplateOverrides ) ) { + $serverInfo = $this->masterTemplateOverrides + $serverInfo; + } + $master = false; + } else { + $serverInfo['replica'] = true; + } + if ( isset( $this->templateOverridesByServer[$serverName] ) ) { + $serverInfo = $this->templateOverridesByServer[$serverName] + $serverInfo; + } + if ( isset( $groupLoadsByServer[$serverName] ) ) { + $serverInfo['groupLoads'] = $groupLoadsByServer[$serverName]; + } + if ( isset( $this->hostsByName[$serverName] ) ) { + $serverInfo['host'] = $this->hostsByName[$serverName]; + } else { + $serverInfo['host'] = $serverName; + } + $serverInfo['hostName'] = $serverName; + $serverInfo['load'] = $load; + $serverInfo += [ 'flags' => DBO_DEFAULT ]; + + $servers[] = $serverInfo; + } + + return $servers; + } + + /** + * Take a group load array indexed by group then server, and reindex it by server then group + * @param array $groupLoads + * @return array + */ + private function reindexGroupLoads( $groupLoads ) { + $reindexed = []; + foreach ( $groupLoads as $group => $loads ) { + foreach ( $loads as $server => $load ) { + $reindexed[$server][$group] = $load; + } + } + + return $reindexed; + } + + /** + * @param DatabaseDomain|string|bool $domain Domain ID, or false for the current domain + * @return array [database name, table prefix] + */ + private function getDBNameAndPrefix( $domain = false ) { + $domain = ( $domain === false ) + ? $this->localDomain + : DatabaseDomain::newFromId( $domain ); + + return [ $domain->getDatabase(), $domain->getTablePrefix() ]; + } + + /** + * Execute a function for each tracked load balancer + * The callback is called with the load balancer as the first parameter, + * and $params passed as the subsequent parameters. + * @param callable $callback + * @param array $params + */ + public function forEachLB( $callback, array $params = [] ) { + foreach ( $this->mainLBs as $lb ) { + call_user_func_array( $callback, array_merge( [ $lb ], $params ) ); + } + foreach ( $this->extLBs as $lb ) { + call_user_func_array( $callback, array_merge( [ $lb ], $params ) ); + } + } +}