r72018 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r72017‎ | r72018 | r72019 >
Date:09:21, 31 August 2010
Author:nikerabbit
Status:ok
Tags:
Comment:
More improvements to message group cache
Modified paths:
  • /trunk/extensions/Translate/SpecialManageGroups.php (modified) (history)
  • /trunk/extensions/Translate/utils/MessageGroupCache.php (modified) (history)

Diff [purge]

Index: trunk/extensions/Translate/SpecialManageGroups.php
@@ -96,7 +96,7 @@
9797 $wgLang->time( $timestamp )
9898 );
9999
100 - if ( $this->changedSinceCached( $group ) ) {
 100+ if ( !$cache->isValid() ) {
101101 $out = '<span style="color:red">!!</span> ' . $out;
102102 }
103103
@@ -365,7 +365,9 @@
366366 continue;
367367 }
368368
369 - if ( !$this->changedSinceCached( $group, $code ) ) {
 369+ $cache = new MessageGroupCache( $group, $code );
 370+
 371+ if ( $cache->isValid() ) {
370372 continue;
371373 }
372374
@@ -376,7 +378,6 @@
377379 array( 'group' => $group->getId(), 'language' => $code )
378380 );
379381
380 - $cache = new MessageGroupCache( $group, $code );
381382 if ( !$cache->exists() ) {
382383 $modified[] = wfMsgHtml( 'translate-manage-modlang-new', $link );
383384 } else {
@@ -457,32 +458,4 @@
458459 $this->out->setSubtitle( implode( ' > ', $links ) );
459460 }
460461
461 - /**
462 - * Checks if the source file has changed since last check.
463 - * Uses modification timestamps and file hashes to check.
464 - */
465 - protected function changedSinceCached( $group, $code = 'en' ) {
466 - $cache = new MessageGroupCache( $group, $code );
467 - $filename = $group->getSourceFilePath( $code );
468 -
469 - $mtime = file_exists( $filename ) ? filemtime( $filename ) : false;
470 - $cachetime = $cache->exists() ? $cache->getTimestamp() : false;
471 -
472 - // No such language at all, or cache is up to date
473 - if ( $mtime <= $cachetime ) {
474 - return false;
475 - }
476 -
477 - // Timestamps differ (or either cache or the file does not exists)
478 - $oldhash = $cache->exists() ? $cache->getHash() : false;
479 - $newhash = file_exists( $filename ) ? md5( file_get_contents( $filename ) ) : false;
480 - wfDebugLog( 'translate-manage', "$mtime === $cachetime | $code | $oldhash !== $newhash\n" );
481 - if ( $newhash === $oldhash ) {
482 - // Update cache so that we don't need to compare hashes next time
483 - $cache->create();
484 - return false;
485 - }
486 -
487 - return true;
488 - }
489462 }
Index: trunk/extensions/Translate/utils/MessageGroupCache.php
@@ -1,14 +1,17 @@
22 <?php
33 /**
4 - * @todo Needs documentation.
 4+ * Code for caching the messages of file based message groups.
55 * @file
66 * @author Niklas Laxström
7 - * @copyright Copyright © 2009 Niklas Laxström
 7+ * @copyright Copyright © 2009-2010 Niklas Laxström
88 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
99 */
1010
1111 /**
12 - * @todo Needs documentation.
 12+ * Caches messages of file based message group source file. Can also track
 13+ * that the cache is up to date. Parsing the source files can be slow, so
 14+ * constructing CDB cache makes accessing that data constant speed regardless
 15+ * of the actual format.
1316 */
1417 class MessageGroupCache {
1518 /// \string
@@ -32,27 +35,43 @@
3336 $this->code = $code;
3437 }
3538
 39+ /**
 40+ * Returns whether cache exists for this language and group.
 41+ * @return \bool
 42+ */
3643 public function exists() {
3744 return file_exists( $this->getCacheFileName() );
3845 }
3946
 47+ /**
 48+ * Returns list of message keys that are stored.
 49+ * @return \List{String} Message keys that can be passed one-by-one to get() method.
 50+ */
4051 public function getKeys() {
41 - return unserialize( $this->open()->get( $this->specialKey( 'keys' ) ) );
 52+ return unserialize( $this->open()->get( '#keys' ) );
4253 }
4354
 55+ /**
 56+ * Returns timestamp in unix-format about when this cache was first created.
 57+ * @return \string Unix timestamp.
 58+ */
4459 public function getTimestamp() {
45 - return $this->open()->get( $this->specialKey( 'timestamp' ) );
 60+ return $this->open()->get( '#created' );
4661 }
4762
48 - public function getHash() {
49 - return $this->open()->get( $this->specialKey( 'hash' ) );
50 - }
51 -
 63+ /**
 64+ * Get an item from the cache.
 65+ * @return \string
 66+ */
