From: Tim Starling Date: Fri, 2 Dec 2011 02:59:11 +0000 (+0000) Subject: purgeParserCache.php improvements: X-Git-Tag: 1.31.0-rc.0~26196 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/?a=commitdiff_plain;h=53d267b3dce25f7b9c7b4216456ad3850ea5035e;p=lhc%2Fweb%2Fwiklou.git purgeParserCache.php improvements: * Do queries in batches of 100 rows instead of all at once. Note that if there are a lot of objects with the exact same expiry time, it might take multiple runs of the script to delete them all. * Progress meter. --- diff --git a/includes/objectcache/BagOStuff.php b/includes/objectcache/BagOStuff.php index 5d635ed580..81ad662168 100644 --- a/includes/objectcache/BagOStuff.php +++ b/includes/objectcache/BagOStuff.php @@ -93,10 +93,14 @@ abstract class BagOStuff { /** * Delete all objects expiring before a certain date. + * @param $date The reference date in MW format + * @param $progressCallback Optional, a function which will be called + * regularly during long-running operations with the percentage progress + * as the first parameter. * * @return true on success, false if unimplemented */ - public function deleteObjectsExpiringBefore( $date ) { + public function deleteObjectsExpiringBefore( $date, $progressCallback = false ) { // stub return false; } diff --git a/includes/objectcache/MultiWriteBagOStuff.php b/includes/objectcache/MultiWriteBagOStuff.php index 2b88b427c9..0d95a846d6 100644 --- a/includes/objectcache/MultiWriteBagOStuff.php +++ b/includes/objectcache/MultiWriteBagOStuff.php @@ -101,10 +101,10 @@ class MultiWriteBagOStuff extends BagOStuff { * * Succeed if any of the child caches succeed. */ - public function deleteObjectsExpiringBefore( $date ) { + public function deleteObjectsExpiringBefore( $date, $progressCallback = false ) { $ret = false; foreach ( $this->caches as $cache ) { - if ( $cache->deleteObjectsExpiringBefore( $date ) ) { + if ( $cache->deleteObjectsExpiringBefore( $date, $progressCallback ) ) { $ret = true; } } diff --git a/includes/objectcache/SqlBagOStuff.php b/includes/objectcache/SqlBagOStuff.php index 77374c75e2..2c43d1b7ad 100644 --- a/includes/objectcache/SqlBagOStuff.php +++ b/includes/objectcache/SqlBagOStuff.php @@ -311,18 +311,67 @@ class SqlBagOStuff extends BagOStuff { /** * Delete objects from the database which expire before a certain date. */ - public function deleteObjectsExpiringBefore( $timestamp ) { + public function deleteObjectsExpiringBefore( $timestamp, $progressCallback = false ) { $db = $this->getDB(); $dbTimestamp = $db->timestamp( $timestamp ); + $totalSeconds = false; + $baseConds = array( 'exptime < ' . $db->addQuotes( $dbTimestamp ) ); try { for ( $i = 0; $i < $this->shards; $i++ ) { - $db->begin(); - $db->delete( - $this->getTableByShard( $i ), - array( 'exptime < ' . $db->addQuotes( $dbTimestamp ) ), - __METHOD__ ); - $db->commit(); + $maxExpTime = false; + while ( true ) { + $conds = $baseConds; + if ( $maxExpTime !== false ) { + $conds[] = 'exptime > ' . $db->addQuotes( $maxExpTime ); + } + $rows = $db->select( + $this->getTableByShard( $i ), + array( 'keyname', 'exptime' ), + $conds, + __METHOD__, + array( 'LIMIT' => 100, 'ORDER BY' => 'exptime' ) ); + if ( !$rows->numRows() ) { + break; + } + $keys = array(); + $row = $rows->current(); + $minExpTime = $row->exptime; + if ( $totalSeconds === false ) { + $totalSeconds = wfTimestamp( TS_UNIX, $timestamp ) + - wfTimestamp( TS_UNIX, $minExpTime ); + } + foreach ( $rows as $row ) { + $keys[] = $row->keyname; + $maxExpTime = $row->exptime; + } + + $db->begin(); + $db->delete( + $this->getTableByShard( $i ), + array( + 'exptime >= ' . $db->addQuotes( $minExpTime ), + 'exptime < ' . $db->addQuotes( $dbTimestamp ), + 'keyname' => $keys + ), + __METHOD__ ); + $db->commit(); + + if ( $progressCallback ) { + if ( intval( $totalSeconds ) === 0 ) { + $percent = 0; + } else { + $remainingSeconds = wfTimestamp( TS_UNIX, $timestamp ) + - wfTimestamp( TS_UNIX, $maxExpTime ); + if ( $remainingSeconds > $totalSeconds ) { + $totalSeconds = $remainingSeconds; + } + $percent = ( $i + $remainingSeconds / $totalSeconds ) + / $this->shards * 100; + } + call_user_func( $progressCallback, $percent ); + } + } } } catch ( DBQueryError $e ) { $this->handleWriteError( $e ); diff --git a/maintenance/purgeParserCache.php b/maintenance/purgeParserCache.php index 4b550b6e4c..7a8f6f7c11 100644 --- a/maintenance/purgeParserCache.php +++ b/maintenance/purgeParserCache.php @@ -3,6 +3,8 @@ require( dirname( __FILE__ ) . '/Maintenance.php' ); class PurgeParserCache extends Maintenance { + var $lastProgress; + function __construct() { parent::__construct(); $this->addDescription( "Remove old objects from the parser cache. " . @@ -31,12 +33,26 @@ class PurgeParserCache extends Maintenance { echo "Deleting objects expiring before " . $english->timeanddate( $date ) . "\n"; $pc = wfGetParserCacheStorage(); - $success = $pc->deleteObjectsExpiringBefore( $date ); + $success = $pc->deleteObjectsExpiringBefore( $date, array( $this, 'showProgress' ) ); if ( !$success ) { - echo "Cannot purge this kind of parser cache.\n"; + echo "\nCannot purge this kind of parser cache.\n"; exit( 1 ); } - echo "Done\n"; + $this->showProgress( 100 ); + echo "\nDone\n"; + } + + function showProgress( $percent ) { + $percentString = sprintf( "%.2f", $percent ); + if ( $percentString === $this->lastProgress ) { + return; + } + $this->lastProgress = $percentString; + + $stars = floor( $percent / 2 ); + echo '[' . str_repeat( '*', $stars ), str_repeat( '.', 50 - $stars ) . '] ' . + "$percentString%\r"; + } } $maintClass = 'PurgeParserCache';