[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Generator of database load balancing objects. 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 * An interface for generating database load balancers 26 * @ingroup Database 27 */ 28 abstract class LBFactory { 29 /** @var LBFactory */ 30 protected static $instance; 31 32 /** 33 * Disables all access to the load balancer, will cause all database access 34 * to throw a DBAccessError 35 */ 36 public static function disableBackend() { 37 global $wgLBFactoryConf; 38 self::$instance = new LBFactoryFake( $wgLBFactoryConf ); 39 } 40 41 /** 42 * Get an LBFactory instance 43 * 44 * @return LBFactory 45 */ 46 static function &singleton() { 47 global $wgLBFactoryConf; 48 49 if ( is_null( self::$instance ) ) { 50 $class = self::getLBFactoryClass( $wgLBFactoryConf ); 51 52 self::$instance = new $class( $wgLBFactoryConf ); 53 } 54 55 return self::$instance; 56 } 57 58 /** 59 * Returns the LBFactory class to use and the load balancer configuration. 60 * 61 * @param array $config (e.g. $wgLBFactoryConf) 62 * @return string Class name 63 */ 64 public static function getLBFactoryClass( array $config ) { 65 // For configuration backward compatibility after removing 66 // underscores from class names in MediaWiki 1.23. 67 $bcClasses = array( 68 'LBFactory_Simple' => 'LBFactorySimple', 69 'LBFactory_Single' => 'LBFactorySingle', 70 'LBFactory_Multi' => 'LBFactoryMulti', 71 'LBFactory_Fake' => 'LBFactoryFake', 72 ); 73 74 $class = $config['class']; 75 76 if ( isset( $bcClasses[$class] ) ) { 77 $class = $bcClasses[$class]; 78 wfDeprecated( 79 '$wgLBFactoryConf must be updated. See RELEASE-NOTES for details', 80 '1.23' 81 ); 82 } 83 84 return $class; 85 } 86 87 /** 88 * Shut down, close connections and destroy the cached instance. 89 */ 90 static function destroyInstance() { 91 if ( self::$instance ) { 92 self::$instance->shutdown(); 93 self::$instance->forEachLBCallMethod( 'closeAll' ); 94 self::$instance = null; 95 } 96 } 97 98 /** 99 * Set the instance to be the given object 100 * 101 * @param LBFactory $instance 102 */ 103 static function setInstance( $instance ) { 104 self::destroyInstance(); 105 self::$instance = $instance; 106 } 107 108 /** 109 * Construct a factory based on a configuration array (typically from $wgLBFactoryConf) 110 * @param array $conf 111 */ 112 abstract function __construct( $conf ); 113 114 /** 115 * Create a new load balancer object. The resulting object will be untracked, 116 * not chronology-protected, and the caller is responsible for cleaning it up. 117 * 118 * @param bool|string $wiki Wiki ID, or false for the current wiki 119 * @return LoadBalancer 120 */ 121 abstract function newMainLB( $wiki = false ); 122 123 /** 124 * Get a cached (tracked) load balancer object. 125 * 126 * @param bool|string $wiki Wiki ID, or false for the current wiki 127 * @return LoadBalancer 128 */ 129 abstract function getMainLB( $wiki = false ); 130 131 /** 132 * Create a new load balancer for external storage. The resulting object will be 133 * untracked, not chronology-protected, and the caller is responsible for 134 * cleaning it up. 135 * 136 * @param string $cluster External storage cluster, or false for core 137 * @param bool|string $wiki Wiki ID, or false for the current wiki 138 * @return LoadBalancer 139 */ 140 abstract function newExternalLB( $cluster, $wiki = false ); 141 142 /** 143 * Get a cached (tracked) load balancer for external storage 144 * 145 * @param string $cluster External storage cluster, or false for core 146 * @param bool|string $wiki Wiki ID, or false for the current wiki 147 * @return LoadBalancer 148 */ 149 abstract function &getExternalLB( $cluster, $wiki = false ); 150 151 /** 152 * Execute a function for each tracked load balancer 153 * The callback is called with the load balancer as the first parameter, 154 * and $params passed as the subsequent parameters. 155 * 156 * @param callable $callback 157 * @param array $params 158 */ 159 abstract function forEachLB( $callback, $params = array() ); 160 161 /** 162 * Prepare all tracked load balancers for shutdown 163 * STUB 164 */ 165 function shutdown() { 166 } 167 168 /** 169 * Call a method of each tracked load balancer 170 * 171 * @param string $methodName 172 * @param array $args 173 */ 174 function forEachLBCallMethod( $methodName, $args = array() ) { 175 $this->forEachLB( array( $this, 'callMethod' ), array( $methodName, $args ) ); 176 } 177 178 /** 179 * Private helper for forEachLBCallMethod 180 * @param LoadBalancer $loadBalancer 181 * @param string $methodName 182 * @param array $args 183 */ 184 function callMethod( $loadBalancer, $methodName, $args ) { 185 call_user_func_array( array( $loadBalancer, $methodName ), $args ); 186 } 187 188 /** 189 * Commit changes on all master connections 190 */ 191 function commitMasterChanges() { 192 $this->forEachLBCallMethod( 'commitMasterChanges' ); 193 } 194 195 /** 196 * Rollback changes on all master connections 197 * @since 1.23 198 */ 199 function rollbackMasterChanges() { 200 $this->forEachLBCallMethod( 'rollbackMasterChanges' ); 201 } 202 203 /** 204 * Detemine if any master connection has pending changes. 205 * @since 1.23 206 * @return bool 207 */ 208 function hasMasterChanges() { 209 $ret = false; 210 $this->forEachLB( function ( $lb ) use ( &$ret ) { 211 $ret = $ret || $lb->hasMasterChanges(); 212 } ); 213 return $ret; 214 } 215 } 216 217 /** 218 * A simple single-master LBFactory that gets its configuration from the b/c globals 219 */ 220 class LBFactorySimple extends LBFactory { 221 /** @var LoadBalancer */ 222 protected $mainLB; 223 224 /** @var LoadBalancer[] */ 225 protected $extLBs = array(); 226 227 /** @var ChronologyProtector */ 228 protected $chronProt; 229 230 function __construct( $conf ) { 231 $this->chronProt = new ChronologyProtector; 232 } 233 234 /** 235 * @param bool|string $wiki 236 * @return LoadBalancer 237 */ 238 function newMainLB( $wiki = false ) { 239 global $wgDBservers; 240 if ( $wgDBservers ) { 241 $servers = $wgDBservers; 242 } else { 243 global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype, $wgDebugDumpSql; 244 global $wgDBssl, $wgDBcompress; 245 246 $flags = DBO_DEFAULT; 247 if ( $wgDebugDumpSql ) { 248 $flags |= DBO_DEBUG; 249 } 250 if ( $wgDBssl ) { 251 $flags |= DBO_SSL; 252 } 253 if ( $wgDBcompress ) { 254 $flags |= DBO_COMPRESS; 255 } 256 257 $servers = array( array( 258 'host' => $wgDBserver, 259 'user' => $wgDBuser, 260 'password' => $wgDBpassword, 261 'dbname' => $wgDBname, 262 'type' => $wgDBtype, 263 'load' => 1, 264 'flags' => $flags 265 ) ); 266 } 267 268 return new LoadBalancer( array( 269 'servers' => $servers, 270 ) ); 271 } 272 273 /** 274 * @param bool|string $wiki 275 * @return LoadBalancer 276 */ 277 function getMainLB( $wiki = false ) { 278 if ( !isset( $this->mainLB ) ) { 279 $this->mainLB = $this->newMainLB( $wiki ); 280 $this->mainLB->parentInfo( array( 'id' => 'main' ) ); 281 $this->chronProt->initLB( $this->mainLB ); 282 } 283 284 return $this->mainLB; 285 } 286 287 /** 288 * @throws MWException 289 * @param string $cluster 290 * @param bool|string $wiki 291 * @return LoadBalancer 292 */ 293 function newExternalLB( $cluster, $wiki = false ) { 294 global $wgExternalServers; 295 if ( !isset( $wgExternalServers[$cluster] ) ) { 296 throw new MWException( __METHOD__ . ": Unknown cluster \"$cluster\"" ); 297 } 298 299 return new LoadBalancer( array( 300 'servers' => $wgExternalServers[$cluster] 301 ) ); 302 } 303 304 /** 305 * @param string $cluster 306 * @param bool|string $wiki 307 * @return array 308 */ 309 function &getExternalLB( $cluster, $wiki = false ) { 310 if ( !isset( $this->extLBs[$cluster] ) ) { 311 $this->extLBs[$cluster] = $this->newExternalLB( $cluster, $wiki ); 312 $this->extLBs[$cluster]->parentInfo( array( 'id' => "ext-$cluster" ) ); 313 $this->chronProt->initLB( $this->extLBs[$cluster] ); 314 } 315 316 return $this->extLBs[$cluster]; 317 } 318 319 /** 320 * Execute a function for each tracked load balancer 321 * The callback is called with the load balancer as the first parameter, 322 * and $params passed as the subsequent parameters. 323 * 324 * @param callable $callback 325 * @param array $params 326 */ 327 function forEachLB( $callback, $params = array() ) { 328 if ( isset( $this->mainLB ) ) { 329 call_user_func_array( $callback, array_merge( array( $this->mainLB ), $params ) ); 330 } 331 foreach ( $this->extLBs as $lb ) { 332 call_user_func_array( $callback, array_merge( array( $lb ), $params ) ); 333 } 334 } 335 336 function shutdown() { 337 if ( $this->mainLB ) { 338 $this->chronProt->shutdownLB( $this->mainLB ); 339 } 340 foreach ( $this->extLBs as $extLB ) { 341 $this->chronProt->shutdownLB( $extLB ); 342 } 343 $this->chronProt->shutdown(); 344 $this->commitMasterChanges(); 345 } 346 } 347 348 /** 349 * LBFactory class that throws an error on any attempt to use it. 350 * This will typically be done via wfGetDB(). 351 * Call LBFactory::disableBackend() to start using this, and 352 * LBFactory::enableBackend() to return to normal behavior 353 */ 354 class LBFactoryFake extends LBFactory { 355 function __construct( $conf ) { 356 } 357 358 function newMainLB( $wiki = false ) { 359 throw new DBAccessError; 360 } 361 362 function getMainLB( $wiki = false ) { 363 throw new DBAccessError; 364 } 365 366 function newExternalLB( $cluster, $wiki = false ) { 367 throw new DBAccessError; 368 } 369 370 function &getExternalLB( $cluster, $wiki = false ) { 371 throw new DBAccessError; 372 } 373 374 function forEachLB( $callback, $params = array() ) { 375 } 376 } 377 378 /** 379 * Exception class for attempted DB access 380 */ 381 class DBAccessError extends MWException { 382 function __construct() { 383 parent::__construct( "Mediawiki tried to access the database via wfGetDB(). " . 384 "This is not allowed." ); 385 } 386 }
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 |