5267 public function get( $key ) {
5368 return $this->open()->get( $key );
5469 }
5570
56 - public function create() {
 71+ /**
 72+ * Populates the cache from current state of the source file.
 73+ * @param $created \string Unix timestamp when the cache is created (for automatic updates).
 74+ */
 75+ public function create( $created = false ) {
5776 $this->close(); // Close the reader instance just to be sure
5877
5978 $group = MessageGroups::getGroup( $this->group );
@@ -64,24 +83,88 @@
6584
6685 $cache = CdbWriter::open( $this->getCacheFileName() );
6786 $keys = array_keys( $messages );
68 - $cache->set( $this->specialKey( 'keys' ), serialize( $keys ) );
 87+ $cache->set( '#keys', serialize( $keys ) );
6988
7089 foreach ( $messages as $key => $value ) {
7190 $cache->set( $key, $value );
7291 }
7392
74 - $cache->set( $this->specialKey( 'timestamp' ), wfTimestamp() );
75 - $cache->set( $this->specialKey( 'hash' ), $hash );
 93+ $cache->set( '#created', $created ? $created : wfTimestamp() );
 94+ $cache->set( '#updated', wfTimestamp() );
 95+ $cache->set( '#filehash', $hash );
 96+ $cache->set( '#msgcount', count( $messages ) );
 97+ $cache->set( '#msghash', md5( serialize( ksort( $messages ) ) ) );
 98+ $cache->set( '#version', '3' );
7699 $cache->close();
77100 }
78101
 102+ /**
 103+ * Checks whether the cache still reflects the source file.
 104+ * It uses multiple conditions to speed up the checking from file
 105+ * modification timestamps to hashing.
 106+ * @return \bool Wether the cache is up to date.
 107+ */
 108+ public function isValid() {
 109+ $group = MessageGroups::getGroup( $this->group );
 110+ $filename = $group->getSourceFilePath( $this->code );
 111+
 112+ // Timestamp and existence checks
 113+ if ( !$this->exists() ) {
 114+ return !file_exists( $filename );
 115+ } elseif ( !file_exists( $filename ) ) {
 116+ //$this->delete();
 117+ return false;
 118+ } else {
 119+ // Cache is up-to-date if created after file was last modified
 120+ return filemtime( $filename ) <= $this->get( '#updated' );
 121+ }
 122+ // From now on cache and source file exists, but source file mtime is newer
 123+ $created = $this->get( '#created' );
 124+
 125+ // File hash check
 126+ $newhash = md5( file_get_contents( $filename ) );
 127+ if ( $this->get( '#filehash' === $oldhash ) ) {
 128+ // Update cache so that we don't need to compare hashes next time
 129+ $cache->create( $created );
 130+ return true;
 131+ }
 132+
 133+ // Message count check
 134+ $messages = $group->load( $this->code );
 135+ if ( $this->get( '#msgcount' ) !== count( $messages ) ) {
 136+ // Number of messsages has changed
 137+ return false;
 138+ }
 139+
 140+ // Content hash check
 141+ if ( $this->get( '#msghash' ) === md5( serialize( ksort( $messages ) ) ) ) {
 142+ // Update cache so that we don't need to do slow checks next time
 143+ $cache->create( $createdat );
 144+ return true;
 145+ }
 146+
 147+ return false;
 148+ }
 149+
 150+ /**
 151+ * Open the cache for reading.
 152+ * @return MessageGroupCache
 153+ */
79154 protected function open() {
80155 if ( $this->cache === null ) {
81156 $this->cache = CdbReader::open( $this->getCacheFileName() );
 157+ if ( $this->cache->get( '#version' ) !== '3' ) {
 158+ $this->updateCacheFormat( $this->cache );
 159+ $this->close();
 160+ return $this->open();
 161+ }
82162 }
83163 return $this->cache;
84164 }
85165
 166+ /**
 167+ * Close the cache from reading.
 168+ */
86169 protected function close() {
87170 if ( $this->cache !== null ) {
88171 $this->cache->close();
@@ -89,11 +172,45 @@
90173 }
91174 }
92175
 176+ /**
 177+ * Returns full path the the cache file.
 178+ */
93179 protected function getCacheFileName() {
94180 return TranslateUtils::cacheFile( "translate_groupcache-{$this->group}-{$this->code}.cdb" );
95181 }
96182
97 - protected function specialKey( $key ) {
98 - return "<|$key#>";
 183+ /**
 184+ * Updates cache to cache format 2.
 185+ */
 186+ protected function updateCacheFormat( $oldcache ) {
 187+ // Read the data from the old format
 188+ $conv = array(
 189+ '#keys' => $oldcache->get( '<|keys#>' ),
 190+ '#created' => $oldcache->get( '<|timestamp#>' ),
 191+ '#updated' => wfTimestamp(),
 192+ '#filehash' => $oldcache->get( '<|hash#>' ),
 193+ '#version' => '3',
 194+ );
 195+ $conv['#msgcount'] = count( $conv['#keys'] );
 196+
 197+ $messages = array();
 198+ foreach ( unserialize( $conv['#keys'] ) as $key ) {
 199+ $messages[$key] = $oldcache->get( $key );
 200+ }
 201+
 202+ $conv['#msghash'] = md5( serialize( ksort( $messages ) ) );
 203+ $oldcache->close();
 204+
 205+ // Store the data in new format
 206+ $cache = CdbWriter::open( $this->getCacheFileName() );
 207+ foreach ( $conv as $key => $value ) {
 208+ $cache->set( $key, $value );
 209+ }
 210+ foreach ( $messages as $key => $value ) {
 211+ $cache->set( $key, $value );
 212+ }
 213+ $cache->close();
 214+
99215 }
 216+
100217 }

Status & tagging log