Merge "Cleaned up database reconnection logic"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 27 May 2014 18:17:02 +0000 (18:17 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 27 May 2014 18:17:02 +0000 (18:17 +0000)
1  2 
includes/db/Database.php

diff --combined includes/db/Database.php
@@@ -806,7 -806,7 +806,7 @@@ abstract class DatabaseBase implements 
         * database. Example uses in core:
         * @see LoadBalancer::reallyOpenConnection()
         * @see ForeignDBRepo::getMasterDB()
 -       * @see WebInstaller_DBConnect::execute()
 +       * @see WebInstallerDBConnect::execute()
         *
         * @since 1.18
         *
                if ( count( $this->mTrxIdleCallbacks ) ) { // sanity
                        throw new MWException( "Transaction idle callbacks still pending." );
                }
 -              $this->mOpened = false;
                if ( $this->mConn ) {
                        if ( $this->trxLevel() ) {
                                if ( !$this->mTrxAutomatic ) {
                                $this->commit( __METHOD__, 'flush' );
                        }
  
 -                      $ret = $this->closeConnection();
 +                      $closed = $this->closeConnection();
                        $this->mConn = false;
 -
 -                      return $ret;
                } else {
 -                      return true;
 +                      $closed = true;
                }
 +              $this->mOpened = false;
 +
 +              return $closed;
        }
  
        /**
                        # Transaction is gone, like it or not
                        $hadTrx = $this->mTrxLevel; // possible lost transaction
                        $this->mTrxLevel = 0;
+                       $this->mTrxIdleCallbacks = array(); // bug 65263
+                       $this->mTrxPreCommitCallbacks = array(); // bug 65263
                        wfDebug( "Connection lost, reconnecting...\n" );
  
                        if ( $this->ping() ) {
+                               global $wgRequestTime;
                                wfDebug( "Reconnected\n" );
                                $sqlx = substr( $commentedSql, 0, 500 );
                                $sqlx = strtr( $sqlx, "\t\n", '  ' );
-                               global $wgRequestTime;
                                $elapsed = round( microtime( true ) - $wgRequestTime, 3 );
                                if ( $elapsed < 300 ) {
                                        # Not a database error to lose a transaction after a minute or two
                                        wfLogDBError( "Connection lost and reconnected after {$elapsed}s, query: $sqlx" );
                                }
-                               if ( !$hadTrx ) {
-                                       # Should be safe to silently retry
+                               if ( $hadTrx ) {
+                                       # Leave $ret as false and let an error be reported.
+                                       # Callers may catch the exception and continue to use the DB.
+                               } else {
+                                       # Should be safe to silently retry (no trx and thus no callbacks)
                                        $ret = $this->doQuery( $commentedSql );
                                }
                        } else {
                        $this->runOnTransactionIdleCallbacks();
                }
  
 +              # Avoid fatals if close() was called
 +              if ( !$this->isOpen() ) {
 +                      throw new DBUnexpectedError( $this, "DB connection was already closed." );
 +              }
 +
                $this->doBegin( $fname );
                $this->mTrxFname = $fname;
                $this->mTrxDoneWrites = false;
                        }
                }
  
 +              # Avoid fatals if close() was called
 +              if ( !$this->isOpen() ) {
 +                      throw new DBUnexpectedError( $this, "DB connection was already closed." );
 +              }
 +
                $this->runOnTransactionPreCommitCallbacks();
                $this->doCommit( $fname );
                if ( $this->mTrxDoneWrites ) {
                        }
                }
  
 +              # Avoid fatals if close() was called
 +              if ( !$this->isOpen() ) {
 +                      throw new DBUnexpectedError( $this, "DB connection was already closed." );
 +              }
 +
                $this->doRollback( $fname );
                $this->mTrxIdleCallbacks = array(); // cancel
                $this->mTrxPreCommitCallbacks = array(); // cancel