MediaWiki
REL1_19
|
00001 <?php 00045 class LBFactory_Multi extends LBFactory { 00046 // Required settings 00047 var $sectionsByDB, $sectionLoads, $serverTemplate; 00048 // Optional settings 00049 var $groupLoadsBySection = array(), $groupLoadsByDB = array(), $hostsByName = array(); 00050 var $externalLoads = array(), $externalTemplateOverrides, $templateOverridesByServer; 00051 var $templateOverridesByCluster, $masterTemplateOverrides, $readOnlyBySection = array(); 00052 // Other stuff 00053 var $conf, $mainLBs = array(), $extLBs = array(); 00054 var $lastWiki, $lastSection; 00055 00059 function __construct( $conf ) { 00060 $this->chronProt = new ChronologyProtector; 00061 $this->conf = $conf; 00062 $required = array( 'sectionsByDB', 'sectionLoads', 'serverTemplate' ); 00063 $optional = array( 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName', 00064 'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer', 00065 'templateOverridesByCluster', 'masterTemplateOverrides', 00066 'readOnlyBySection' ); 00067 00068 foreach ( $required as $key ) { 00069 if ( !isset( $conf[$key] ) ) { 00070 throw new MWException( __CLASS__.": $key is required in configuration" ); 00071 } 00072 $this->$key = $conf[$key]; 00073 } 00074 00075 foreach ( $optional as $key ) { 00076 if ( isset( $conf[$key] ) ) { 00077 $this->$key = $conf[$key]; 00078 } 00079 } 00080 00081 // Check for read-only mode 00082 $section = $this->getSectionForWiki(); 00083 if ( !empty( $this->readOnlyBySection[$section] ) ) { 00084 global $wgReadOnly; 00085 $wgReadOnly = $this->readOnlyBySection[$section]; 00086 } 00087 } 00088 00093 function getSectionForWiki( $wiki = false ) { 00094 if ( $this->lastWiki === $wiki ) { 00095 return $this->lastSection; 00096 } 00097 list( $dbName, ) = $this->getDBNameAndPrefix( $wiki ); 00098 if ( isset( $this->sectionsByDB[$dbName] ) ) { 00099 $section = $this->sectionsByDB[$dbName]; 00100 } else { 00101 $section = 'DEFAULT'; 00102 } 00103 $this->lastSection = $section; 00104 $this->lastWiki = $wiki; 00105 return $section; 00106 } 00107 00112 function newMainLB( $wiki = false ) { 00113 list( $dbName, ) = $this->getDBNameAndPrefix( $wiki ); 00114 $section = $this->getSectionForWiki( $wiki ); 00115 $groupLoads = array(); 00116 if ( isset( $this->groupLoadsByDB[$dbName] ) ) { 00117 $groupLoads = $this->groupLoadsByDB[$dbName]; 00118 } 00119 if ( isset( $this->groupLoadsBySection[$section] ) ) { 00120 $groupLoads = array_merge_recursive( $groupLoads, $this->groupLoadsBySection[$section] ); 00121 } 00122 return $this->newLoadBalancer( $this->serverTemplate, $this->sectionLoads[$section], $groupLoads ); 00123 } 00124 00129 function getMainLB( $wiki = false ) { 00130 $section = $this->getSectionForWiki( $wiki ); 00131 if ( !isset( $this->mainLBs[$section] ) ) { 00132 $lb = $this->newMainLB( $wiki, $section ); 00133 $this->chronProt->initLB( $lb ); 00134 $lb->parentInfo( array( 'id' => "main-$section" ) ); 00135 $this->mainLBs[$section] = $lb; 00136 } 00137 return $this->mainLBs[$section]; 00138 } 00139 00145 function newExternalLB( $cluster, $wiki = false ) { 00146 if ( !isset( $this->externalLoads[$cluster] ) ) { 00147 throw new MWException( __METHOD__.": Unknown cluster \"$cluster\"" ); 00148 } 00149 $template = $this->serverTemplate; 00150 if ( isset( $this->externalTemplateOverrides ) ) { 00151 $template = $this->externalTemplateOverrides + $template; 00152 } 00153 if ( isset( $this->templateOverridesByCluster[$cluster] ) ) { 00154 $template = $this->templateOverridesByCluster[$cluster] + $template; 00155 } 00156 return $this->newLoadBalancer( $template, $this->externalLoads[$cluster], array() ); 00157 } 00158 00164 function &getExternalLB( $cluster, $wiki = false ) { 00165 if ( !isset( $this->extLBs[$cluster] ) ) { 00166 $this->extLBs[$cluster] = $this->newExternalLB( $cluster, $wiki ); 00167 $this->extLBs[$cluster]->parentInfo( array( 'id' => "ext-$cluster" ) ); 00168 } 00169 return $this->extLBs[$cluster]; 00170 } 00171 00180 function newLoadBalancer( $template, $loads, $groupLoads ) { 00181 global $wgMasterWaitTimeout; 00182 $servers = $this->makeServerArray( $template, $loads, $groupLoads ); 00183 $lb = new LoadBalancer( array( 00184 'servers' => $servers, 00185 'masterWaitTimeout' => $wgMasterWaitTimeout 00186 )); 00187 return $lb; 00188 } 00189 00198 function makeServerArray( $template, $loads, $groupLoads ) { 00199 $servers = array(); 00200 $master = true; 00201 $groupLoadsByServer = $this->reindexGroupLoads( $groupLoads ); 00202 foreach ( $groupLoadsByServer as $server => $stuff ) { 00203 if ( !isset( $loads[$server] ) ) { 00204 $loads[$server] = 0; 00205 } 00206 } 00207 foreach ( $loads as $serverName => $load ) { 00208 $serverInfo = $template; 00209 if ( $master ) { 00210 $serverInfo['master'] = true; 00211 if ( isset( $this->masterTemplateOverrides ) ) { 00212 $serverInfo = $this->masterTemplateOverrides + $serverInfo; 00213 } 00214 $master = false; 00215 } 00216 if ( isset( $this->templateOverridesByServer[$serverName] ) ) { 00217 $serverInfo = $this->templateOverridesByServer[$serverName] + $serverInfo; 00218 } 00219 if ( isset( $groupLoadsByServer[$serverName] ) ) { 00220 $serverInfo['groupLoads'] = $groupLoadsByServer[$serverName]; 00221 } 00222 if ( isset( $this->hostsByName[$serverName] ) ) { 00223 $serverInfo['host'] = $this->hostsByName[$serverName]; 00224 } else { 00225 $serverInfo['host'] = $serverName; 00226 } 00227 $serverInfo['hostName'] = $serverName; 00228 $serverInfo['load'] = $load; 00229 $servers[] = $serverInfo; 00230 } 00231 return $servers; 00232 } 00233 00239 function reindexGroupLoads( $groupLoads ) { 00240 $reindexed = array(); 00241 foreach ( $groupLoads as $group => $loads ) { 00242 foreach ( $loads as $server => $load ) { 00243 $reindexed[$server][$group] = $load; 00244 } 00245 } 00246 return $reindexed; 00247 } 00248 00254 function getDBNameAndPrefix( $wiki = false ) { 00255 if ( $wiki === false ) { 00256 global $wgDBname, $wgDBprefix; 00257 return array( $wgDBname, $wgDBprefix ); 00258 } else { 00259 return wfSplitWikiID( $wiki ); 00260 } 00261 } 00262 00270 function forEachLB( $callback, $params = array() ) { 00271 foreach ( $this->mainLBs as $lb ) { 00272 call_user_func_array( $callback, array_merge( array( $lb ), $params ) ); 00273 } 00274 foreach ( $this->extLBs as $lb ) { 00275 call_user_func_array( $callback, array_merge( array( $lb ), $params ) ); 00276 } 00277 } 00278 00279 function shutdown() { 00280 foreach ( $this->mainLBs as $lb ) { 00281 $this->chronProt->shutdownLB( $lb ); 00282 } 00283 $this->chronProt->shutdown(); 00284 $this->commitMasterChanges(); 00285 } 00286 }