/** @var MysqlMasterPos */
protected $lastKnownSlavePos;
+ /** @var null|int */
+ protected $mFakeSlaveLag = null;
+
+ protected $mFakeMaster = false;
+
/**
* @return string
*/
*/
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.
*
*
* @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 );
- return $status;
+ if ( $wait > $timeout * 1e6 ) {
+ wfDebug( "Fake slave timed out waiting for $pos ($wait us)\n" );
+ wfProfileOut( __METHOD__ );
+
+ 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
*/
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]';
+ $version = $this->getServerVersion();
+ if ( strpos( $version, 'MariaDB' ) !== false ) {
+ return '[{{int:version-db-mariadb-url}} MariaDB]';
+ } elseif ( strpos( $version, 'percona' ) !== false ) {
+ return '[{{int:version-db-percona-url}} Percona Server]';
+ } else {
+ return '[{{int:version-db-mysql-url}} MySQL]';
+ }
}
/**
* @param string $fname
* @return bool
*/
- public function upsert(
- $table, array $rows, array $uniqueIndexes, array $set, $fname = __METHOD__
+ public function upsert( $table, array $rows, array $uniqueIndexes,
+ array $set, $fname = __METHOD__
) {
if ( !count( $rows ) ) {
return true; // nothing to do
$newName = $this->addIdentifierQuotes( $newName );
$oldName = $this->addIdentifierQuotes( $oldName );
$query = "CREATE $tmp TABLE $newName (LIKE $oldName)";
- $this->query( $query, $fname );
+
+ return $this->query( $query, $fname );
}
/**
/** @var string */
public $file;
- /** @var int */
- private $pos;
+ /** @var int timestamp */
+ public $pos;
function __construct( $file, $pos ) {
$this->file = $file;