26use InvalidArgumentException;
27use UnexpectedValueException;
114 parent::__construct( $conf );
116 $this->hostsByName = $conf[
'hostsByName'] ?? [];
117 $this->sectionsByDB = $conf[
'sectionsByDB'];
118 $this->groupLoadsBySection = $conf[
'groupLoadsBySection'] ?? [];
119 foreach ( ( $conf[
'sectionLoads'] ?? [] ) as $section => $loadByHost ) {
120 $this->groupLoadsBySection[$section][ILoadBalancer::GROUP_GENERIC] = $loadByHost;
122 $this->groupLoadsByDB = $conf[
'groupLoadsByDB'] ?? [];
123 $this->externalLoads = $conf[
'externalLoads'] ?? [];
124 $this->serverTemplate = $conf[
'serverTemplate'] ?? [];
125 $this->externalTemplateOverrides = $conf[
'externalTemplateOverrides'] ?? [];
126 $this->templateOverridesBySection = $conf[
'templateOverridesBySection'] ?? [];
127 $this->templateOverridesByCluster = $conf[
'templateOverridesByCluster'] ?? [];
128 $this->masterTemplateOverrides = $conf[
'masterTemplateOverrides'] ?? [];
129 $this->templateOverridesByServer = $conf[
'templateOverridesByServer'] ?? [];
130 $this->readOnlyBySection = $conf[
'readOnlyBySection'] ?? [];
132 if ( isset( $conf[
'loadMonitor'] ) ) {
133 $this->loadMonitorConfig = $conf[
'loadMonitor'];
134 } elseif ( isset( $conf[
'loadMonitorClass'] ) ) {
135 $this->loadMonitorConfig = [
'class' => $conf[
'loadMonitorClass'] ];
137 $this->loadMonitorConfig = [
'class' => LoadMonitor::class ];
141 public function newMainLB( $domain =
false, $owner =
null ) {
143 $database = $domainInstance->getDatabase();
145 if ( !isset( $this->groupLoadsBySection[$section][ILoadBalancer::GROUP_GENERIC] ) ) {
146 throw new UnexpectedValueException(
"Section '$section' has no hosts defined." );
148 $dbGroupLoads = $this->groupLoadsByDB[$database] ?? [];
149 unset( $dbGroupLoads[ILoadBalancer::GROUP_GENERIC] );
152 $this->serverTemplate,
153 $this->templateOverridesBySection[$section] ?? []
155 array_merge( $this->groupLoadsBySection[$section], $dbGroupLoads ),
157 is_string( $this->readOnlyReason )
158 ? $this->readOnlyReason
159 : ( $this->readOnlyBySection[$section] ?? false ),
168 if ( !isset( $this->mainLBs[$section] ) ) {
172 return $this->mainLBs[$section];
176 if ( !isset( $this->externalLoads[$cluster] ) ) {
177 throw new InvalidArgumentException(
"Unknown cluster '$cluster'" );
181 $this->serverTemplate,
182 $this->externalTemplateOverrides,
183 $this->templateOverridesByCluster[$cluster] ?? []
185 [ ILoadBalancer::GROUP_GENERIC => $this->externalLoads[$cluster] ],
186 $this->readOnlyReason,
192 if ( !isset( $this->externalLBs[$cluster] ) ) {
193 $this->externalLBs[$cluster] =
197 return $this->externalLBs[$cluster];
202 foreach ( $this->sectionsByDB as $db => $section ) {
203 if ( !isset( $lbs[$section] ) ) {
204 $lbs[$section] = $this->
getMainLB( $db );
213 foreach ( $this->externalLoads as $cluster => $unused ) {
220 public function forEachLB( $callback, array $params = [] ) {
221 foreach ( $this->mainLBs as $lb ) {
222 $callback( $lb, ...$params );
224 foreach ( $this->externalLBs as $lb ) {
225 $callback( $lb, ...$params );
243 'loadMonitor' => $this->loadMonitorConfig,
261 if ( !$groupLoads[ILoadBalancer::GROUP_GENERIC] ) {
262 throw new UnexpectedValueException(
"Empty generic load array; no master defined." );
266 $genericLoads = $groupLoads[ILoadBalancer::GROUP_GENERIC];
268 $genericLoads += array_fill_keys( array_keys( $groupLoadsByHost ), 0 );
270 foreach ( $genericLoads as $host => $load ) {
271 $servers[] = array_merge(
274 $this->templateOverridesByServer[$host] ?? [],
276 'host' => $this->hostsByName[$host] ?? $host,
279 'groupLoads' => $groupLoadsByHost[$host] ?? []
293 $groupLoadsByHost = [];
294 foreach ( $groupLoads as $group => $loadByHost ) {
295 foreach ( $loadByHost as $host => $load ) {
296 $groupLoadsByHost[$host][$group] = $load;
300 return $groupLoadsByHost;
308 return $this->sectionsByDB[$database] ??
'DEFAULT';