loadbalancer.php

来自「php 开发的内容管理系统」· PHP 代码 · 共 667 行 · 第 1/2 页

PHP
667
字号
	function &getConnection( $i, $fail = true, $groups = array() )	{		global $wgDBtype;		$fname = 'LoadBalancer::getConnection';		wfProfileIn( $fname );		# Query groups		if ( !is_array( $groups ) ) {			$groupIndex = $this->getGroupIndex( $groups, $i );			if ( $groupIndex !== false ) {				$i = $groupIndex;			}		} else {			foreach ( $groups as $group ) {				$groupIndex = $this->getGroupIndex( $group, $i );				if ( $groupIndex !== false ) {					$i = $groupIndex;					break;				}			}		}		# For now, only go through all this for mysql databases		if ($wgDBtype != 'mysql') {			$i = $this->getWriterIndex();		}		# Operation-based index		elseif ( $i == DB_SLAVE ) {			$i = $this->getReaderIndex();		} elseif ( $i == DB_MASTER ) {			$i = $this->getWriterIndex();		} elseif ( $i == DB_LAST ) {			# Just use $this->mLastIndex, which should already be set			$i = $this->mLastIndex;			if ( $i === -1 ) {				# Oh dear, not set, best to use the writer for safety				wfDebug( "Warning: DB_LAST used when there was no previous index\n" );				$i = $this->getWriterIndex();			}		}		# Couldn't find a working server in getReaderIndex()?		if ( $i === false ) {			$this->reportConnectionError( $this->mErrorConnection );		}		# Now we have an explicit index into the servers array		$this->openConnection( $i, $fail );		wfProfileOut( $fname );		return $this->mConnections[$i];	}	/**	 * Open a connection to the server given by the specified index	 * Index must be an actual index into the array	 * Returns success	 * @access private	 */	function openConnection( $i, $fail = false ) {		$fname = 'LoadBalancer::openConnection';		wfProfileIn( $fname );		$success = true;		if ( !$this->isOpen( $i ) ) {			$this->mConnections[$i] = $this->reallyOpenConnection( $this->mServers[$i] );		}		if ( !$this->isOpen( $i ) ) {			wfDebug( "Failed to connect to database $i at {$this->mServers[$i]['host']}\n" );			if ( $fail ) {				$this->reportConnectionError( $this->mConnections[$i] );			}			$this->mErrorConnection = $this->mConnections[$i];			$this->mConnections[$i] = false;			$success = false;		}		$this->mLastIndex = $i;		wfProfileOut( $fname );		return $success;	}	/**	 * Test if the specified index represents an open connection	 * @access private	 */	function isOpen( $index ) {		if( !is_integer( $index ) ) {			return false;		}		if ( array_key_exists( $index, $this->mConnections ) && is_object( $this->mConnections[$index] ) &&		  $this->mConnections[$index]->isOpen() )		{			return true;		} else {			return false;		}	}	/**	 * Really opens a connection	 * @access private	 */	function reallyOpenConnection( &$server ) {		if( !is_array( $server ) ) {			throw new MWException( '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		$db = new $class( $host, $user, $password, $dbname, 1, $flags );		$db->setLBInfo( $server );		return $db;	}	function reportConnectionError( &$conn )	{		$fname = 'LoadBalancer::reportConnectionError';		wfProfileIn( $fname );		# Prevent infinite recursion		static $reporting = false;		if ( !$reporting ) {			$reporting = true;			if ( !is_object( $conn ) ) {				// No last connection, probably due to all servers being too busy				$conn = new Database;				if ( $this->mFailFunction ) {					$conn->failFunction( $this->mFailFunction );					$conn->reportConnectionError( $this->mLastError );				} else {					// If all servers were busy, mLastError will contain something sensible					throw new DBConnectionError( $conn, $this->mLastError );				}			} else {				if ( $this->mFailFunction ) {					$conn->failFunction( $this->mFailFunction );				} else {					$conn->failFunction( false );				}				$server = $conn->getProperty( 'mServer' );				$conn->reportConnectionError( "{$this->mLastError} ({$server})" );			}			$reporting = false;		}		wfProfileOut( $fname );	}	function getWriterIndex() {		return 0;	}	/**	 * Force subsequent calls to getConnection(DB_SLAVE) to return the 	 * given index. Set to -1 to restore the original load balancing	 * behaviour. I thought this was a good idea when I originally 	 * wrote this class, but it has never been used.	 */	function force( $i ) {		$this->mForce = $i;	}	/**	 * Returns true if the specified index is a valid server index	 */	function haveIndex( $i ) {		return array_key_exists( $i, $this->mServers );	}	/**	 * Returns true if the specified index is valid and has non-zero load	 */	function isNonZeroLoad( $i ) {		return array_key_exists( $i, $this->mServers ) && $this->mLoads[$i] != 0;	}	/**	 * 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	 */	function saveMasterPos() {		global $wgSessionStarted;		if ( $wgSessionStarted && count( $this->mServers ) > 1 ) {			# If this entire request was served from a slave without opening a connection to the			# master (however unlikely that may be), then we can fetch the position from the slave.			if ( empty( $this->mConnections[0] ) ) {				$conn =& $this->getConnection( DB_SLAVE );				list( $file, $pos ) = $conn->getSlavePos();				wfDebug( "Saving master pos fetched from slave: $file $pos\n" );			} else {				$conn =& $this->getConnection( 0 );				list( $file, $pos ) = $conn->getMasterPos();				wfDebug( "Saving master pos: $file $pos\n" );			}			if ( $file !== false ) {				$_SESSION['master_log_file'] = $file;				$_SESSION['master_pos'] = $pos;			}		}	}	/**	 * 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	 */	function closeAll() {		foreach( $this->mConnections as $i => $conn ) {			if ( $this->isOpen( $i ) ) {				// Need to use this syntax because $conn is a copy not a reference				$this->mConnections[$i]->close();			}		}	}	function commitAll() {		foreach( $this->mConnections as $i => $conn ) {			if ( $this->isOpen( $i ) ) {				// Need to use this syntax because $conn is a copy not a reference				$this->mConnections[$i]->immediateCommit();			}		}	}	function waitTimeout( $value = NULL ) {		return wfSetVar( $this->mWaitTimeout, $value );	}	function getLaggedSlaveMode() {		return $this->mLaggedSlaveMode;	}	/* Disables/enables lag checks */	function allowLagged($mode=null) {		if ($mode===null)			return $this->mAllowLagged;		$this->mAllowLagged=$mode;	}	function pingAll() {		$success = true;		foreach ( $this->mConnections as $i => $conn ) {			if ( $this->isOpen( $i ) ) {				if ( !$this->mConnections[$i]->ping() ) {					$success = false;				}			}		}		return $success;	}	/**	 * Get the hostname and lag time of the most-lagged slave	 * This is useful for maintenance scripts that need to throttle their updates	 */	function getMaxLag() {		$maxLag = -1;		$host = '';		foreach ( $this->mServers as $i => $conn ) {			if ( $this->openConnection( $i ) ) {				$lag = $this->mConnections[$i]->getLag();				if ( $lag > $maxLag ) {					$maxLag = $lag;					$host = $this->mServers[$i]['host'];				}			}		}		return array( $host, $maxLag );	}	/**	 * Get lag time for each DB	 * Results are cached for a short time in memcached	 */	function getLagTimes() {		global $wgDBname;		$expiry = 5;		$requestRate = 10;		global $wgMemc;		$times = $wgMemc->get( "$wgDBname:lag_times" );		if ( $times ) {			# Randomly recache with probability rising over $expiry			$elapsed = time() - $times['timestamp'];			$chance = max( 0, ( $expiry - $elapsed ) * $requestRate );			if ( mt_rand( 0, $chance ) != 0 ) {				unset( $times['timestamp'] );				return $times;			}		}		# Cache key missing or expired		$times = array();		foreach ( $this->mServers as $i => $conn ) {			if ($i==0) { # Master				$times[$i] = 0;			} elseif ( $this->openConnection( $i ) ) {				$times[$i] = $this->mConnections[$i]->getLag();			}		}		# Add a timestamp key so we know when it was cached		$times['timestamp'] = time();		$wgMemc->set( "$wgDBname:lag_times", $times, $expiry );		# But don't give the timestamp to the caller		unset($times['timestamp']);		return $times;	}}?>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?