$class = $this->mLoadMonitorClass;
$this->mLoadMonitor = new $class( $this );
}
+
return $this->mLoadMonitor;
}
#wfDebugLog( 'connect', var_export( $loads, true ) );
# Return a random representative of the remainder
- return $this->pickRandom( $loads );
+ return ArrayUtils::pickRandom( $loads );
}
/**
# No loads for this group, return false and the caller can use some other group
wfDebug( __METHOD__ . ": no loads for group $group\n" );
wfProfileOut( __METHOD__ );
+
return false;
}
} else {
$currentLoads = $nonErrorLoads;
while ( count( $currentLoads ) ) {
if ( $wgReadOnly || $this->mAllowLagged || $laggedSlaveMode ) {
- $i = $this->pickRandom( $currentLoads );
+ $i = ArrayUtils::pickRandom( $currentLoads );
} else {
$i = $this->getRandomNonLagged( $currentLoads, $wiki );
if ( $i === false && count( $currentLoads ) != 0 ) {
wfDebugLog( 'replication', "All slaves lagged. Switch to read-only mode\n" );
$wgReadOnly = 'The database has been automatically locked ' .
'while the slave database servers catch up to the master';
- $i = $this->pickRandom( $currentLoads );
+ $i = ArrayUtils::pickRandom( $currentLoads );
$laggedSlaveMode = true;
}
}
# wants us to return false.
wfDebugLog( 'connect', __METHOD__ . ": pickRandom() returned false\n" );
wfProfileOut( __METHOD__ );
+
return false;
}
}
}
wfProfileOut( __METHOD__ );
+
return $i;
}
wfDebug( __METHOD__ . ": waiting $t us\n" );
usleep( $t );
wfProfileOut( __METHOD__ );
+
return $t;
}
public function waitForAll( $pos ) {
wfProfileIn( __METHOD__ );
$this->mWaitForPos = $pos;
- for ( $i = 1; $i < count( $this->mServers ); $i++ ) {
- $this->doWait( $i, true );
+ $serverCount = count( $this->mServers );
+ for ( $i = 1; $i < $serverCount; $i++ ) {
+ if ( $this->mLoads[$i] > 0 ) {
+ $this->doWait( $i, true );
+ }
}
wfProfileOut( __METHOD__ );
}
return reset( $conns[$i] );
}
}
+
return false;
}
if ( !$conn ) {
if ( !$open ) {
wfDebug( __METHOD__ . ": no connection open\n" );
+
return false;
} else {
$conn = $this->openConnection( $index, '' );
if ( !$conn ) {
wfDebug( __METHOD__ . ": failed to open connection\n" );
+
return false;
}
}
if ( $result == -1 || is_null( $result ) ) {
# Timed out waiting for slave, use master instead
wfDebug( __METHOD__ . ": Timed out waiting for slave #$index pos {$this->mWaitForPos}\n" );
+
return false;
} else {
wfDebug( __METHOD__ . ": Done\n" );
+
return true;
}
}
if ( $i == DB_LAST ) {
wfProfileOut( __METHOD__ );
- throw new MWException( 'Attempt to call ' . __METHOD__ . ' with deprecated server index DB_LAST' );
+ throw new MWException( 'Attempt to call ' . __METHOD__ .
+ ' with deprecated server index DB_LAST' );
} elseif ( $i === null || $i === false ) {
wfProfileOut( __METHOD__ );
- throw new MWException( 'Attempt to call ' . __METHOD__ . ' with invalid server index' );
+ throw new MWException( 'Attempt to call ' . __METHOD__ .
+ ' with invalid server index' );
}
if ( $wiki === wfWikiID() ) {
if ( $i === false ) {
$this->mLastError = 'No working slave server: ' . $this->mLastError;
wfProfileOut( __METHOD__ );
+
return $this->reportConnectionError();
}
}
$conn = $this->openConnection( $i, $wiki );
if ( !$conn ) {
wfProfileOut( __METHOD__ );
+
return $this->reportConnectionError();
}
wfProfileOut( __METHOD__ );
+
return $conn;
}
}
if ( $serverIndex === null || $refCount === null ) {
wfDebug( __METHOD__ . ": this connection was not opened as a foreign connection\n" );
+
/**
* This can happen in code like:
* foreach ( $dbs as $db ) {
* When a connection to the local DB is opened in this way, reuseConnection()
* should be ignored
*/
+
return;
}
if ( $this->mConns['foreignUsed'][$serverIndex][$wiki] !== $conn ) {
- throw new MWException( __METHOD__ . ": connection not found, has the connection been freed already?" );
+ throw new MWException( __METHOD__ . ": connection not found, has " .
+ "the connection been freed already?" );
}
$conn->setLBInfo( 'foreignPoolRefCount', --$refCount );
if ( $refCount <= 0 ) {
return new DBConnRef( $this, $this->getConnection( $db, $groups, $wiki ) );
}
+ /**
+ * Get a database connection handle reference without connecting yet
+ *
+ * The handle's methods wrap simply wrap those of a DatabaseBase handle
+ *
+ * @see LoadBalancer::getConnection() for parameter information
+ *
+ * @param integer $db
+ * @param mixed $groups
+ * @param string $wiki
+ * @return DBConnRef
+ */
+ public function getLazyConnectionRef( $db, $groups = array(), $wiki = false ) {
+ return new DBConnRef( $this, array( $db, $groups, $wiki ) );
+ }
+
/**
* Open a connection to the server given by the specified index
* Index must be an actual index into the array.
if ( $wiki !== false ) {
$conn = $this->openForeignConnection( $i, $wiki );
wfProfileOut( __METHOD__ );
+
return $conn;
}
if ( isset( $this->mConns['local'][$i][0] ) ) {
}
}
wfProfileOut( __METHOD__ );
+
return $conn;
}
$conn->setLBInfo( 'foreignPoolRefCount', $refCount + 1 );
}
wfProfileOut( __METHOD__ );
+
return $conn;
}
if ( !is_integer( $index ) ) {
return false;
}
+
return (bool)$this->getAnyOpenConnection( $index );
}
if ( isset( $server['fakeMaster'] ) ) {
$db->setFakeMaster( true );
}
+
return $db;
}
wfLogDBError( "Connection error: {$this->mLastError} ({$server})\n" );
$conn->reportConnectionError( "{$this->mLastError} ({$server})" ); // throws DBConnectionError
}
+
return false; /* not reached */
}
}
/**
- * Sets the server info structure for the given index. Entry at index $i is created if it doesn't exist
+ * Sets the server info structure for the given index. Entry at index $i
+ * is created if it doesn't exist
* @param $i
* @param $serverInfo
*/
# master (however unlikely that may be), then we can fetch the position from the slave.
$masterConn = $this->getAnyOpenConnection( 0 );
if ( !$masterConn ) {
- for ( $i = 1; $i < count( $this->mServers ); $i++ ) {
+ $serverCount = count( $this->mServers );
+ for ( $i = 1; $i < $serverCount; $i++ ) {
$conn = $this->getAnyOpenConnection( $i );
if ( $conn ) {
wfDebug( "Master pos fetched from slave\n" );
+
return $conn->getSlavePos();
}
}
} else {
wfDebug( "Master pos fetched from master\n" );
+
return $masterConn->getMasterPos();
}
+
return false;
}
return $this->mAllowLagged;
}
$this->mAllowLagged = $mode;
+
return $this->mAllowLagged;
}
}
}
}
+
return $success;
}
}
}
}
+
return array( $host, $maxLag, $maxIndex );
}
$this->mLagTimes = $this->getLoadMonitor()->getLagTimes(
array_keys( $this->mServers ), $wiki );
}
+
return $this->mLagTimes;
}
/**
* Helper class to handle automatically marking connectons as reusable (via RAII pattern)
+ * as well handling deferring the actual network connection until the handle is used
*
* @ingroup Database
* @since 1.22
class DBConnRef implements IDatabase {
/** @var LoadBalancer */
protected $lb;
- /** @var DatabaseBase */
+ /** @var DatabaseBase|null */
protected $conn;
+ /** @var Array|null */
+ protected $params;
/**
* @param $lb LoadBalancer
- * @param $conn DatabaseBase
+ * @param $conn DatabaseBase|array Connection or (server index, group, wiki ID) array
*/
- public function __construct( LoadBalancer $lb, DatabaseBase $conn ) {
+ public function __construct( LoadBalancer $lb, $conn ) {
$this->lb = $lb;
- $this->conn = $conn;
+ if ( $conn instanceof DatabaseBase ) {
+ $this->conn = $conn;
+ } else {
+ $this->params = $conn;
+ }
}
public function __call( $name, $arguments ) {
+ if ( $this->conn === null ) {
+ list( $db, $groups, $wiki ) = $this->params;
+ $this->conn = $this->lb->getConnection( $db, $groups, $wiki );
+ }
+
return call_user_func_array( array( $this->conn, $name ), $arguments );
}
function __destruct() {
- $this->lb->reuseConnection( $this->conn );
+ if ( $this->conn !== null ) {
+ $this->lb->reuseConnection( $this->conn );
+ }
}
}