* Generalised FileRepoStatus, providing a very similar general Status object.
authorTim Starling <tstarling@users.mediawiki.org>
Sat, 5 Apr 2008 18:11:23 +0000 (18:11 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Sat, 5 Apr 2008 18:11:23 +0000 (18:11 +0000)
* Fixed external storage in LBFactory_Multi, was broken
* Useful debugging hack $wgAllDBsAreLocalhost

includes/AutoLoader.php
includes/Database.php
includes/DefaultSettings.php
includes/LBFactory_Multi.php
includes/Status.php [new file with mode: 0644]
includes/filerepo/FileRepoStatus.php

index ebf166c..0aa929a 100644 (file)
@@ -242,6 +242,7 @@ function __autoload($className) {
                'SpecialVersion' => 'includes/SpecialVersion.php',
                'SqlBagOStuff' => 'includes/BagOStuff.php',
                'SquidUpdate' => 'includes/SquidUpdate.php',
+               'Status' => 'includes/Status.php',
                'StringUtils' => 'includes/StringUtils.php',
                'TableDiffFormatter' => 'includes/DifferenceEngine.php',
                'TablePager' => 'includes/Pager.php',
index 1e247b4..486877f 100644 (file)
@@ -295,7 +295,7 @@ class Database {
         * If the failFunction is set to a non-zero integer, returns success
         */
        function open( $server, $user, $password, $dbName ) {
-               global $wguname;
+               global $wguname, $wgAllDBsAreLocalhost;
                wfProfileIn( __METHOD__ );
 
                # Test for missing mysql.so
@@ -310,6 +310,12 @@ class Database {
                        throw new DBConnectionError( $this, "MySQL functions missing, have you compiled PHP with the --with-mysql option?\n" );
                }
 
+               # Debugging hack -- fake cluster
+               if ( $wgAllDBsAreLocalhost ) {
+                       $realServer = 'localhost';
+               } else {
+                       $realServer = $server;
+               }
                $this->close();
                $this->mServer = $server;
                $this->mUser = $user;
@@ -330,10 +336,10 @@ class Database {
                                usleep( 1000 );
                        }
                        if ( $this->mFlags & DBO_PERSISTENT ) {
-                               @/**/$this->mConn = mysql_pconnect( $server, $user, $password );
+                               @/**/$this->mConn = mysql_pconnect( $realServer, $user, $password );
                        } else {
                                # Create a new connection...
-                               @/**/$this->mConn = mysql_connect( $server, $user, $password, true );
+                               @/**/$this->mConn = mysql_connect( $realServer, $user, $password, true );
                        }
                        if ($this->mConn === false) {
                                #$iplus = $i + 1;
index 4d578a1..ca8065d 100644 (file)
@@ -565,6 +565,13 @@ $wgDBprefix         = '';
 /** MySQL table options to use during installation or update */
 $wgDBTableOptions = 'TYPE=InnoDB';
 
+/**
+ * Make all database connections secretly go to localhost. Fool the load balancer
+ * thinking there is an arbitrarily large cluster of servers to connect to. 
+ * Useful for debugging.
+ */
+$wgAllDBsAreLocalhost = false;
+
 /**#@-*/
 
 
@@ -2663,6 +2670,7 @@ $wgExternalStores = false;
 /**
  * An array of external mysql servers, e.g.
  * $wgExternalServers = array( 'cluster1' => array( 'srv28', 'srv29', 'srv30' ) );
+ * Used by LBFactory_Simple, may be ignored if $wgLBFactoryConf is set to another class.
  */
 $wgExternalServers = array();
 
index 788a28c..c0f8289 100644 (file)
@@ -5,15 +5,15 @@
  * Ignores the old configuration globals
  *
  * Configuration: 
- *     sectionsByDB                       A map of database names to section names
+ *     sectionsByDB                A map of database names to section names
  *
  *     sectionLoads                A 2-d map. For each section, gives a map of server names to load ratios.
  *                                 For example: array( 'section1' => array( 'db1' => 100, 'db2' => 100 ) )
  *
- *     mainTemplate                A server info associative array as documented for $wgDBservers. The host,
+ *     serverTemplate              A server info associative array as documented for $wgDBservers. The host,
  *                                 hostName and load entries will be overridden.
  *
- *     groupLoadsBySection            A 3-d map giving server load ratios for each section and group. For example:
+ *     groupLoadsBySection         A 3-d map giving server load ratios for each section and group. For example:
  *                                 array( 'section1' => array( 'group1' => array( 'db1' => 100, 'db2' => 100 ) ) )
  *
  *     groupLoadsByDB              A 3-d map giving server load ratios by DB name.
  *
  *     externalLoads               A map of external storage cluster name to server load map
  *
- *     externalTemplate            A server info structure used for external storage servers
+ *     externalTemplateOverrides   A set of server info keys overriding serverTemplate for external storage
  *
- *     templateOverridesByServer   A 2-d map overriding mainTemplate or externalTemplate on a 
- *                                 server-by-server basis.
+ *     templateOverridesByServer   A 2-d map overriding serverTemplate and externalTemplateOverrides on a 
+ *                                 server-by-server basis. Applies to both core and external storage.
  *
- *     templateOverridesByCluster  A 2-d map overriding externalTemplate by cluster
+ *     templateOverridesByCluster  A 2-d map overriding the server info by external storage cluster
  *
- *     masterTemplateOverrides     An override array for mainTemplate and externalTemplate for all
- *                                 master servers.
+ *     masterTemplateOverrides     An override array for all master servers.
  *
  */
 class LBFactory_Multi extends LBFactory {
        // Required settings
-       var $sectionsByDB, $sectionLoads, $mainTemplate;
+       var $sectionsByDB, $sectionLoads, $serverTemplate;
        // Optional settings
        var $groupLoadsBySection = array(), $groupLoadsByDB = array(), $hostsByName = array();
-       var $externalLoads = array(), $externalTemplate, $templateOverridesByServer;
+       var $externalLoads = array(), $externalTemplateOverrides, $templateOverridesByServer;
        var $templateOverridesByCluster, $masterTemplateOverrides;
        // Other stuff
        var $conf, $mainLBs = array(), $extLBs = array();
@@ -47,9 +46,9 @@ class LBFactory_Multi extends LBFactory {
        function __construct( $conf ) {
                $this->chronProt = new ChronologyProtector;
                $this->conf = $conf;
-               $required = array( 'sectionsByDB', 'sectionLoads', 'mainTemplate' );
+               $required = array( 'sectionsByDB', 'sectionLoads', 'serverTemplate' );
                $optional = array( 'groupLoadsBySection', 'groupLoadsByDB', 'hostsByName', 
-                       'externalLoads', 'externalTemplate', 'templateOverridesByServer',
+                       'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer',
                        'templateOverridesByCluster', 'masterTemplateOverrides' );
 
                foreach ( $required as $key ) {
@@ -95,7 +94,7 @@ class LBFactory_Multi extends LBFactory {
                        if ( isset( $this->groupLoadsBySection[$section] ) ) {
                                $groupLoads = array_merge_recursive( $groupLoads, $this->groupLoadsBySection[$section] );
                        }
-                       $this->mainLBs[$section] = $this->newLoadBalancer( $this->mainTemplate, 
+                       $this->mainLBs[$section] = $this->newLoadBalancer( $this->serverTemplate, 
                                $this->sectionLoads[$section], $groupLoads, "main-$section" );
                        $this->chronProt->initLB( $this->mainLBs[$section] );
                }
@@ -107,12 +106,12 @@ class LBFactory_Multi extends LBFactory {
                        if ( !isset( $this->externalLoads[$cluster] ) ) {
                                throw new MWException( __METHOD__.": Unknown cluster \"$cluster\"" );
                        }
+                       $template = $this->serverTemplate;
+                       if ( isset( $this->externalTemplateOverrides ) ) {
+                               $template = $this->externalTemplateOverrides + $template;
+                       }
                        if ( isset( $this->templateOverridesByCluster[$cluster] ) ) {
-                               $template = $this->templateOverridesByCluster[$cluster];
-                       } elseif ( isset( $this->externalTemplate ) ) {
-                               $template = $this->externalTemplate;
-                       } else {
-                               $template = $this->mainTemplate;
+                               $template = $this->templateOverridesByCluster[$cluster] + $template;
                        }
                        $this->extLBs[$cluster] = $this->newLoadBalancer( $template, 
                                $this->externalLoads[$cluster], array(), "ext-$cluster" );
diff --git a/includes/Status.php b/includes/Status.php
new file mode 100644 (file)
index 0000000..12a101a
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+
+/**
+ * Generic operation result class
+ * Has warning/error list, boolean status and arbitrary value
+ *
+ * "Good" means the operation was completed with no warnings or errors. 
+ *
+ * "OK" means the operation was partially or wholly completed.
+ *
+ * An operation which is not OK should have errors so that the user can be 
+ * informed as to what went wrong. Calling the fatal() function sets an error 
+ * message and simultaneously switches off the OK flag.
+ */
+class Status {
+       var $ok = true;
+       var $value;
+
+       /** Counters for batch operations */
+       var $successCount = 0, $failCount = 0;
+
+       /*semi-private*/ var $errors = array();
+       /*semi-private*/ var $cleanCallback = false;
+
+       /**
+        * Factory function for fatal errors
+        */
+       static function newFatal( $message /*, parameters...*/ ) {
+               $params = func_get_args();
+               $result = new self;
+               call_user_func_array( array( &$result, 'error' ), $params );
+               $result->ok = false;
+               return $result;
+       }
+
+       static function newGood( $value = null ) {
+               $result = new self;
+               $result->value = $value;
+               return $result;
+       }
+
+       function setResult( $ok, $value = null ) {
+               $this->ok = $ok;
+               $this->value = $value;
+       }
+
+       function isGood() {
+               return $this->ok && !$this->errors;
+       }
+
+       function isOK() {
+               return $this->ok;
+       }
+
+       function warning( $message /*, parameters... */ ) {
+               $params = array_slice( func_get_args(), 1 );            
+               $this->errors[] = array( 
+                       'type' => 'warning', 
+                       'message' => $message, 
+                       'params' => $params );
+       }
+
+       /**
+        * Add an error, do not set fatal flag
+        * This can be used for non-fatal errors
+        */
+       function error( $message /*, parameters... */ ) {
+               $params = array_slice( func_get_args(), 1 );            
+               $this->errors[] = array( 
+                       'type' => 'error', 
+                       'message' => $message, 
+                       'params' => $params );
+       }
+
+       /**
+        * Add an error and set OK to false, indicating that the operation as a whole was fatal
+        */
+       function fatal( $message /*, parameters... */ ) {
+               $params = array_slice( func_get_args(), 1 );            
+               $this->errors[] = array( 
+                       'type' => 'error', 
+                       'message' => $message, 
+                       'params' => $params );
+               $this->ok = false;
+       }
+
+       protected function cleanParams( $params ) {
+               if ( !$this->cleanCallback ) {
+                       return $params;
+               }
+               $cleanParams = array();
+               foreach ( $params as $i => $param ) {
+                       $cleanParams[$i] = call_user_func( $this->cleanCallback, $param );
+               }
+               return $cleanParams;
+       }
+
+       protected function getItemXML( $item ) {
+               $params = $this->cleanParams( $item['params'] );
+               $xml = "<{$item['type']}>\n" . 
+                       Xml::element( 'message', null, $item['message'] ) . "\n" .
+                       Xml::element( 'text', null, wfMsgReal( $item['message'], $params ) ) ."\n";
+               foreach ( $params as $param ) {
+                       $xml .= Xml::element( 'param', null, $param );
+               }
+               $xml .= "</{$this->type}>\n";
+               return $xml;
+       }
+
+       /**
+        * Get the error list as XML
+        */
+       function getXML() {
+               $xml = "<errors>\n";
+               foreach ( $this->errors as $error ) {
+                       $xml .= $this->getItemXML( $error );
+               }
+               $xml .= "</errors>\n";
+               return $xml;
+       }
+
+       /**
+        * Get the error list as a wikitext formatted list
+        * @param string $shortContext A short enclosing context message name, to be used 
+        *     when there is a single error
+        * @param string $longContext A long enclosing context message name, for a list
+        */
+       function getWikiText( $shortContext = false, $longContext = false ) {
+               if ( count( $this->errors ) == 0 ) {
+                       if ( $this->ok ) {
+                               $this->fatal( 'internalerror_info',
+                                       __METHOD__." called for a good result, this is incorrect\n" );
+                       } else {
+                               $this->fatal( 'internalerror_info', 
+                                       __METHOD__.": Invalid result object: no error text but not OK\n" );
+                       }
+               }
+               if ( count( $this->errors ) == 1 ) {
+                       $params = array_map( 'wfEscapeWikiText', $this->cleanParams( $this->errors[0]['params'] ) );
+                       $s = wfMsgReal( $this->errors[0]['message'], $params, true, false, false );
+                       if ( $shortContext ) {
+                               $s = wfMsgNoTrans( $shortContext, $s );
+                       } elseif ( $longContext ) {
+                               $s = wfMsgNoTrans( $longContext, "* $s\n" );
+                       }
+               } else {
+                       $s = '';
+                       foreach ( $this->errors as $error ) {
+                               $params = array_map( 'wfEscapeWikiText', $this->cleanParams( $error['params'] ) );
+                               $s .= '* ' . wfMsgReal( $error['message'], $params, true, false, false ) . "\n";
+                       }
+                       if ( $longContext ) {
+                               $s = wfMsgNoTrans( $longContext, $s );
+                       } elseif ( $shortContext ) {
+                               $s = wfMsgNoTrans( $shortContext, "\n* $s\n" );
+                       }
+               }
+               return $s;
+       }
+
+       /**
+        * Merge another status object into this one
+        */
+       function merge( $other, $overwriteValue = false ) {
+               $this->errors = array_merge( $this->errors, $other->errors );
+               $this->ok = $this->ok && $other->ok;
+               if ( $overwriteValue ) {
+                       $this->value = $other->value;
+               }
+               $this->successCount += $other->successCount;
+               $this->failCount += $other->failCount;
+       }
+}
+
index 5dd1dbd..63c6680 100644 (file)
@@ -1,19 +1,9 @@
 <?php
 
 /**
- * Generic operation result class
- * Has warning/error list, boolean status and arbitrary value
+ * Generic operation result class for FileRepo-related operations
  */
-class FileRepoStatus {
-       var $ok = true;
-       var $value;
-
-       /** Counters for batch operations */
-       var $successCount = 0, $failCount = 0;
-
-       /*semi-private*/ var $errors = array();
-       /*semi-private*/ var $cleanCallback = false;
-
+class FileRepoStatus extends Status {
        /**
         * Factory function for fatal errors
         */
@@ -36,136 +26,4 @@ class FileRepoStatus {
                        $this->cleanCallback = $repo->getErrorCleanupFunction();
                }
        }
-
-       function setResult( $ok, $value = null ) {
-               $this->ok = $ok;
-               $this->value = $value;
-       }
-
-       function isGood() {
-               return $this->ok && !$this->errors;
-       }
-
-       function isOK() {
-               return $this->ok;
-       }
-
-       function warning( $message /*, parameters... */ ) {
-               $params = array_slice( func_get_args(), 1 );            
-               $this->errors[] = array( 
-                       'type' => 'warning', 
-                       'message' => $message, 
-                       'params' => $params );
-       }
-
-       /**
-        * Add an error, do not set fatal flag
-        * This can be used for non-fatal errors
-        */
-       function error( $message /*, parameters... */ ) {
-               $params = array_slice( func_get_args(), 1 );            
-               $this->errors[] = array( 
-                       'type' => 'error', 
-                       'message' => $message, 
-                       'params' => $params );
-       }
-
-       /**
-        * Add an error and set OK to false, indicating that the operation as a whole was fatal
-        */
-       function fatal( $message /*, parameters... */ ) {
-               $params = array_slice( func_get_args(), 1 );            
-               $this->errors[] = array( 
-                       'type' => 'error', 
-                       'message' => $message, 
-                       'params' => $params );
-               $this->ok = false;
-       }
-
-       protected function cleanParams( $params ) {
-               if ( !$this->cleanCallback ) {
-                       return $params;
-               }
-               $cleanParams = array();
-               foreach ( $params as $i => $param ) {
-                       $cleanParams[$i] = call_user_func( $this->cleanCallback, $param );
-               }
-               return $cleanParams;
-       }
-
-       protected function getItemXML( $item ) {
-               $params = $this->cleanParams( $item['params'] );
-               $xml = "<{$item['type']}>\n" . 
-                       Xml::element( 'message', null, $item['message'] ) . "\n" .
-                       Xml::element( 'text', null, wfMsgReal( $item['message'], $params ) ) ."\n";
-               foreach ( $params as $param ) {
-                       $xml .= Xml::element( 'param', null, $param );
-               }
-               $xml .= "</{$this->type}>\n";
-               return $xml;
-       }
-
-       /**
-        * Get the error list as XML
-        */
-       function getXML() {
-               $xml = "<errors>\n";
-               foreach ( $this->errors as $error ) {
-                       $xml .= $this->getItemXML( $error );
-               }
-               $xml .= "</errors>\n";
-               return $xml;
-       }
-
-       /**
-        * Get the error list as a wikitext formatted list
-        * @param string $shortContext A short enclosing context message name, to be used 
-        *     when there is a single error
-        * @param string $longContext A long enclosing context message name, for a list
-        */
-       function getWikiText( $shortContext = false, $longContext = false ) {
-               if ( count( $this->errors ) == 0 ) {
-                       if ( $this->ok ) {
-                               $this->fatal( 'internalerror_info',
-                                       __METHOD__." called for a good result, this is incorrect\n" );
-                       } else {
-                               $this->fatal( 'internalerror_info', 
-                                       __METHOD__.": Invalid result object: no error text but not OK\n" );
-                       }
-               }
-               if ( count( $this->errors ) == 1 ) {
-                       $params = array_map( 'wfEscapeWikiText', $this->cleanParams( $this->errors[0]['params'] ) );
-                       $s = wfMsgReal( $this->errors[0]['message'], $params, true, false, false );
-                       if ( $shortContext ) {
-                               $s = wfMsgNoTrans( $shortContext, $s );
-                       } elseif ( $longContext ) {
-                               $s = wfMsgNoTrans( $longContext, "* $s\n" );
-                       }
-               } else {
-                       $s = '';
-                       foreach ( $this->errors as $error ) {
-                               $params = array_map( 'wfEscapeWikiText', $this->cleanParams( $error['params'] ) );
-                               $s .= '* ' . wfMsgReal( $error['message'], $params, true, false, false ) . "\n";
-                       }
-                       if ( $longContext ) {
-                               $s = wfMsgNoTrans( $longContext, $s );
-                       } elseif ( $shortContext ) {
-                               $s = wfMsgNoTrans( $shortContext, "\n* $s\n" );
-                       }
-               }
-               return $s;
-       }
-
-       /**
-        * Merge another status object into this one
-        */
-       function merge( $other, $overwriteValue = false ) {
-               $this->errors = array_merge( $this->errors, $other->errors );
-               $this->ok = $this->ok && $other->ok;
-               if ( $overwriteValue ) {
-                       $this->value = $other->value;
-               }
-               $this->successCount += $other->successCount;
-               $this->failCount += $other->failCount;
-       }
 }