r32818 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r32817‎ | r32818 | r32819 >
Date:18:11, 5 April 2008
Author:tstarling
Status:old
Tags:
Comment:
* Generalised FileRepoStatus, providing a very similar general Status object.
* Fixed external storage in LBFactory_Multi, was broken
* Useful debugging hack $wgAllDBsAreLocalhost
Modified paths:
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/Database.php (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/LBFactory_Multi.php (modified) (history)
  • /trunk/phase3/includes/Status.php (added) (history)
  • /trunk/phase3/includes/filerepo/FileRepoStatus.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/AutoLoader.php
@@ -242,6 +242,7 @@
243243 'SpecialVersion' => 'includes/SpecialVersion.php',
244244 'SqlBagOStuff' => 'includes/BagOStuff.php',
245245 'SquidUpdate' => 'includes/SquidUpdate.php',
 246+ 'Status' => 'includes/Status.php',
246247 'StringUtils' => 'includes/StringUtils.php',
247248 'TableDiffFormatter' => 'includes/DifferenceEngine.php',
248249 'TablePager' => 'includes/Pager.php',
Index: trunk/phase3/includes/filerepo/FileRepoStatus.php
@@ -1,19 +1,9 @@
22 <?php
33
44 /**
5 - * Generic operation result class
6 - * Has warning/error list, boolean status and arbitrary value
 5+ * Generic operation result class for FileRepo-related operations
76 */
8 -class FileRepoStatus {
9 - var $ok = true;
10 - var $value;
11 -
12 - /** Counters for batch operations */
13 - var $successCount = 0, $failCount = 0;
14 -
15 - /*semi-private*/ var $errors = array();
16 - /*semi-private*/ var $cleanCallback = false;
17 -
 7+class FileRepoStatus extends Status {
188 /**
199 * Factory function for fatal errors
2010 */
@@ -36,136 +26,4 @@
3727 $this->cleanCallback = $repo->getErrorCleanupFunction();
3828 }
3929 }
40 -
41 - function setResult( $ok, $value = null ) {
42 - $this->ok = $ok;
43 - $this->value = $value;
44 - }
45 -
46 - function isGood() {
47 - return $this->ok && !$this->errors;
48 - }
49 -
50 - function isOK() {
51 - return $this->ok;
52 - }
53 -
54 - function warning( $message /*, parameters... */ ) {
55 - $params = array_slice( func_get_args(), 1 );
56 - $this->errors[] = array(
57 - 'type' => 'warning',
58 - 'message' => $message,
59 - 'params' => $params );
60 - }
61 -
62 - /**
63 - * Add an error, do not set fatal flag
64 - * This can be used for non-fatal errors
65 - */
66 - function error( $message /*, parameters... */ ) {
67 - $params = array_slice( func_get_args(), 1 );
68 - $this->errors[] = array(
69 - 'type' => 'error',
70 - 'message' => $message,
71 - 'params' => $params );
72 - }
73 -
74 - /**
75 - * Add an error and set OK to false, indicating that the operation as a whole was fatal
76 - */
77 - function fatal( $message /*, parameters... */ ) {
78 - $params = array_slice( func_get_args(), 1 );
79 - $this->errors[] = array(
80 - 'type' => 'error',
81 - 'message' => $message,
82 - 'params' => $params );
83 - $this->ok = false;
84 - }
85 -
86 - protected function cleanParams( $params ) {
87 - if ( !$this->cleanCallback ) {
88 - return $params;
89 - }
90 - $cleanParams = array();
91 - foreach ( $params as $i => $param ) {
92 - $cleanParams[$i] = call_user_func( $this->cleanCallback, $param );
93 - }
94 - return $cleanParams;
95 - }
96 -
97 - protected function getItemXML( $item ) {
98 - $params = $this->cleanParams( $item['params'] );
99 - $xml = "<{$item['type']}>\n" .
100 - Xml::element( 'message', null, $item['message'] ) . "\n" .
101 - Xml::element( 'text', null, wfMsgReal( $item['message'], $params ) ) ."\n";
102 - foreach ( $params as $param ) {
103 - $xml .= Xml::element( 'param', null, $param );
104 - }
105 - $xml .= "</{$this->type}>\n";
106 - return $xml;
107 - }
108 -
109 - /**
110 - * Get the error list as XML
111 - */
112 - function getXML() {
113 - $xml = "<errors>\n";
114 - foreach ( $this->errors as $error ) {
115 - $xml .= $this->getItemXML( $error );
116 - }
117 - $xml .= "</errors>\n";
118 - return $xml;
119 - }
120 -
121 - /**
122 - * Get the error list as a wikitext formatted list
123 - * @param string $shortContext A short enclosing context message name, to be used
124 - * when there is a single error
125 - * @param string $longContext A long enclosing context message name, for a list
126 - */
127 - function getWikiText( $shortContext = false, $longContext = false ) {
128 - if ( count( $this->errors ) == 0 ) {
129 - if ( $this->ok ) {
130 - $this->fatal( 'internalerror_info',
131 - __METHOD__." called for a good result, this is incorrect\n" );
132 - } else {
133 - $this->fatal( 'internalerror_info',
134 - __METHOD__.": Invalid result object: no error text but not OK\n" );
135 - }
136 - }
137 - if ( count( $this->errors ) == 1 ) {
138 - $params = array_map( 'wfEscapeWikiText', $this->cleanParams( $this->errors[0]['params'] ) );
139 - $s = wfMsgReal( $this->errors[0]['message'], $params, true, false, false );
140 - if ( $shortContext ) {
141 - $s = wfMsgNoTrans( $shortContext, $s );
142 - } elseif ( $longContext ) {
143 - $s = wfMsgNoTrans( $longContext, "* $s\n" );
144 - }
145 - } else {
146 - $s = '';
147 - foreach ( $this->errors as $error ) {
148 - $params = array_map( 'wfEscapeWikiText', $this->cleanParams( $error['params'] ) );
149 - $s .= '* ' . wfMsgReal( $error['message'], $params, true, false, false ) . "\n";
150 - }
151 - if ( $longContext ) {
152 - $s = wfMsgNoTrans( $longContext, $s );
153 - } elseif ( $shortContext ) {
154 - $s = wfMsgNoTrans( $shortContext, "\n* $s\n" );
155 - }
156 - }
157 - return $s;
158 - }
159 -
160 - /**
161 - * Merge another status object into this one
162 - */
163 - function merge( $other, $overwriteValue = false ) {
164 - $this->errors = array_merge( $this->errors, $other->errors );
165 - $this->ok = $this->ok && $other->ok;
166 - if ( $overwriteValue ) {
167 - $this->value = $other->value;
168 - }
169 - $this->successCount += $other->successCount;
170 - $this->failCount += $other->failCount;
171 - }
17230 }
Index: trunk/phase3/includes/Status.php
@@ -0,0 +1,174 @@
 2+<?php
 3+
 4+/**
 5+ * Generic operation result class
 6+ * Has warning/error list, boolean status and arbitrary value
 7+ *
 8+ * "Good" means the operation was completed with no warnings or errors.
 9+ *
 10+ * "OK" means the operation was partially or wholly completed.
 11+ *
 12+ * An operation which is not OK should have errors so that the user can be
 13+ * informed as to what went wrong. Calling the fatal() function sets an error
 14+ * message and simultaneously switches off the OK flag.
 15+ */
 16+class Status {
 17+ var $ok = true;
 18+ var $value;
 19+
 20+ /** Counters for batch operations */
 21+ var $successCount = 0, $failCount = 0;
 22+
 23+ /*semi-private*/ var $errors = array();
 24+ /*semi-private*/ var $cleanCallback = false;
 25+
 26+ /**
 27+ * Factory function for fatal errors
 28+ */
 29+ static function newFatal( $message /*, parameters...*/ ) {
 30+ $params = func_get_args();
 31+ $result = new self;
 32+ call_user_func_array( array( &$result, 'error' ), $params );
 33+ $result->ok = false;
 34+ return $result;
 35+ }
 36+
 37+ static function newGood( $value = null ) {
 38+ $result = new self;
 39+ $result->value = $value;
 40+ return $result;
 41+ }
 42+
 43+ function setResult( $ok, $value = null ) {
 44+ $this->ok = $ok;
 45+ $this->value = $value;
 46+ }
 47+
 48+ function isGood() {
 49+ return $this->ok && !$this->errors;
 50+ }
 51+
 52+ function isOK() {
 53+ return $this->ok;
 54+ }
 55+
 56+ function warning( $message /*, parameters... */ ) {
 57+ $params = array_slice( func_get_args(), 1 );
 58+ $this->errors[] = array(
 59+ 'type' => 'warning',
 60+ 'message' => $message,
 61+ 'params' => $params );
 62+ }
 63+
 64+ /**
 65+ * Add an error, do not set fatal flag
 66+ * This can be used for non-fatal errors
 67+ */
 68+ function error( $message /*, parameters... */ ) {
 69+ $params = array_slice( func_get_args(), 1 );
 70+ $this->errors[] = array(
 71+ 'type' => 'error',
 72+ 'message' => $message,
 73+ 'params' => $params );
 74+ }
 75+
 76+ /**
 77+ * Add an error and set OK to false, indicating that the operation as a whole was fatal
 78+ */
 79+ function fatal( $message /*, parameters... */ ) {
 80+ $params = array_slice( func_get_args(), 1 );
 81+ $this->errors[] = array(
 82+ 'type' => 'error',
 83+ 'message' => $message,
 84+ 'params' => $params );
 85+ $this->ok = false;
 86+ }
 87+
 88+ protected function cleanParams( $params ) {
 89+ if ( !$this->cleanCallback ) {
 90+ return $params;
 91+ }
 92+ $cleanParams = array();
 93+ foreach ( $params as $i => $param ) {
 94+ $cleanParams[$i] = call_user_func( $this->cleanCallback, $param );
 95+ }
 96+ return $cleanParams;
 97+ }
 98+
 99+ protected function getItemXML( $item ) {
 100+ $params = $this->cleanParams( $item['params'] );
 101+ $xml = "<{$item['type']}>\n" .
 102+ Xml::element( 'message', null, $item['message'] ) . "\n" .
 103+ Xml::element( 'text', null, wfMsgReal( $item['message'], $params ) ) ."\n";
 104+ foreach ( $params as $param ) {
 105+ $xml .= Xml::element( 'param', null, $param );
 106+ }
 107+ $xml .= "</{$this->type}>\n";
 108+ return $xml;
 109+ }
 110+
 111+ /**
 112+ * Get the error list as XML
 113+ */
 114+ function getXML() {
 115+ $xml = "<errors>\n";
 116+ foreach ( $this->errors as $error ) {
 117+ $xml .= $this->getItemXML( $error );
 118+ }
 119+ $xml .= "</errors>\n";
 120+ return $xml;
 121+ }
 122+
 123+ /**
 124+ * Get the error list as a wikitext formatted list
 125+ * @param string $shortContext A short enclosing context message name, to be used
 126+ * when there is a single error
 127+ * @param string $longContext A long enclosing context message name, for a list
 128+ */
 129+ function getWikiText( $shortContext = false, $longContext = false ) {
 130+ if ( count( $this->errors ) == 0 ) {
 131+ if ( $this->ok ) {
 132+ $this->fatal( 'internalerror_info',
 133+ __METHOD__." called for a good result, this is incorrect\n" );
 134+ } else {
 135+ $this->fatal( 'internalerror_info',
 136+ __METHOD__.": Invalid result object: no error text but not OK\n" );
 137+ }
 138+ }
 139+ if ( count( $this->errors ) == 1 ) {
 140+ $params = array_map( 'wfEscapeWikiText', $this->cleanParams( $this->errors[0]['params'] ) );
 141+ $s = wfMsgReal( $this->errors[0]['message'], $params, true, false, false );
 142+ if ( $shortContext ) {
 143+ $s = wfMsgNoTrans( $shortContext, $s );
 144+ } elseif ( $longContext ) {
 145+ $s = wfMsgNoTrans( $longContext, "* $s\n" );
 146+ }
 147+ } else {
 148+ $s = '';
 149+ foreach ( $this->errors as $error ) {
 150+ $params = array_map( 'wfEscapeWikiText', $this->cleanParams( $error['params'] ) );
 151+ $s .= '* ' . wfMsgReal( $error['message'], $params, true, false, false ) . "\n";
 152+ }
 153+ if ( $longContext ) {
 154+ $s = wfMsgNoTrans( $longContext, $s );
 155+ } elseif ( $shortContext ) {
 156+ $s = wfMsgNoTrans( $shortContext, "\n* $s\n" );
 157+ }
 158+ }
 159+ return $s;
 160+ }
 161+
 162+ /**
 163+ * Merge another status object into this one
 164+ */
 165+ function merge( $other, $overwriteValue = false ) {
 166+ $this->errors = array_merge( $this->errors, $other->errors );
 167+ $this->ok = $this->ok && $other->ok;
 168+ if ( $overwriteValue ) {
 169+ $this->value = $other->value;
 170+ }
 171+ $this->successCount += $other->successCount;
 172+ $this->failCount += $other->failCount;
 173+ }
 174+}
 175+
