The return of the validation feature (caveat: new table scheme!)
[lhc/web/wiklou.git] / includes / LoadBalancer.php
index 13f01fc..f5fdf61 100644 (file)
@@ -1,6 +1,12 @@
 <?php
-# Database load balancing object
-
+/**
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Depends on the database object
+ */
 require_once( 'Database.php' );
 
 # Valid database indexes
@@ -24,13 +30,18 @@ define( 'DB_ASKSQL_R', 1002 );    # Special:Asksql read
 define( 'DB_WATCHLIST_R', 1004 ); # Watchlist read
 define( 'DB_TASK_LAST', 1004) ;   # Last in list
 
-define( 'MASTER_WAIT_TIMEOUT', 15 ); # Time to wait for a slave to synchronise
-
+/**
+ * Database load balancing object
+ *
+ * @todo document
+ * @package MediaWiki
+ */
 class LoadBalancer {
        /* private */ var $mServers, $mConnections, $mLoads;
        /* private */ var $mFailFunction;
        /* private */ var $mForce, $mReadIndex, $mLastIndex;
-       /* private */ var $mWaitForFile, $mWaitForPos;
+       /* private */ var $mWaitForFile, $mWaitForPos, $mWaitTimeout;
+       /* private */ var $mLaggedSlaveMode;
 
        function LoadBalancer()
        {
@@ -42,14 +53,14 @@ class LoadBalancer {
                $this->mLastIndex = -1;
        }
 
-       function newFromParams( $servers, $failFunction = false )
+       function newFromParams( $servers, $failFunction = false, $waitTimeout = 10 )
        {
                $lb = new LoadBalancer;
                $lb->initialise( $servers, $failFunction = false );
                return $lb;
        }
 
-       function initialise( $servers, $failFunction = false )
+       function initialise( $servers, $failFunction = false, $waitTimeout = 10 )
        {
                $this->mServers = $servers;
                $this->mFailFunction = $failFunction;
@@ -61,14 +72,18 @@ class LoadBalancer {
                $this->mLoads = array();
                $this->mWaitForFile = false;
                $this->mWaitForPos = false;
+               $this->mWaitTimeout = $waitTimeout;
+               $this->mLaggedSlaveMode = false;
 
                foreach( $servers as $i => $server ) {
                        $this->mLoads[$i] = $server['load'];
                }
        }
        
-       # Given an array of non-normalised probabilities, this function will select
-       # an element and return the appropriate key
+       /**
+        * Given an array of non-normalised probabilities, this function will select
+        * an element and return the appropriate key
+        */
        function pickRandom( $weights )
        {
                if ( !is_array( $weights ) || count( $weights ) == 0 ) {
@@ -131,9 +146,11 @@ class LoadBalancer {
                return $i;
        }
 
-       # Set the master wait position
-       # If a DB_SLAVE connection has been opened already, waits
-       # Otherwise sets a variable telling it to wait if such a connection is opened
+       /**
+        * Set the master wait position
+        * If a DB_SLAVE connection has been opened already, waits
+        * Otherwise sets a variable telling it to wait if such a connection is opened
+        */
        function waitFor( $file, $pos ) {
                $fname = 'LoadBalancer::waitFor';
                wfProfileIn( $fname );
@@ -148,15 +165,16 @@ class LoadBalancer {
 
                        if ( $this->mReadIndex > 0 ) {
                                if ( !$this->doWait( $this->mReadIndex ) ) {
-                                       # Use master instead
-                                       $this->mReadIndex = 0;
+                                       $this->mLaggedSlaveMode = true;
                                }
                        } 
                }
                wfProfileOut( $fname );
        }
 
-       # Wait for a given slave to catch up to the master pos stored in $this
+       /**
+        * Wait for a given slave to catch up to the master pos stored in $this
+        */
        function doWait( $index ) {
                global $wgMemc;
                
@@ -173,9 +191,9 @@ class LoadBalancer {
                }
 
                if ( !$retVal && $this->isOpen( $index ) ) {
-                       $conn =& $this->mConnections( $index );
+                       $conn =& $this->mConnections[$index];
                        wfDebug( "Waiting for slave #$index to catch up...\n" );
-                       $result = $conn->masterPosWait( $this->mWaitForFile, $this->mWaitForPos, MASTER_WAIT_TIMEOUT );
+                       $result = $conn->masterPosWait( $this->mWaitForFile, $this->mWaitForPos, $this->mWaitTimeout );
 
                        if ( $result == -1 || is_null( $result ) ) {
                                # Timed out waiting for slave, use master instead
@@ -189,7 +207,9 @@ class LoadBalancer {
                return $retVal;
        }               
 
-       # Get a connection by index
+       /**
+        * Get a connection by index
+        */
        function &getConnection( $i, $fail = true )
        {
                $fname = 'LoadBalancer::getConnection';
@@ -226,9 +246,12 @@ class LoadBalancer {
                return $this->mConnections[$i];
        }
 
-       # Open a connection to the server given by the specified index
-       # Index must be an actual index into the array
-       /* private */ function openConnection( $i, $fail = false ) {
+       /**
+        * Open a connection to the server given by the specified index
+        * Index must be an actual index into the array
+        * @private
+        */
+       function openConnection( $i, $fail = false ) {
                $fname = 'LoadBalancer::openConnection';
                wfProfileIn( $fname );
 
@@ -258,8 +281,11 @@ class LoadBalancer {
                wfProfileOut( $fname );
        }
 
-       # Test if the specified index represents an open connection
-       /* private */ function isOpen( $index ) {
+       /**
+        * Test if the specified index represents an open connection
+        * @private
+        */
+       function isOpen( $index ) {
                if( !is_integer( $index ) ) {
                        return false;
                }
@@ -272,17 +298,24 @@ class LoadBalancer {
                }
        }
        
-       # Really opens a connection
-       /* private */ function reallyOpenConnection( &$server ) {
-                       extract( $server );
-                       # Get class for this database type
-                       $class = 'Database' . ucfirst( $type );
-                       if ( !class_exists( $class ) ) {
-                               require_once( "$class.php" );
-                       }
+       /**
+        * Really opens a connection
+        * @private
+        */
+       function reallyOpenConnection( &$server ) {
+               if( !is_array( $server ) ) {
+                       wfDebugDieBacktrace( 'You must update your load-balancing configuration. See DefaultSettings.php entry for $wgDBservers.' );
+               }
+               
+               extract( $server );
+               # Get class for this database type
+               $class = 'Database' . ucfirst( $type );
+               if ( !class_exists( $class ) ) {
+                       require_once( "$class.php" );
+               }
 
-                       # Create object
-                       return new $class( $host, $user, $password, $dbname, 1, $flags );
+               # Create object
+               return new $class( $host, $user, $password, $dbname, 1, $flags );
        }
        
        function reportConnectionError( &$conn )
@@ -323,12 +356,16 @@ class LoadBalancer {
                return array_key_exists( $i, $this->mServers );
        }
 
-       # Get the number of defined servers (not the number of open connections)
+       /**
+        * Get the number of defined servers (not the number of open connections)
+        */
        function getServerCount() {
                return count( $this->mServers );
        }
 
-       # Save master pos to the session and to memcached, if the session exists
+       /**
+        * Save master pos to the session and to memcached, if the session exists
+        */
        function saveMasterPos() {
                global $wgSessionStarted;
                if ( $wgSessionStarted && count( $this->mServers ) > 1 ) {
@@ -350,14 +387,18 @@ class LoadBalancer {
                }
        }
 
-       # Loads the master pos from the session, waits for it if necessary
+       /**
+        * Loads the master pos from the session, waits for it if necessary
+        */
        function loadMasterPos() {
                if ( isset( $_SESSION['master_log_file'] ) && isset( $_SESSION['master_pos'] ) ) {
                        $this->waitFor( $_SESSION['master_log_file'], $_SESSION['master_pos'] );
                }
        }
 
-       # Close all open connections
+       /**
+        * Close all open connections
+        */
        function closeAll() {
                foreach( $this->mConnections as $i => $conn ) {
                        if ( $this->isOpen( $i ) ) {
@@ -373,4 +414,12 @@ class LoadBalancer {
                        }
                }
        }
+
+       function waitTimeout( $value = NULL ) {
+               return wfSetVar( $this->mWaitTimeout, $value );
+       }
+
+       function getLaggedSlaveMode() {
+               return $this->mLaggedSlaveMode;
+       }
 }