X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Flibs%2Frdbms%2Fdatabase%2FDatabase.php;h=d1230e00f18befd7bd626761d858ac5e9bdab2e7;hp=c6b99efee8770f8ae8c3a4e44417d44af73c8352;hb=ab85b17368dba24dbd60049d2bbe31713d585243;hpb=c7fc4ef9bf3dc044e8da3497fdab226bc177dd88 diff --git a/includes/libs/rdbms/database/Database.php b/includes/libs/rdbms/database/Database.php index c6b99efee8..d1230e00f1 100644 --- a/includes/libs/rdbms/database/Database.php +++ b/includes/libs/rdbms/database/Database.php @@ -677,6 +677,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware ); } + public function preCommitCallbacksPending() { + return $this->trxLevel && $this->trxPreCommitCallbacks; + } + /** * @return string|null */ @@ -722,17 +726,15 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } /** - * Get the list of method names that have pending write queries or callbacks - * for this transaction + * List the methods that have write queries or callbacks for the current transaction * - * @return array + * This method should not be used outside of Database/LoadBalancer + * + * @return string[] + * @since 1.32 */ - protected function pendingWriteAndCallbackCallers() { - if ( !$this->trxLevel ) { - return []; - } - - $fnames = $this->trxWriteCallers; + public function pendingWriteAndCallbackCallers() { + $fnames = $this->pendingWriteCallers(); foreach ( [ $this->trxIdleCallbacks, $this->trxPreCommitCallbacks, @@ -960,12 +962,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } // Sanity check that no callbacks are dangling - if ( - $this->trxIdleCallbacks || $this->trxPreCommitCallbacks || $this->trxEndCallbacks - ) { + $fnames = $this->pendingWriteAndCallbackCallers(); + if ( $fnames ) { throw new RuntimeException( - "Transaction callbacks are still pending:\n" . - implode( ', ', $this->pendingWriteAndCallbackCallers() ) + "Transaction callbacks are still pending:\n" . implode( ', ', $fnames ) ); } @@ -3292,7 +3292,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $this->trxEndCallbacks[] = [ $callback, $fname, $this->currentAtomicSectionId() ]; } - final public function onTransactionIdle( callable $callback, $fname = __METHOD__ ) { + final public function onTransactionCommitOrIdle( callable $callback, $fname = __METHOD__ ) { if ( !$this->trxLevel && $this->getTransactionRoundId() ) { // Start an implicit transaction similar to how query() does $this->begin( __METHOD__, self::TRANSACTION_INTERNAL ); @@ -3305,6 +3305,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } } + final public function onTransactionIdle( callable $callback, $fname = __METHOD__ ) { + $this->onTransactionCommitOrIdle( $callback, $fname ); + } + final public function onTransactionPreCommitOrIdle( callable $callback, $fname = __METHOD__ ) { if ( !$this->trxLevel && $this->getTransactionRoundId() ) { // Start an implicit transaction similar to how query() does @@ -3318,7 +3322,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware // No transaction is active nor will start implicitly, so make one for this callback $this->startAtomic( __METHOD__, self::ATOMIC_CANCELABLE ); try { - call_user_func( $callback ); + call_user_func( $callback, $this ); $this->endAtomic( __METHOD__ ); } catch ( Exception $e ) { $this->cancelAtomic( __METHOD__ ); @@ -3387,7 +3391,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware if ( in_array( $entry[2], $sectionIds, true ) ) { $callback = $entry[0]; $this->trxEndCallbacks[$key][0] = function () use ( $callback ) { - return $callback( self::TRIGGER_ROLLBACK ); + return $callback( self::TRIGGER_ROLLBACK, $this ); }; } } @@ -3414,19 +3418,25 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } /** - * Actually run and consume any "on transaction idle/resolution" callbacks. + * Actually consume and run any "on transaction idle/resolution" callbacks. * * This method should not be used outside of Database/LoadBalancer * * @param int $trigger IDatabase::TRIGGER_* constant + * @return int Number of callbacks attempted * @since 1.20 * @throws Exception */ public function runOnTransactionIdleCallbacks( $trigger ) { + if ( $this->trxLevel ) { // sanity + throw new DBUnexpectedError( $this, __METHOD__ . ': a transaction is still open.' ); + } + if ( $this->trxEndCallbacksSuppressed ) { - return; + return 0; } + $count = 0; $autoTrx = $this->getFlag( self::DBO_TRX ); // automatic begin() enabled? /** @var Exception $e */ $e = null; // first exception @@ -3439,9 +3449,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $this->trxEndCallbacks = []; // consumed (recursion guard) foreach ( $callbacks as $callback ) { try { + ++$count; list( $phpCallback ) = $callback; $this->clearFlag( self::DBO_TRX ); // make each query its own transaction - call_user_func_array( $phpCallback, [ $trigger ] ); + call_user_func( $phpCallback, $trigger, $this ); if ( $autoTrx ) { $this->setFlag( self::DBO_TRX ); // restore automatic begin() } else { @@ -3462,25 +3473,31 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware if ( $e instanceof Exception ) { throw $e; // re-throw any first exception } + + return $count; } /** - * Actually run and consume any "on transaction pre-commit" callbacks. + * Actually consume and run any "on transaction pre-commit" callbacks. * * This method should not be used outside of Database/LoadBalancer * * @since 1.22 + * @return int Number of callbacks attempted * @throws Exception */ public function runOnTransactionPreCommitCallbacks() { + $count = 0; + $e = null; // first exception do { // callbacks may add callbacks :) $callbacks = $this->trxPreCommitCallbacks; $this->trxPreCommitCallbacks = []; // consumed (and recursion guard) foreach ( $callbacks as $callback ) { try { + ++$count; list( $phpCallback ) = $callback; - call_user_func( $phpCallback ); + call_user_func( $phpCallback, $this ); } catch ( Exception $ex ) { call_user_func( $this->errorLogger, $ex ); $e = $e ?: $ex; @@ -3491,6 +3508,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware if ( $e instanceof Exception ) { throw $e; // re-throw any first exception } + + return $count; } /** @@ -3591,7 +3610,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $savepointId = $cancelable === self::ATOMIC_CANCELABLE ? self::$NOT_APPLICABLE : null; if ( !$this->trxLevel ) { - $this->begin( $fname, self::TRANSACTION_INTERNAL ); + $this->begin( $fname, self::TRANSACTION_INTERNAL ); // sets trxAutomatic // 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( self::DBO_TRX ) ) { @@ -3845,8 +3864,11 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware ); } - $this->runOnTransactionIdleCallbacks( self::TRIGGER_COMMIT ); - $this->runTransactionListenerCallbacks( self::TRIGGER_COMMIT ); + // With FLUSHING_ALL_PEERS, callbacks will be explicitly run later + if ( $flush !== self::FLUSHING_ALL_PEERS ) { + $this->runOnTransactionIdleCallbacks( self::TRIGGER_COMMIT ); + $this->runTransactionListenerCallbacks( self::TRIGGER_COMMIT ); + } } /** @@ -3895,7 +3917,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $this->trxIdleCallbacks = []; $this->trxPreCommitCallbacks = []; - if ( $trxActive ) { + // With FLUSHING_ALL_PEERS, callbacks will be explicitly run later + if ( $trxActive && $flush !== self::FLUSHING_ALL_PEERS ) { try { $this->runOnTransactionIdleCallbacks( self::TRIGGER_ROLLBACK ); } catch ( Exception $e ) { @@ -4615,5 +4638,12 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } } -class_alias( Database::class, 'DatabaseBase' ); // b/c for old name -class_alias( Database::class, 'Database' ); // b/c global alias +/** + * @deprecated since 1.28 + */ +class_alias( Database::class, 'DatabaseBase' ); + +/** + * @deprecated since 1.29 + */ +class_alias( Database::class, 'Database' );