Index: trunk/phase3/includes/Database.php
@@ -295,7 +295,7 @@
296296 * If the failFunction is set to a non-zero integer, returns success
297297 */
298298 function open( $server, $user, $password, $dbName ) {
299 - global $wguname;
 299+ global $wguname, $wgAllDBsAreLocalhost;
300300 wfProfileIn( __METHOD__ );
301301
302302 # Test for missing mysql.so
@@ -310,6 +310,12 @@
311311 throw new DBConnectionError( $this, "MySQL functions missing, have you compiled PHP with the --with-mysql option?\n" );
312312 }
313313
 314+ # Debugging hack -- fake cluster
 315+ if ( $wgAllDBsAreLocalhost ) {
 316+ $realServer = 'localhost';
 317+ } else {
 318+ $realServer = $server;
 319+ }
314320 $this->close();
315321 $this->mServer = $server;
316322 $this->mUser = $user;
@@ -330,10 +336,10 @@
331337 usleep( 1000 );
332338 }
333339 if ( $this->mFlags & DBO_PERSISTENT ) {
334 - @/**/$this->mConn = mysql_pconnect( $server, $user, $password );
 340+ @/**/$this->mConn = mysql_pconnect( $realServer, $user, $password );
335341 } else {
336342 # Create a new connection...
337 - @/**/$this->mConn = mysql_connect( $server, $user, $password, true );
 343+ @/**/$this->mConn = mysql_connect( $realServer, $user, $password, true );
338344 }
339345 if ($this->mConn === false) {
340346 #$iplus = $i + 1;
Index: trunk/phase3/includes/DefaultSettings.php
@@ -565,6 +565,13 @@
566566 /** MySQL table options to use during installation or update */
567567 $wgDBTableOptions = 'TYPE=InnoDB';
568568
 569+/**
 570+ * Make all database connections secretly go to localhost. Fool the load balancer
 571+ * thinking there is an arbitrarily large cluster of servers to connect to.
 572+ * Useful for debugging.
 573+ */
 574+$wgAllDBsAreLocalhost = false;
 575+
569576 /**#@-*/
570577
571578
@@ -2663,6 +2670,7 @@
26642671 /**
26652672 * An array of external mysql servers, e.g.
26662673 * $wgExternalServers = array( 'cluster1' => array( 'srv28', 'srv29', 'srv30' ) );
 2674+ * Used by LBFactory_Simple, may be ignored if $wgLBFactoryConf is set to another class.
26672675 */
26682676 $wgExternalServers = array();
26692677
Index: trunk/phase3/includes/LBFactory_Multi.php
@@ -5,15 +5,15 @@
66 * Ignores the old configuration globals
77 *
88 * Configuration:
9 - * sectionsByDB A map of database names to section names
 9+ * sectionsByDB A map of database names to section names
1010 *
1111 * sectionLoads A 2-d map. For each section, gives a map of server names to load ratios.
1212 * For example: array( 'section1' => array( 'db1' => 100, 'db2' => 100 ) )
1313 *
14 - * mainTemplate A server info associative array as documented for $wgDBservers. The host,
 14+ * serverTemplate A server info associative array as documented for $wgDBservers. The host,
1515 * hostName and load entries will be overridden.
1616 *
17 - * groupLoadsBySection A 3-d map giving server load ratios for each section and group. For example:
 17+ * groupLoadsBySection A 3-d map giving server load ratios for each section and group. For example:
1818 * array( 'section1' => array( 'group1' => array( 'db1' => 100, 'db2' => 100 ) ) )
1919 *
2020 * groupLoadsByDB A 3-d map giving server load ratios by DB name.
@@ -22,23 +22,22 @@
2323 *
2424 * externalLoads A map of external storage cluster name to server load map
2525 *
26 - * externalTemplate A server info structure used for external storage servers
 26+ * externalTemplateOverrides A set of server info keys overriding serverTemplate for external storage
2727 *
28 - * templateOverridesByServer A 2-d map overriding mainTemplate or externalTemplate on a
29 - * server-by-server basis.
 28+ * templateOverridesByServer A 2-d map overriding serverTemplate and externalTemplateOverrides on a
 29+ * server-by-server basis. Applies to both core and external storage.
3030 *
31 - * templateOverridesByCluster A 2-d map overriding externalTemplate by cluster
 31+ * templateOverridesByCluster A 2-d map overriding the server info by external storage cluster
3232 *
33 - * masterTemplateOverrides An override array for mainTemplate and externalTemplate for all
34 - * master servers.
 33+ * masterTemplateOverrides An override array for all master servers.
3534 *
3635 */
3736 class LBFactory_Multi extends LBFactory {
3837 // Required settings
39 - var $sectionsByDB, $sectionLoads, $mainTemplate;
 38+ var $sectionsByDB, $sectionLoads, $serverTemplate;
4039 // Optional settings
4140 var $groupLoadsBySection = array(), $groupLoadsByDB = array(), $hostsByName = array();
42 - var $externalLoads = array(), $externalTemplate, $templateOverridesByServer;
 41+ var $externalLoads = array(), $externalTemplateOverrides, $templateOverridesByServer;
4342 var $templateOverridesByCluster, $masterTemplateOverrides;
4443 // Other stuff
4544 var $conf, $mainLBs = array(), $extLBs = array();
@@ -47,9 +46,9 @@
4847 function __construct( $conf ) {
4948 $this->chronProt = new ChronologyProtector;
5049 $this->conf = $conf;
51 - $required = array( 'sectionsByDB', 'sectionLoads', 'mainTemplate' );
 50+ $required = array( 'sectionsByDB', 'sectionLoads', 'serverTemplate' );
5251 $optional = array( 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName',
53 - 'externalLoads', 'externalTemplate', 'templateOverridesByServer',
 52+ 'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer',
5453 'templateOverridesByCluster', 'masterTemplateOverrides' );
5554
5655 foreach ( $required as $key ) {
@@ -95,7 +94,7 @@
9695 if ( isset( $this->groupLoadsBySection[$section] ) ) {
9796 $groupLoads = array_merge_recursive( $groupLoads, $this->groupLoadsBySection[$section] );
9897 }
99 - $this->mainLBs[$section] = $this->newLoadBalancer( $this->mainTemplate,
 98+ $this->mainLBs[$section] = $this->newLoadBalancer( $this->serverTemplate,
10099 $this->sectionLoads[$section], $groupLoads, "main-$section" );
101100 $this->chronProt->initLB( $this->mainLBs[$section] );
102101 }
@@ -107,12 +106,12 @@
108107 if ( !isset( $this->externalLoads[$cluster] ) ) {
109108 throw new MWException( __METHOD__.": Unknown cluster \"$cluster\"" );
110109 }
 110+ $template = $this->serverTemplate;
 111+ if ( isset( $this->externalTemplateOverrides ) ) {
 112+ $template = $this->externalTemplateOverrides + $template;
 113+ }
111114 if ( isset( $this->templateOverridesByCluster[$cluster] ) ) {
112 - $template = $this->templateOverridesByCluster[$cluster];
113 - } elseif ( isset( $this->externalTemplate ) ) {
114 - $template = $this->externalTemplate;
115 - } else {
116 - $template = $this->mainTemplate;
 115+ $template = $this->templateOverridesByCluster[$cluster] + $template;
117116 }
118117 $this->extLBs[$cluster] = $this->newLoadBalancer( $template,
119118 $this->externalLoads[$cluster], array(), "ext-$cluster" );

Status & tagging log