Consistently use '@deprecated since <version>'
[lhc/web/wiklou.git] / includes / db / DatabaseMysqlBase.php
index 7bf247f..d437c4c 100644 (file)
@@ -33,6 +33,11 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
        /** @var MysqlMasterPos */
        protected $lastKnownSlavePos;
 
+       /** @var null|int */
+       protected $mFakeSlaveLag = null;
+
+       protected $mFakeMaster = false;
+
        /**
         * @return string
         */
@@ -88,7 +93,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                        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" );
@@ -103,7 +108,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                        $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" );
 
@@ -578,6 +583,24 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         */
        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.
         *
@@ -615,7 +638,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
        }
 
        /**
-        * @deprecated in 1.19, use getLagFromSlaveStatus
+        * @deprecated since 1.19, use getLagFromSlaveStatus
         *
         * @return bool|int
         */
@@ -661,7 +684,9 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         *
         * @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 ) ) {
@@ -673,15 +698,30 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                $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 );
 
@@ -705,7 +745,10 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         */
        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' );
@@ -729,7 +772,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         */
        function getMasterPos() {
                if ( $this->mFakeMaster ) {
-                       return parent::getMasterPos();
+                       return new MySQLMasterPos( 'fake', microtime( true ) );
                }
 
                $res = $this->query( 'SHOW MASTER STATUS', 'DatabaseBase::getMasterPos' );
@@ -761,7 +804,18 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         * @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]';
        }
 
        /**
@@ -946,7 +1000,10 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                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] );
@@ -1225,8 +1282,8 @@ class MySQLMasterPos implements DBMasterPos {
        /** @var string */
        public $file;
 
-       /** @var int */
-       private $pos;
+       /** @var int timestamp */
+       public $pos;
 
        function __construct( $file, $pos ) {
                $this->file = $file;
@@ -1256,11 +1313,4 @@ class MySQLMasterPos implements DBMasterPos {
 
                return ( $thisPos && $thatPos && $thisPos >= $thatPos );
        }
-
-       /**
-        * @return int
-        */
-       public function getMasterPos() {
-               return $this->pos;
-       }
 }