From: Tim Starling Date: Fri, 9 Sep 2011 03:51:45 +0000 (+0000) Subject: * Added a script to reduce disk space on a MySQL parser cache setup such as the one... X-Git-Tag: 1.31.0-rc.0~27774 X-Git-Url: https://git.cyclocoop.org/%242?a=commitdiff_plain;h=cac02778e4f8fd660e8c212562f5164c45477a19;p=lhc%2Fweb%2Fwiklou.git * Added a script to reduce disk space on a MySQL parser cache setup such as the one at Wikimedia at the moment, by removing all objects which expire before a given time. * Fixed unintentional shortcut evaluation in MultiWriteBagOStuff::doWrite(). It would have caused writes to be skipped on the second cache if the first cache failed, now writes should be attempted on all caches. --- diff --git a/includes/objectcache/BagOStuff.php b/includes/objectcache/BagOStuff.php index 634eff35f7..97b6cb2cda 100644 --- a/includes/objectcache/BagOStuff.php +++ b/includes/objectcache/BagOStuff.php @@ -91,6 +91,16 @@ abstract class BagOStuff { return array(); } + /** + * Delete all objects expiring before a certain date. + * + * @return true on success, false if unimplemented + */ + public function deleteObjectsExpiringBefore( $date ) { + // stub + return false; + } + /* *** Emulated functions *** */ public function add( $key, $value, $exptime = 0 ) { diff --git a/includes/objectcache/MultiWriteBagOStuff.php b/includes/objectcache/MultiWriteBagOStuff.php index 4ed1188d35..2b88b427c9 100644 --- a/includes/objectcache/MultiWriteBagOStuff.php +++ b/includes/objectcache/MultiWriteBagOStuff.php @@ -89,9 +89,25 @@ class MultiWriteBagOStuff extends BagOStuff { array_shift( $args ); foreach ( $this->caches as $cache ) { - $ret = $ret && call_user_func_array( array( $cache, $method ), $args ); + if ( !call_user_func_array( array( $cache, $method ), $args ) ) { + $ret = false; + } } return $ret; } + /** + * Delete objects expiring before a certain date. + * + * Succeed if any of the child caches succeed. + */ + public function deleteObjectsExpiringBefore( $date ) { + $ret = false; + foreach ( $this->caches as $cache ) { + if ( $cache->deleteObjectsExpiringBefore( $date ) ) { + $ret = true; + } + } + return $ret; + } } diff --git a/includes/objectcache/SqlBagOStuff.php b/includes/objectcache/SqlBagOStuff.php index 7eb125ac70..78817d0bef 100644 --- a/includes/objectcache/SqlBagOStuff.php +++ b/includes/objectcache/SqlBagOStuff.php @@ -305,21 +305,29 @@ class SqlBagOStuff extends BagOStuff { } public function expireAll() { + $this->deleteObjectsExpiringBefore( wfTimestampNow() ); + } + + /** + * Delete objects from the database which expire before a certain date. + */ + public function deleteObjectsExpiringBefore( $timestamp ) { $db = $this->getDB(); - $now = $db->timestamp(); + $dbTimestamp = $db->timestamp( $timestamp ); try { for ( $i = 0; $i < $this->shards; $i++ ) { $db->begin(); $db->delete( $this->getTableByShard( $i ), - array( 'exptime < ' . $db->addQuotes( $now ) ), + array( 'exptime < ' . $db->addQuotes( $dbTimestamp ) ), __METHOD__ ); $db->commit(); } } catch ( DBQueryError $e ) { $this->handleWriteError( $e ); } + return true; } public function deleteAll() { diff --git a/maintenance/purgeParserCache.php b/maintenance/purgeParserCache.php new file mode 100644 index 0000000000..4b550b6e4c --- /dev/null +++ b/maintenance/purgeParserCache.php @@ -0,0 +1,43 @@ +addDescription( "Remove old objects from the parser cache. " . + "This only works when the parser cache is in an SQL database." ); + $this->addOption( 'expiredate', 'Delete objects expiring before this date.', false, true ); + $this->addOption( 'age', + 'Delete objects created more than this many seconds ago, assuming $wgParserCacheExpireTime '. + 'has been consistent.', + false, true ); + } + + function execute() { + $inputDate = $this->getOption( 'expiredate' ); + $inputAge = $this->getOption( 'age' ); + if ( $inputDate !== null ) { + $date = wfTimestamp( TS_MW, strtotime( $inputDate ) ); + } elseif ( $inputAge !== null ) { + global $wgParserCacheExpireTime; + $date = wfTimestamp( TS_MW, time() + $wgParserCacheExpireTime - intval( $inputAge ) ); + } else { + echo "Must specify either --expiredate or --age\n"; + exit( 1 ); + } + + $english = Language::factory( 'en' ); + echo "Deleting objects expiring before " . $english->timeanddate( $date ) . "\n"; + + $pc = wfGetParserCacheStorage(); + $success = $pc->deleteObjectsExpiringBefore( $date ); + if ( !$success ) { + echo "Cannot purge this kind of parser cache.\n"; + exit( 1 ); + } + echo "Done\n"; + } +} +$maintClass = 'PurgeParserCache'; +require_once( RUN_MAINTENANCE_IF_MAIN );