Merge "Do SearchUpdate::indexTitle after search-update is supported check"
[lhc/web/wiklou.git] / includes / db / Database.php
index 2f135a4..68f94b6 100644 (file)
@@ -441,6 +441,14 @@ abstract class DatabaseBase implements IDatabase {
                return $this->mDoneWrites ?: false;
        }
 
+       /**
+        * @return bool Whether there is a transaction open with possible write queries
+        * @since 1.27
+        */
+       public function writesPending() {
+               return $this->mTrxLevel && $this->mTrxDoneWrites;
+       }
+
        /**
         * Returns true if there is a transaction open with possible write
         * queries or transaction pre-commit/idle callbacks waiting on it to finish.
@@ -607,8 +615,7 @@ abstract class DatabaseBase implements IDatabase {
        function __construct( array $params ) {
                global $wgDBprefix, $wgDBmwschema, $wgCommandLineMode;
 
-               $this->mTrxAtomicLevels = new SplStack;
-               $this->srvCache = ObjectCache::newAccelerator( 'hash' );
+               $this->srvCache = ObjectCache::getLocalServerInstance( 'hash' );
 
                $server = $params['host'];
                $user = $params['user'];
@@ -982,7 +989,7 @@ abstract class DatabaseBase implements IDatabase {
                }
 
                if ( $this->debug() ) {
-                       wfDebugLog( 'queries', sprintf( "%s: %s", $this->mDBname, $sql ) );
+                       wfDebugLog( 'queries', sprintf( "%s: %s", $this->mDBname, $commentedSql ) );
                }
 
                $queryId = MWDebug::query( $sql, $fname, $isMaster );
@@ -3307,6 +3314,11 @@ abstract class DatabaseBase implements IDatabase {
                                                MWExceptionHandler::logException( $ePrior );
                                        }
                                        $ePrior = $e;
+                                       // Some callbacks may use startAtomic/endAtomic, so make sure
+                                       // their transactions are ended so other callbacks don't fail
+                                       if ( $this->trxLevel() ) {
+                                               $this->rollback( __METHOD__ );
+                                       }
                                }
                        }
                } while ( count( $this->mTrxIdleCallbacks ) );
@@ -3431,7 +3443,7 @@ abstract class DatabaseBase implements IDatabase {
                                $levels = implode( ', ', $this->mTrxAtomicLevels );
                                throw new DBUnexpectedError(
                                        $this,
-                                       "Got explicit BEGIN while atomic sections $levels are still open."
+                                       "Got explicit BEGIN from $fname while atomic section(s) $levels are open."
                                );
                        } elseif ( !$this->mTrxAutomatic ) {
                                // We want to warn about inadvertently nested begin/commit pairs, but not about
@@ -3761,19 +3773,6 @@ abstract class DatabaseBase implements IDatabase {
                return true;
        }
 
-       /**
-        * Get the slave lag when the current transaction started
-        * or a general lag estimate if not transaction is active
-        *
-        * This is useful when transactions might use snapshot isolation
-        * (e.g. REPEATABLE-READ in innodb), so the "real" lag of that data
-        * is this lag plus transaction duration. If they don't, it is still
-        * safe to be pessimistic. In AUTO-COMMIT mode, this still gives an
-        * indication of the staleness of subsequent reads.
-        *
-        * @return array ('lag': seconds, 'since': UNIX timestamp of BEGIN)
-        * @since 1.27
-        */
        public function getSessionLagStatus() {
                return $this->getTransactionLagStatus() ?: $this->getApproximateLagStatus();
        }
@@ -3786,7 +3785,7 @@ abstract class DatabaseBase implements IDatabase {
         * is this lag plus transaction duration. If they don't, it is still
         * safe to be pessimistic. This returns null if there is no transaction.
         *
-        * @return array|null ('lag': seconds, 'since': UNIX timestamp of BEGIN)
+        * @return array|null ('lag': seconds or false on error, 'since': UNIX timestamp of BEGIN)
         * @since 1.27
         */
        public function getTransactionLagStatus() {
@@ -3798,7 +3797,7 @@ abstract class DatabaseBase implements IDatabase {
        /**
         * Get a slave lag estimate for this server
         *
-        * @return array ('lag': seconds, 'since': UNIX timestamp of estimate)
+        * @return array ('lag': seconds or false on error, 'since': UNIX timestamp of estimate)
         * @since 1.27
         */
        public function getApproximateLagStatus() {
@@ -3820,30 +3819,29 @@ abstract class DatabaseBase implements IDatabase {
         *
         * @param IDatabase $db1
         * @param IDatabase ...
-        * @return array ('lag': highest lag, 'since': lowest estimate UNIX timestamp)
+        * @return array Map of values:
+        *   - lag: highest lag of any of the DBs or false on error (e.g. replication stopped)
+        *   - since: oldest UNIX timestamp of any of the DB lag estimates
+        *   - pending: whether any of the DBs have uncommitted changes
         * @since 1.27
         */
        public static function getCacheSetOptions( IDatabase $db1 ) {
-               $res = array( 'lag' => 0, 'since' => INF );
+               $res = array( 'lag' => 0, 'since' => INF, 'pending' => false );
                foreach ( func_get_args() as $db ) {
                        /** @var IDatabase $db */
                        $status = $db->getSessionLagStatus();
-                       $res['lag'] = max( $res['lag'], $status['lag'] );
+                       if ( $status['lag'] === false ) {
+                               $res['lag'] = false;
+                       } elseif ( $res['lag'] !== false ) {
+                               $res['lag'] = max( $res['lag'], $status['lag'] );
+                       }
                        $res['since'] = min( $res['since'], $status['since'] );
+                       $res['pending'] = $res['pending'] ?: $db->writesPending();
                }
 
                return $res;
        }
 
-       /**
-        * Get slave lag. Currently supported only by MySQL.
-        *
-        * Note that this function will generate a fatal error on many
-        * installations. Most callers should use LoadBalancer::safeGetLag()
-        * instead.
-        *
-        * @return int Database replication lag in seconds
-        */
        public function getLag() {
                return 0;
        }