summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Translate/utils/MessageIndex.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/Translate/utils/MessageIndex.php')
-rw-r--r--www/wiki/extensions/Translate/utils/MessageIndex.php170
1 files changed, 115 insertions, 55 deletions
diff --git a/www/wiki/extensions/Translate/utils/MessageIndex.php b/www/wiki/extensions/Translate/utils/MessageIndex.php
index d77707ad..0015d0aa 100644
--- a/www/wiki/extensions/Translate/utils/MessageIndex.php
+++ b/www/wiki/extensions/Translate/utils/MessageIndex.php
@@ -5,7 +5,7 @@
* @file
* @author Niklas Laxstrom
* @copyright Copyright © 2008-2013, Niklas Laxström
- * @license GPL-2.0+
+ * @license GPL-2.0-or-later
*/
/**
@@ -23,6 +23,11 @@ abstract class MessageIndex {
protected static $instance;
/**
+ * @var MapCacheLRU|null
+ */
+ private static $keysCache;
+
+ /**
* @return self
*/
public static function singleton() {
@@ -58,19 +63,34 @@ abstract class MessageIndex {
$title = $handle->getTitle();
if ( !$title->inNamespaces( $wgTranslateMessageNamespaces ) ) {
- return array();
+ return [];
}
$namespace = $title->getNamespace();
$key = $handle->getKey();
$normkey = TranslateUtils::normaliseKey( $namespace, $key );
- $value = self::singleton()->get( $normkey );
- if ( $value !== null ) {
- return (array)$value;
- } else {
- return array();
+ $cache = self::getCache();
+ $value = $cache->get( $normkey );
+ if ( $value === null ) {
+ $value = self::singleton()->get( $normkey );
+ $value = $value !== null
+ ? (array)$value
+ : [];
+ $cache->set( $normkey, $value );
}
+
+ return $value;
+ }
+
+ /**
+ * @return MapCacheLRU
+ */
+ private static function getCache() {
+ if ( self::$keysCache === null ) {
+ self::$keysCache = new MapCacheLRU( 30 );
+ }
+ return self::$keysCache;
}
/**
@@ -100,9 +120,20 @@ abstract class MessageIndex {
}
}
- /// @return array
+ /**
+ * @param bool $forRebuild
+ * @return array
+ */
abstract public function retrieve( $forRebuild = false );
+ /**
+ * @since 2018.01
+ * @return string[]
+ */
+ public function getKeys() {
+ return array_keys( $this->retrieve() );
+ }
+
abstract protected function store( array $array, array $diff );
protected function lock() {
@@ -121,7 +152,7 @@ abstract class MessageIndex {
wfWarn( $msg );
$recursion--;
- return array();
+ return [];
}
$recursion++;
@@ -131,15 +162,19 @@ abstract class MessageIndex {
throw new Exception( __CLASS__ . ': unable to acquire lock' );
}
- $new = $old = array();
+ self::getCache()->clear();
+
+ $new = $old = [];
$old = $this->retrieve( 'rebuild' );
- $postponed = array();
+ $postponed = [];
/**
* @var MessageGroup $g
*/
foreach ( $groups as $g ) {
if ( !$g->exists() ) {
+ $id = $g->getId();
+ wfWarn( __METHOD__ . ": group '$id' is registered but does not exist" );
continue;
}
@@ -195,26 +230,26 @@ abstract class MessageIndex {
* @return array
*/
public static function getArrayDiff( array $old, array $new ) {
- $values = array();
+ $values = [];
$record = function ( $groups ) use ( &$values ) {
foreach ( $groups as $group ) {
$values[$group] = true;
}
};
- $keys = array(
- 'add' => array(),
- 'del' => array(),
- 'mod' => array(),
- );
+ $keys = [
+ 'add' => [],
+ 'del' => [],
+ 'mod' => [],
+ ];
foreach ( $new as $key => $groups ) {
if ( !isset( $old[$key] ) ) {
- $keys['add'][$key] = array( array(), (array)$groups );
+ $keys['add'][$key] = [ [], (array)$groups ];
$record( (array)$groups );
// Using != here on purpose to ignore the order of items
} elseif ( $groups != $old[$key] ) {
- $keys['mod'][$key] = array( (array)$old[$key], (array)$groups );
+ $keys['mod'][$key] = [ (array)$old[$key], (array)$groups ];
$record( array_diff( (array)$old[$key], (array)$groups ) );
$record( array_diff( (array)$groups, (array)$old[$key] ) );
}
@@ -222,16 +257,16 @@ abstract class MessageIndex {
foreach ( $old as $key => $groups ) {
if ( !isset( $new[$key] ) ) {
- $keys['del'][$key] = array( (array)$groups, array() );
- $record( (array)$groups, array() );
+ $keys['del'][$key] = [ (array)$groups, [] ];
+ $record( (array)$groups, [] );
}
// We already checked for diffs above
}
- return array(
+ return [
'keys' => $keys,
'values' => array_keys( $values ),
- );
+ ];
}
/**
@@ -247,15 +282,15 @@ abstract class MessageIndex {
list( $ns, $pagename ) = explode( ':', $key, 2 );
$title = Title::makeTitle( $ns, $pagename );
$handle = new MessageHandle( $title );
- list ( $oldGroups, $newGroups ) = $data;
+ list( $oldGroups, $newGroups ) = $data;
Hooks::run( 'TranslateEventMessageMembershipChange',
- array( $handle, $oldGroups, $newGroups ) );
+ [ $handle, $oldGroups, $newGroups ] );
}
}
}
/**
- * @param array $hugearray
+ * @param array &$hugearray
* @param MessageGroup $g
* @param bool $ignore
*/
@@ -296,7 +331,7 @@ abstract class MessageIndex {
// references instead. References are hard!
$value = & $hugearray[$key];
unset( $hugearray[$key] );
- $hugearray[$key] = array( &$value, &$id );
+ $hugearray[$key] = [ &$value, &$id ];
}
} else {
$hugearray[$key] = & $id;
@@ -305,9 +340,13 @@ abstract class MessageIndex {
unset( $id ); // Disconnect the previous references to this $id
}
- /* These are probably slower than serialize and unserialize,
+ /**
+ * These are probably slower than serialize and unserialize,
* but they are more space efficient because we only need
- * strings and arrays. */
+ * strings and arrays.
+ * @param mixed $data
+ * @return mixed
+ */
protected function serialize( $data ) {
if ( is_array( $data ) ) {
return implode( '|', $data );
@@ -408,11 +447,20 @@ class DatabaseMessageIndex extends MessageIndex {
}
protected function unlock() {
+ $fname = __METHOD__;
$dbw = wfGetDB( DB_MASTER );
// Unlock once the rows are actually unlocked to avoid deadlocks
- $dbw->onTransactionIdle( function () use ( $dbw ) {
- $dbw->unlock( 'translate-messageindex', __METHOD__ );
- } );
+ if ( !$dbw->trxLevel() ) {
+ $dbw->unlock( 'translate-messageindex', $fname );
+ } elseif ( method_exists( $dbw, 'onTransactionResolution' ) ) { // 1.28
+ $dbw->onTransactionResolution( function () use ( $dbw, $fname ) {
+ $dbw->unlock( 'translate-messageindex', $fname );
+ } );
+ } else {
+ $dbw->onTransactionIdle( function () use ( $dbw, $fname ) {
+ $dbw->unlock( 'translate-messageindex', $fname );
+ } );
+ }
return true;
}
@@ -426,9 +474,9 @@ class DatabaseMessageIndex extends MessageIndex {
return $this->index;
}
- $dbr = wfGetDB( $forRebuild ? DB_MASTER : DB_SLAVE );
- $res = $dbr->select( 'translate_messageindex', '*', array(), __METHOD__ );
- $this->index = array();
+ $dbr = wfGetDB( $forRebuild ? DB_MASTER : DB_REPLICA );
+ $res = $dbr->select( 'translate_messageindex', '*', [], __METHOD__ );
+ $this->index = [];
foreach ( $res as $row ) {
$this->index[$row->tmi_key] = $this->unserialize( $row->tmi_value );
}
@@ -437,11 +485,11 @@ class DatabaseMessageIndex extends MessageIndex {
}
protected function get( $key ) {
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$value = $dbr->selectField(
'translate_messageindex',
'tmi_value',
- array( 'tmi_key' => $key ),
+ [ 'tmi_key' => $key ],
__METHOD__
);
@@ -455,30 +503,30 @@ class DatabaseMessageIndex extends MessageIndex {
}
protected function store( array $array, array $diff ) {
- $updates = array();
+ $updates = [];
- foreach ( array( $diff['add'], $diff['mod'] ) as $changes ) {
+ foreach ( [ $diff['add'], $diff['mod'] ] as $changes ) {
foreach ( $changes as $key => $data ) {
list( $old, $new ) = $data;
- $updates[] = array(
+ $updates[] = [
'tmi_key' => $key,
'tmi_value' => $this->serialize( $new ),
- );
+ ];
}
}
- $index = array( 'tmi_key' );
+ $index = [ 'tmi_key' ];
$deletions = array_keys( $diff['del'] );
$dbw = wfGetDB( DB_MASTER );
$dbw->startAtomic( __METHOD__ );
- if ( $updates !== array() ) {
- $dbw->replace( 'translate_messageindex', array( $index ), $updates, __METHOD__ );
+ if ( $updates !== [] ) {
+ $dbw->replace( 'translate_messageindex', [ $index ], $updates, __METHOD__ );
}
- if ( $deletions !== array() ) {
- $dbw->delete( 'translate_messageindex', array( 'tmi_key' => $deletions ), __METHOD__ );
+ if ( $deletions !== [] ) {
+ $dbw->delete( 'translate_messageindex', [ 'tmi_key' => $deletions ], __METHOD__ );
}
$dbw->endAtomic( __METHOD__ );
@@ -556,7 +604,7 @@ class CDBMessageIndex extends MessageIndex {
protected $index;
/**
- * @var CdbReader|null
+ * @var \Cdb\Reader|null
*/
protected $reader;
@@ -576,15 +624,28 @@ class CDBMessageIndex extends MessageIndex {
return $this->index;
}
- $keys = (array)$this->unserialize( $reader->get( '#keys' ) );
- $this->index = array();
- foreach ( $keys as $key ) {
+ $this->index = [];
+ foreach ( $this->getKeys() as $key ) {
$this->index[$key] = $this->unserialize( $reader->get( $key ) );
}
return $this->index;
}
+ public function getKeys() {
+ $reader = $this->getReader();
+ $keys = [];
+ while ( true ) {
+ $key = $keys === [] ? $reader->firstkey() : $reader->nextkey();
+ if ( $key === false ) {
+ break;
+ }
+ $keys[] = $key;
+ }
+
+ return $keys;
+ }
+
protected function get( $key ) {
$reader = $this->getReader();
// We might have the full cache loaded
@@ -611,8 +672,6 @@ class CDBMessageIndex extends MessageIndex {
$file = TranslateUtils::cacheFile( $this->filename );
$cache = \Cdb\Writer::open( $file );
- $keys = array_keys( $array );
- $cache->set( '#keys', $this->serialize( $keys ) );
foreach ( $array as $key => $value ) {
$value = $this->serialize( $value );
@@ -632,11 +691,12 @@ class CDBMessageIndex extends MessageIndex {
$file = TranslateUtils::cacheFile( $this->filename );
if ( !file_exists( $file ) ) {
// Create an empty index to allow rebuild
- $this->store( array(), array() );
+ $this->store( [], [] );
$this->index = $this->rebuild();
}
- return $this->reader = \Cdb\Reader::open( $file );
+ $this->reader = \Cdb\Reader::open( $file );
+ return $this->reader;
}
}
@@ -651,7 +711,7 @@ class HashMessageIndex extends MessageIndex {
/**
* @var array
*/
- protected $index = array();
+ protected $index = [];
/**
* @param bool $forRebuild