/** @var MysqlMasterPos */
protected $lastKnownSlavePos;
+ /** @var null|int */
+ protected $mFakeSlaveLag = null;
+
+ protected $mFakeMaster = false;
+
/**
* @return string
*/
if ( !$error ) {
$error = $this->lastError();
}
- wfLogDBError( "Error connecting to {$this->mServer}: $error\n" );
+ wfLogDBError( "Error connecting to {$this->mServer}: $error" );
wfDebug( "DB connection error\n" .
"Server: $server, User: $user, Password: " .
substr( $password, 0, 3 ) . "..., error: " . $error . "\n" );
$success = $this->selectDB( $dbName );
wfRestoreWarnings();
if ( !$success ) {
- wfLogDBError( "Error selecting database $dbName on server {$this->mServer}\n" );
+ wfLogDBError( "Error selecting database $dbName on server {$this->mServer}" );
wfDebug( "Error selecting database $dbName on server {$this->mServer} " .
"from client host " . wfHostname() . "\n" );
*/
abstract protected function mysqlPing();
+ /**
+ * Set lag time in seconds for a fake slave
+ *
+ * @param int $lag
+ */
+ public function setFakeSlaveLag( $lag ) {
+ $this->mFakeSlaveLag = $lag;
+ }
+
+ /**
+ * Make this connection a fake master
+ *
+ * @param bool $enabled
+ */
+ public function setFakeMaster( $enabled = true ) {
+ $this->mFakeMaster = $enabled;
+ }
+
/**
* Returns slave lag.
*
}
/**
- * @deprecated in 1.19, use getLagFromSlaveStatus
+ * @deprecated since 1.19, use getLagFromSlaveStatus
*
* @return bool|int
*/
*
* @param DBMasterPos|MySQLMasterPos $pos
* @param int $timeout The maximum number of seconds to wait for synchronisation
- * @return bool|string
+ * @return int Zero if the slave was past that position already,
+ * greater than zero if we waited for some period of time, less than
+ * zero if we timed out.
*/
function masterPosWait( DBMasterPos $pos, $timeout ) {
if ( $this->lastKnownSlavePos && $this->lastKnownSlavePos->hasReached( $pos ) ) {
$this->commit( __METHOD__, 'flush' );
if ( !is_null( $this->mFakeSlaveLag ) ) {
- $status = parent::masterPosWait( $pos, $timeout );
- wfProfileOut( __METHOD__ );
+ $wait = intval( ( $pos->pos - microtime( true ) + $this->mFakeSlaveLag ) * 1e6 );
+
+ if ( $wait > $timeout * 1e6 ) {
+ wfDebug( "Fake slave timed out waiting for $pos ($wait us)\n" );
+ wfProfileOut( __METHOD__ );
- return $status;
+ return -1;
+ } elseif ( $wait > 0 ) {
+ wfDebug( "Fake slave waiting $wait us\n" );
+ usleep( $wait );
+ wfProfileOut( __METHOD__ );
+
+ return 1;
+ } else {
+ wfDebug( "Fake slave up to date ($wait us)\n" );
+ wfProfileOut( __METHOD__ );
+
+ return 0;
+ }
}
# Call doQuery() directly, to avoid opening a transaction if DBO_TRX is set
$encFile = $this->addQuotes( $pos->file );
- $encPos = intval( $pos->getMasterPos() );
+ $encPos = intval( $pos->pos );
$sql = "SELECT MASTER_POS_WAIT($encFile, $encPos, $timeout)";
$res = $this->doQuery( $sql );
*/
function getSlavePos() {
if ( !is_null( $this->mFakeSlaveLag ) ) {
- return parent::getSlavePos();
+ $pos = new MySQLMasterPos( 'fake', microtime( true ) - $this->mFakeSlaveLag );
+ wfDebug( __METHOD__ . ": fake slave pos = $pos\n" );
+
+ return $pos;
}
$res = $this->query( 'SHOW SLAVE STATUS', 'DatabaseBase::getSlavePos' );
*/
function getMasterPos() {
if ( $this->mFakeMaster ) {
- return parent::getMasterPos();
+ return new MySQLMasterPos( 'fake', microtime( true ) );
}
$res = $this->query( 'SHOW MASTER STATUS', 'DatabaseBase::getMasterPos' );
* @return string
*/
public function getSoftwareLink() {
- return '[http://www.mysql.com/ MySQL]';
+ // MariaDB includes its name in its version string (sent when the connection is opened),
+ // and this is how MariaDB's version of the mysql command-line client identifies MariaDB
+ // servers (see the mariadb_connection() function in libmysql/libmysql.c).
+ $version = $this->getServerVersion();
+ if ( strpos( $version, 'MariaDB' ) !== false || strpos( $version, '-maria-' ) !== false ) {
+ return '[{{int:version-db-mariadb-url}} MariaDB]';
+ }
+
+ // Percona Server's version suffix is not very distinctive, and @@version_comment
+ // doesn't give the necessary info for source builds, so assume the server is MySQL.
+ // (Even Percona's version of mysql doesn't try to make the distinction.)
+ return '[{{int:version-db-mysql-url}} MySQL]';
}
/**
if ( !count( $rows ) ) {
return true; // nothing to do
}
- $rows = is_array( reset( $rows ) ) ? $rows : array( $rows );
+
+ if ( !is_array( reset( $rows ) ) ) {
+ $rows = array( $rows );
+ }
$table = $this->tableName( $table );
$columns = array_keys( $rows[0] );
/** @var string */
public $file;
- /** @var int */
- private $pos;
+ /** @var int timestamp */
+ public $pos;
function __construct( $file, $pos ) {
$this->file = $file;
return ( $thisPos && $thatPos && $thisPos >= $thatPos );
}
-
- /**
- * @return int
- */
- public function getMasterPos() {
- return $this->pos;
- }
}