[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Advanced generator of database load balancing objects for wiki farms. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * http://www.gnu.org/copyleft/gpl.html 19 * 20 * @file 21 * @ingroup Database 22 */ 23 24 /** 25 * A multi-wiki, multi-master factory for Wikimedia and similar installations. 26 * Ignores the old configuration globals 27 * 28 * Configuration: 29 * sectionsByDB A map of database names to section names. 30 * 31 * sectionLoads A 2-d map. For each section, gives a map of server names to 32 * load ratios. For example: 33 * array( 34 * 'section1' => array( 35 * 'db1' => 100, 36 * 'db2' => 100 37 * ) 38 * ) 39 * 40 * serverTemplate A server info associative array as documented for $wgDBservers. 41 * The host, hostName and load entries will be overridden. 42 * 43 * groupLoadsBySection A 3-d map giving server load ratios for each section and group. 44 * For example: 45 * array( 46 * 'section1' => array( 47 * 'group1' => array( 48 * 'db1' => 100, 49 * 'db2' => 100 50 * ) 51 * ) 52 * ) 53 * 54 * groupLoadsByDB A 3-d map giving server load ratios by DB name. 55 * 56 * hostsByName A map of hostname to IP address. 57 * 58 * externalLoads A map of external storage cluster name to server load map. 59 * 60 * externalTemplateOverrides A set of server info keys overriding serverTemplate for external 61 * storage. 62 * 63 * templateOverridesByServer A 2-d map overriding serverTemplate and 64 * externalTemplateOverrides on a server-by-server basis. Applies 65 * to both core and external storage. 66 * 67 * templateOverridesByCluster A 2-d map overriding the server info by external storage cluster. 68 * 69 * masterTemplateOverrides An override array for all master servers. 70 * 71 * readOnlyBySection A map of section name to read-only message. 72 * Missing or false for read/write. 73 * 74 * @ingroup Database 75 */ 76 class LBFactoryMulti extends LBFactory { 77 // Required settings 78 79 /** @var array A map of database names to section names */ 80 protected $sectionsByDB; 81 82 /** 83 * @var array A 2-d map. For each section, gives a map of server names to 84 * load ratios 85 */ 86 protected $sectionLoads; 87 88 /** 89 * @var array A server info associative array as documented for 90 * $wgDBservers. The host, hostName and load entries will be 91 * overridden 92 */ 93 protected $serverTemplate; 94 95 // Optional settings 96 97 /** @var array A 3-d map giving server load ratios for each section and group */ 98 protected $groupLoadsBySection = array(); 99 100 /** @var array A 3-d map giving server load ratios by DB name */ 101 protected $groupLoadsByDB = array(); 102 103 /** @var array A map of hostname to IP address */ 104 protected $hostsByName = array(); 105 106 /** @var array A map of external storage cluster name to server load map */ 107 protected $externalLoads = array(); 108 109 /** 110 * @var array A set of server info keys overriding serverTemplate for 111 * external storage 112 */ 113 protected $externalTemplateOverrides; 114 115 /** 116 * @var array A 2-d map overriding serverTemplate and 117 * externalTemplateOverrides on a server-by-server basis. Applies to both 118 * core and external storage 119 */ 120 protected $templateOverridesByServer; 121 122 /** @var array A 2-d map overriding the server info by external storage cluster */ 123 protected $templateOverridesByCluster; 124 125 /** @var array An override array for all master servers */ 126 protected $masterTemplateOverrides; 127 128 /** 129 * @var array|bool A map of section name to read-only message. Missing or 130 * false for read/write 131 */ 132 protected $readOnlyBySection = array(); 133 134 // Other stuff 135 136 /** @var array Load balancer factory configuration */ 137 protected $conf; 138 139 /** @var LoadBalancer[] */ 140 protected $mainLBs = array(); 141 142 /** @var LoadBalancer[] */ 143 protected $extLBs = array(); 144 145 /** @var string */ 146 protected $lastWiki; 147 148 /** @var string */ 149 protected $lastSection; 150 151 /** 152 * @param array $conf 153 * @throws MWException 154 */ 155 function __construct( $conf ) { 156 $this->chronProt = new ChronologyProtector; 157 $this->conf = $conf; 158 $required = array( 'sectionsByDB', 'sectionLoads', 'serverTemplate' ); 159 $optional = array( 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName', 160 'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer', 161 'templateOverridesByCluster', 'masterTemplateOverrides', 162 'readOnlyBySection' ); 163 164 foreach ( $required as $key ) { 165 if ( !isset( $conf[$key] ) ) { 166 throw new MWException( __CLASS__ . ": $key is required in configuration" ); 167 } 168 $this->$key = $conf[$key]; 169 } 170 171 foreach ( $optional as $key ) { 172 if ( isset( $conf[$key] ) ) { 173 $this->$key = $conf[$key]; 174 } 175 } 176 177 // Check for read-only mode 178 $section = $this->getSectionForWiki(); 179 if ( !empty( $this->readOnlyBySection[$section] ) ) { 180 global $wgReadOnly; 181 $wgReadOnly = $this->readOnlyBySection[$section]; 182 } 183 } 184 185 /** 186 * @param bool|string $wiki 187 * @return string 188 */ 189 function getSectionForWiki( $wiki = false ) { 190 if ( $this->lastWiki === $wiki ) { 191 return $this->lastSection; 192 } 193 list( $dbName, ) = $this->getDBNameAndPrefix( $wiki ); 194 if ( isset( $this->sectionsByDB[$dbName] ) ) { 195 $section = $this->sectionsByDB[$dbName]; 196 } else { 197 $section = 'DEFAULT'; 198 } 199 $this->lastSection = $section; 200 $this->lastWiki = $wiki; 201 202 return $section; 203 } 204 205 /** 206 * @param bool|string $wiki 207 * @return LoadBalancer 208 */ 209 function newMainLB( $wiki = false ) { 210 list( $dbName, ) = $this->getDBNameAndPrefix( $wiki ); 211 $section = $this->getSectionForWiki( $wiki ); 212 $groupLoads = array(); 213 if ( isset( $this->groupLoadsByDB[$dbName] ) ) { 214 $groupLoads = $this->groupLoadsByDB[$dbName]; 215 } 216 217 if ( isset( $this->groupLoadsBySection[$section] ) ) { 218 $groupLoads = array_merge_recursive( $groupLoads, $this->groupLoadsBySection[$section] ); 219 } 220 221 return $this->newLoadBalancer( 222 $this->serverTemplate, 223 $this->sectionLoads[$section], 224 $groupLoads 225 ); 226 } 227 228 /** 229 * @param bool|string $wiki 230 * @return LoadBalancer 231 */ 232 function getMainLB( $wiki = false ) { 233 $section = $this->getSectionForWiki( $wiki ); 234 if ( !isset( $this->mainLBs[$section] ) ) { 235 $lb = $this->newMainLB( $wiki, $section ); 236 $lb->parentInfo( array( 'id' => "main-$section" ) ); 237 $this->chronProt->initLB( $lb ); 238 $this->mainLBs[$section] = $lb; 239 } 240 241 return $this->mainLBs[$section]; 242 } 243 244 /** 245 * @param string $cluster 246 * @param bool|string $wiki 247 * @throws MWException 248 * @return LoadBalancer 249 */ 250 function newExternalLB( $cluster, $wiki = false ) { 251 if ( !isset( $this->externalLoads[$cluster] ) ) { 252 throw new MWException( __METHOD__ . ": Unknown cluster \"$cluster\"" ); 253 } 254 $template = $this->serverTemplate; 255 if ( isset( $this->externalTemplateOverrides ) ) { 256 $template = $this->externalTemplateOverrides + $template; 257 } 258 if ( isset( $this->templateOverridesByCluster[$cluster] ) ) { 259 $template = $this->templateOverridesByCluster[$cluster] + $template; 260 } 261 262 return $this->newLoadBalancer( $template, $this->externalLoads[$cluster], array() ); 263 } 264 265 /** 266 * @param string $cluster External storage cluster, or false for core 267 * @param bool|string $wiki Wiki ID, or false for the current wiki 268 * @return LoadBalancer 269 */ 270 function &getExternalLB( $cluster, $wiki = false ) { 271 if ( !isset( $this->extLBs[$cluster] ) ) { 272 $this->extLBs[$cluster] = $this->newExternalLB( $cluster, $wiki ); 273 $this->extLBs[$cluster]->parentInfo( array( 'id' => "ext-$cluster" ) ); 274 $this->chronProt->initLB( $this->extLBs[$cluster] ); 275 } 276 277 return $this->extLBs[$cluster]; 278 } 279 280 /** 281 * Make a new load balancer object based on template and load array 282 * 283 * @param array $template 284 * @param array $loads 285 * @param array $groupLoads 286 * @return LoadBalancer 287 */ 288 function newLoadBalancer( $template, $loads, $groupLoads ) { 289 $servers = $this->makeServerArray( $template, $loads, $groupLoads ); 290 $lb = new LoadBalancer( array( 291 'servers' => $servers, 292 ) ); 293 294 return $lb; 295 } 296 297 /** 298 * Make a server array as expected by LoadBalancer::__construct, using a template and load array 299 * 300 * @param array $template 301 * @param array $loads 302 * @param array $groupLoads 303 * @return array 304 */ 305 function makeServerArray( $template, $loads, $groupLoads ) { 306 $servers = array(); 307 $master = true; 308 $groupLoadsByServer = $this->reindexGroupLoads( $groupLoads ); 309 foreach ( $groupLoadsByServer as $server => $stuff ) { 310 if ( !isset( $loads[$server] ) ) { 311 $loads[$server] = 0; 312 } 313 } 314 foreach ( $loads as $serverName => $load ) { 315 $serverInfo = $template; 316 if ( $master ) { 317 $serverInfo['master'] = true; 318 if ( isset( $this->masterTemplateOverrides ) ) { 319 $serverInfo = $this->masterTemplateOverrides + $serverInfo; 320 } 321 $master = false; 322 } 323 if ( isset( $this->templateOverridesByServer[$serverName] ) ) { 324 $serverInfo = $this->templateOverridesByServer[$serverName] + $serverInfo; 325 } 326 if ( isset( $groupLoadsByServer[$serverName] ) ) { 327 $serverInfo['groupLoads'] = $groupLoadsByServer[$serverName]; 328 } 329 if ( isset( $this->hostsByName[$serverName] ) ) { 330 $serverInfo['host'] = $this->hostsByName[$serverName]; 331 } else { 332 $serverInfo['host'] = $serverName; 333 } 334 $serverInfo['hostName'] = $serverName; 335 $serverInfo['load'] = $load; 336 $servers[] = $serverInfo; 337 } 338 339 return $servers; 340 } 341 342 /** 343 * Take a group load array indexed by group then server, and reindex it by server then group 344 * @param array $groupLoads 345 * @return array 346 */ 347 function reindexGroupLoads( $groupLoads ) { 348 $reindexed = array(); 349 foreach ( $groupLoads as $group => $loads ) { 350 foreach ( $loads as $server => $load ) { 351 $reindexed[$server][$group] = $load; 352 } 353 } 354 355 return $reindexed; 356 } 357 358 /** 359 * Get the database name and prefix based on the wiki ID 360 * @param bool|string $wiki 361 * @return array 362 */ 363 function getDBNameAndPrefix( $wiki = false ) { 364 if ( $wiki === false ) { 365 global $wgDBname, $wgDBprefix; 366 367 return array( $wgDBname, $wgDBprefix ); 368 } else { 369 return wfSplitWikiID( $wiki ); 370 } 371 } 372 373 /** 374 * Execute a function for each tracked load balancer 375 * The callback is called with the load balancer as the first parameter, 376 * and $params passed as the subsequent parameters. 377 * @param callable $callback 378 * @param array $params 379 */ 380 function forEachLB( $callback, $params = array() ) { 381 foreach ( $this->mainLBs as $lb ) { 382 call_user_func_array( $callback, array_merge( array( $lb ), $params ) ); 383 } 384 foreach ( $this->extLBs as $lb ) { 385 call_user_func_array( $callback, array_merge( array( $lb ), $params ) ); 386 } 387 } 388 389 function shutdown() { 390 foreach ( $this->mainLBs as $lb ) { 391 $this->chronProt->shutdownLB( $lb ); 392 } 393 foreach ( $this->extLBs as $extLB ) { 394 $this->chronProt->shutdownLB( $extLB ); 395 } 396 $this->chronProt->shutdown(); 397 $this->commitMasterChanges(); 398 } 399 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |