Merge "Clean up handling of 'infinity'"
[lhc/web/wiklou.git] / includes / db / Database.php
index ee1722e..0bef28a 100644 (file)
@@ -153,6 +153,9 @@ abstract class DatabaseBase implements IDatabase {
         */
        protected $allViews = null;
 
+       /** @var TransactionProfiler */
+       protected $trxProfiler;
+
        /**
         * A string describing the current software version, and possibly
         * other details in a user-friendly way. Will be listed on Special:Version, etc.
@@ -345,6 +348,15 @@ abstract class DatabaseBase implements IDatabase {
        public function setFakeMaster( $enabled = true ) {
        }
 
+       /**
+        * @return TransactionProfiler
+        */
+       protected function getTransactionProfiler() {
+               return $this->trxProfiler
+                       ? $this->trxProfiler
+                       : Profiler::instance()->getTransactionProfiler();
+       }
+
        /**
         * Returns true if this database supports (and uses) cascading deletes
         *
@@ -798,13 +810,13 @@ abstract class DatabaseBase implements IDatabase {
 
                $this->mForeign = $foreign;
 
+               if ( isset( $params['trxProfiler'] ) ) {
+                       $this->trxProfiler = $params['trxProfiler']; // override
+               }
+
                if ( $user ) {
                        $this->open( $server, $user, $password, $dbName );
                }
-
-               $isMaster = !is_null( $this->getLBInfo( 'master' ) );
-               $trxProf = Profiler::instance()->getTransactionProfiler();
-               $trxProf->recordConnection( $this->mServer, $this->mDBname, $isMaster );
        }
 
        /**
@@ -1103,7 +1115,7 @@ abstract class DatabaseBase implements IDatabase {
                # Keep track of whether the transaction has write queries pending
                if ( $this->mTrxLevel && !$this->mTrxDoneWrites && $isWriteQuery ) {
                        $this->mTrxDoneWrites = true;
-                       Profiler::instance()->getTransactionProfiler()->transactionWritingIn(
+                       $this->getTransactionProfiler()->transactionWritingIn(
                                $this->mServer, $this->mDBname, $this->mTrxShortId );
                }
 
@@ -1149,7 +1161,7 @@ abstract class DatabaseBase implements IDatabase {
                $startTime = microtime( true );
                $ret = $this->doQuery( $commentedSql );
                # Log the query time and feed it into the DB trx profiler
-               $profiler->getTransactionProfiler()->recordQueryCompletion(
+               $this->getTransactionProfiler()->recordQueryCompletion(
                        $queryProf, $startTime, $isWriteQuery, $this->affectedRows() );
 
                MWDebug::queryTime( $queryId );
@@ -1180,7 +1192,7 @@ abstract class DatabaseBase implements IDatabase {
                                        $startTime = microtime( true );
                                        $ret = $this->doQuery( $commentedSql );
                                        # Log the query time and feed it into the DB trx profiler
-                                       $profiler->getTransactionProfiler()->recordQueryCompletion(
+                                       $this->getTransactionProfiler()->recordQueryCompletion(
                                                $queryProf, $startTime, $isWriteQuery, $this->affectedRows() );
                                }
                        } else {
@@ -1214,13 +1226,10 @@ abstract class DatabaseBase implements IDatabase {
         * @throws DBQueryError
         */
        public function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
-               # Ignore errors during error handling to avoid infinite recursion
-               $ignore = $this->ignoreErrors( true );
                ++$this->mErrorCount;
 
-               if ( $ignore || $tempIgnore ) {
+               if ( $this->ignoreErrors() || $tempIgnore ) {
                        wfDebug( "SQL ERROR (ignored): $error\n" );
-                       $this->ignoreErrors( $ignore );
                } else {
                        $sql1line = mb_substr( str_replace( "\n", "\\n", $sql ), 0, 5 * 1024 );
                        wfLogDBError(
@@ -3312,41 +3321,40 @@ abstract class DatabaseBase implements IDatabase {
         * @return bool
         */
        public function deadlockLoop() {
-               $this->begin( __METHOD__ );
                $args = func_get_args();
                $function = array_shift( $args );
-               $oldIgnore = $this->ignoreErrors( true );
                $tries = self::DEADLOCK_TRIES;
-
                if ( is_array( $function ) ) {
                        $fname = $function[0];
                } else {
                        $fname = $function;
                }
 
-               do {
-                       $retVal = call_user_func_array( $function, $args );
-                       $error = $this->lastError();
-                       $errno = $this->lastErrno();
-                       $sql = $this->lastQuery();
+               $this->begin( __METHOD__ );
 
-                       if ( $errno ) {
+               $e = null;
+               do {
+                       try {
+                               $retVal = call_user_func_array( $function, $args );
+                               break;
+                       } catch ( DBQueryError $e ) {
+                               $error = $this->lastError();
+                               $errno = $this->lastErrno();
+                               $sql = $this->lastQuery();
                                if ( $this->wasDeadlock() ) {
-                                       # Retry
+                                       // Retry after a randomized delay
                                        usleep( mt_rand( self::DEADLOCK_DELAY_MIN, self::DEADLOCK_DELAY_MAX ) );
                                } else {
-                                       $this->reportQueryError( $error, $errno, $sql, $fname );
+                                       // Throw the error back up
+                                       throw $e;
                                }
                        }
-               } while ( $this->wasDeadlock() && --$tries > 0 );
-
-               $this->ignoreErrors( $oldIgnore );
+               } while ( --$tries > 0 );
 
                if ( $tries <= 0 ) {
+                       // Too many deadlocks; give up
                        $this->rollback( __METHOD__ );
-                       $this->reportQueryError( $error, $errno, $sql, $fname );
-
-                       return false;
+                       throw $e;
                } else {
                        $this->commit( __METHOD__ );
 
@@ -3517,7 +3525,11 @@ abstract class DatabaseBase implements IDatabase {
                if ( !$this->mTrxLevel ) {
                        $this->begin( $fname );
                        $this->mTrxAutomatic = true;
-                       $this->mTrxAutomaticAtomic = true;
+                       // If DBO_TRX is set, a series of startAtomic/endAtomic pairs will result
+                       // in all changes being in one transaction to keep requests transactional.
+                       if ( !$this->getFlag( DBO_TRX ) ) {
+                               $this->mTrxAutomaticAtomic = true;
+                       }
                }
 
                $this->mTrxAtomicLevels->push( $fname );
@@ -3599,7 +3611,8 @@ abstract class DatabaseBase implements IDatabase {
                        $this->runOnTransactionPreCommitCallbacks();
                        $this->doCommit( $fname );
                        if ( $this->mTrxDoneWrites ) {
-                               Profiler::instance()->getTransactionProfiler()->transactionWritingOut(
+                               $this->mDoneWrites = microtime( true );
+                               $this->getTransactionProfiler()->transactionWritingOut(
                                        $this->mServer, $this->mDBname, $this->mTrxShortId );
                        }
                        $this->runOnTransactionIdleCallbacks();
@@ -3679,7 +3692,8 @@ abstract class DatabaseBase implements IDatabase {
                $this->runOnTransactionPreCommitCallbacks();
                $this->doCommit( $fname );
                if ( $this->mTrxDoneWrites ) {
-                       Profiler::instance()->getTransactionProfiler()->transactionWritingOut(
+                       $this->mDoneWrites = microtime( true );
+                       $this->getTransactionProfiler()->transactionWritingOut(
                                $this->mServer, $this->mDBname, $this->mTrxShortId );
                }
                $this->runOnTransactionIdleCallbacks();
@@ -3738,7 +3752,7 @@ abstract class DatabaseBase implements IDatabase {
                $this->mTrxPreCommitCallbacks = array(); // cancel
                $this->mTrxAtomicLevels = new SplStack;
                if ( $this->mTrxDoneWrites ) {
-                       Profiler::instance()->getTransactionProfiler()->transactionWritingOut(
+                       $this->getTransactionProfiler()->transactionWritingOut(
                                $this->mServer, $this->mDBname, $this->mTrxShortId );
                }
        }
@@ -4318,7 +4332,7 @@ abstract class DatabaseBase implements IDatabase {
         * @return string
         */
        public function decodeExpiry( $expiry, $format = TS_MW ) {
-               return ( $expiry == '' || $expiry == $this->getInfinity() )
+               return ( $expiry == '' || $expiry == 'infinity' || $expiry == $this->getInfinity() )
                        ? 'infinity'
                        : wfTimestamp( $format, $expiry );
        }