'MapCacheLRU' => 'includes/cache/MapCacheLRU.php',
'MessageCache' => 'includes/cache/MessageCache.php',
'ObjectFileCache' => 'includes/cache/ObjectFileCache.php',
- 'ProcessCacheLRU' => 'includes/cache/ProcessCacheLRU.php',
'ResourceFileCache' => 'includes/cache/ResourceFileCache.php',
# includes/changes
'JSTokenizer' => 'includes/libs/jsminplus.php',
'MultiHttpClient' => 'includes/libs/MultiHttpClient.php',
'MWMessagePack' => 'includes/libs/MWMessagePack.php',
+ 'ProcessCacheLRU' => 'includes/libs/ProcessCacheLRU.php',
'RunningStat' => 'includes/libs/RunningStat.php',
'ScopedCallback' => 'includes/libs/ScopedCallback.php',
'ScopedPHPTimeout' => 'includes/libs/ScopedPHPTimeout.php',
+++ /dev/null
-<?php
-/**
- * Per-process memory cache for storing items.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Cache
- */
-
-/**
- * Handles per process caching of items
- * @ingroup Cache
- */
-class ProcessCacheLRU {
- /** @var Array */
- protected $cache = array(); // (key => prop => value)
- /** @var Array */
- protected $cacheTimes = array(); // (key => prop => UNIX timestamp)
-
- protected $maxCacheKeys; // integer; max entries
-
- /**
- * @param $maxKeys integer Maximum number of entries allowed (min 1).
- * @throws MWException When $maxCacheKeys is not an int or =< 0.
- */
- public function __construct( $maxKeys ) {
- if ( !is_int( $maxKeys ) || $maxKeys < 1 ) {
- throw new MWException( __METHOD__ . " must be given an integer and >= 1" );
- }
- $this->maxCacheKeys = $maxKeys;
- }
-
- /**
- * Set a property field for a cache entry.
- * This will prune the cache if it gets too large based on LRU.
- * If the item is already set, it will be pushed to the top of the cache.
- *
- * @param $key string
- * @param $prop string
- * @param $value mixed
- * @return void
- */
- public function set( $key, $prop, $value ) {
- if ( isset( $this->cache[$key] ) ) {
- $this->ping( $key ); // push to top
- } elseif ( count( $this->cache ) >= $this->maxCacheKeys ) {
- reset( $this->cache );
- $evictKey = key( $this->cache );
- unset( $this->cache[$evictKey] );
- unset( $this->cacheTimes[$evictKey] );
- }
- $this->cache[$key][$prop] = $value;
- $this->cacheTimes[$key][$prop] = time();
- }
-
- /**
- * Check if a property field exists for a cache entry.
- *
- * @param $key string
- * @param $prop string
- * @param $maxAge integer Ignore items older than this many seconds (since 1.21)
- * @return bool
- */
- public function has( $key, $prop, $maxAge = 0 ) {
- if ( isset( $this->cache[$key][$prop] ) ) {
- return ( $maxAge <= 0 || ( time() - $this->cacheTimes[$key][$prop] ) <= $maxAge );
- }
-
- return false;
- }
-
- /**
- * Get a property field for a cache entry.
- * This returns null if the property is not set.
- * If the item is already set, it will be pushed to the top of the cache.
- *
- * @param $key string
- * @param $prop string
- * @return mixed
- */
- public function get( $key, $prop ) {
- if ( isset( $this->cache[$key][$prop] ) ) {
- $this->ping( $key ); // push to top
- return $this->cache[$key][$prop];
- } else {
- return null;
- }
- }
-
- /**
- * Clear one or several cache entries, or all cache entries
- *
- * @param $keys string|Array
- * @return void
- */
- public function clear( $keys = null ) {
- if ( $keys === null ) {
- $this->cache = array();
- $this->cacheTimes = array();
- } else {
- foreach ( (array)$keys as $key ) {
- unset( $this->cache[$key] );
- unset( $this->cacheTimes[$key] );
- }
- }
- }
-
- /**
- * Push an entry to the top of the cache
- *
- * @param $key string
- */
- protected function ping( $key ) {
- $item = $this->cache[$key];
- unset( $this->cache[$key] );
- $this->cache[$key] = $item;
- }
-}
--- /dev/null
+<?php
+/**
+ * Per-process memory cache for storing items.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Cache
+ */
+
+/**
+ * Handles per process caching of items
+ * @ingroup Cache
+ */
+class ProcessCacheLRU {
+ /** @var Array */
+ protected $cache = array(); // (key => prop => value)
+ /** @var Array */
+ protected $cacheTimes = array(); // (key => prop => UNIX timestamp)
+
+ protected $maxCacheKeys; // integer; max entries
+
+ /**
+ * @param $maxKeys integer Maximum number of entries allowed (min 1).
+ * @throws UnexpectedValueException When $maxCacheKeys is not an int or =< 0.
+ */
+ public function __construct( $maxKeys ) {
+ if ( !is_int( $maxKeys ) || $maxKeys < 1 ) {
+ throw new UnexpectedValueException( __METHOD__ . " must be given an integer >= 1" );
+ }
+ $this->maxCacheKeys = $maxKeys;
+ }
+
+ /**
+ * Set a property field for a cache entry.
+ * This will prune the cache if it gets too large based on LRU.
+ * If the item is already set, it will be pushed to the top of the cache.
+ *
+ * @param $key string
+ * @param $prop string
+ * @param $value mixed
+ * @return void
+ */
+ public function set( $key, $prop, $value ) {
+ if ( isset( $this->cache[$key] ) ) {
+ $this->ping( $key ); // push to top
+ } elseif ( count( $this->cache ) >= $this->maxCacheKeys ) {
+ reset( $this->cache );
+ $evictKey = key( $this->cache );
+ unset( $this->cache[$evictKey] );
+ unset( $this->cacheTimes[$evictKey] );
+ }
+ $this->cache[$key][$prop] = $value;
+ $this->cacheTimes[$key][$prop] = time();
+ }
+
+ /**
+ * Check if a property field exists for a cache entry.
+ *
+ * @param $key string
+ * @param $prop string
+ * @param $maxAge integer Ignore items older than this many seconds (since 1.21)
+ * @return bool
+ */
+ public function has( $key, $prop, $maxAge = 0 ) {
+ if ( isset( $this->cache[$key][$prop] ) ) {
+ return ( $maxAge <= 0 || ( time() - $this->cacheTimes[$key][$prop] ) <= $maxAge );
+ }
+
+ return false;
+ }
+
+ /**
+ * Get a property field for a cache entry.
+ * This returns null if the property is not set.
+ * If the item is already set, it will be pushed to the top of the cache.
+ *
+ * @param $key string
+ * @param $prop string
+ * @return mixed
+ */
+ public function get( $key, $prop ) {
+ if ( isset( $this->cache[$key][$prop] ) ) {
+ $this->ping( $key ); // push to top
+ return $this->cache[$key][$prop];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Clear one or several cache entries, or all cache entries
+ *
+ * @param $keys string|Array
+ * @return void
+ */
+ public function clear( $keys = null ) {
+ if ( $keys === null ) {
+ $this->cache = array();
+ $this->cacheTimes = array();
+ } else {
+ foreach ( (array)$keys as $key ) {
+ unset( $this->cache[$key] );
+ unset( $this->cacheTimes[$key] );
+ }
+ }
+ }
+
+ /**
+ * Push an entry to the top of the cache
+ *
+ * @param $key string
+ */
+ protected function ping( $key ) {
+ $item = $this->cache[$key];
+ unset( $this->cache[$key] );
+ $this->cache[$key] = $item;
+ }
+}
+++ /dev/null
-<?php
-
-/**
- * Test for ProcessCacheLRU class.
- *
- * Note that it uses the ProcessCacheLRUTestable class which extends some
- * properties and methods visibility. That class is defined at the end of the
- * file containing this class.
- *
- * @group Cache
- */
-class ProcessCacheLRUTest extends MediaWikiTestCase {
-
- /**
- * Helper to verify emptiness of a cache object.
- * Compare against an array so we get the cache content difference.
- */
- function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) {
- $this->assertAttributeEquals( array(), 'cache', $cache, $msg );
- }
-
- /**
- * Helper to fill a cache object passed by reference
- */
- function fillCache( &$cache, $numEntries ) {
- // Fill cache with three values
- for ( $i = 1; $i <= $numEntries; $i++ ) {
- $cache->set( "cache-key-$i", "prop-$i", "value-$i" );
- }
- }
-
- /**
- * Generates an array of what would be expected in cache for a given cache
- * size and a number of entries filled in sequentially
- */
- function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
- $expected = array();
-
- if ( $entryToFill === 0 ) {
- # The cache is empty!
- return array();
- } elseif ( $entryToFill <= $cacheMaxEntries ) {
- # Cache is not fully filled
- $firstKey = 1;
- } else {
- # Cache overflowed
- $firstKey = 1 + $entryToFill - $cacheMaxEntries;
- }
-
- $lastKey = $entryToFill;
-
- for ( $i = $firstKey; $i <= $lastKey; $i++ ) {
- $expected["cache-key-$i"] = array( "prop-$i" => "value-$i" );
- }
-
- return $expected;
- }
-
- /**
- * Highlight diff between assertEquals and assertNotSame
- */
- public function testPhpUnitArrayEquality() {
- $one = array( 'A' => 1, 'B' => 2 );
- $two = array( 'B' => 2, 'A' => 1 );
- $this->assertEquals( $one, $two ); // ==
- $this->assertNotSame( $one, $two ); // ===
- }
-
- /**
- * @dataProvider provideInvalidConstructorArg
- * @expectedException MWException
- */
- public function testConstructorGivenInvalidValue( $maxSize ) {
- new ProcessCacheLRUTestable( $maxSize );
- }
-
- /**
- * Value which are forbidden by the constructor
- */
- public static function provideInvalidConstructorArg() {
- return array(
- array( null ),
- array( array() ),
- array( new stdClass() ),
- array( 0 ),
- array( '5' ),
- array( -1 ),
- );
- }
-
- public function testAddAndGetAKey() {
- $oneCache = new ProcessCacheLRUTestable( 1 );
- $this->assertCacheEmpty( $oneCache );
-
- // First set just one value
- $oneCache->set( 'cache-key', 'prop1', 'value1' );
- $this->assertEquals( 1, $oneCache->getEntriesCount() );
- $this->assertTrue( $oneCache->has( 'cache-key', 'prop1' ) );
- $this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) );
- }
-
- public function testDeleteOldKey() {
- $oneCache = new ProcessCacheLRUTestable( 1 );
- $this->assertCacheEmpty( $oneCache );
-
- $oneCache->set( 'cache-key', 'prop1', 'value1' );
- $oneCache->set( 'cache-key', 'prop1', 'value2' );
- $this->assertEquals( 'value2', $oneCache->get( 'cache-key', 'prop1' ) );
- }
-
- /**
- * This test that we properly overflow when filling a cache with
- * a sequence of always different cache-keys. Meant to verify we correclty
- * delete the older key.
- *
- * @dataProvider provideCacheFilling
- * @param $cacheMaxEntries Maximum entry the created cache will hold
- * @param $entryToFill Number of entries to insert in the created cache.
- */
- public function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) {
- $cache = new ProcessCacheLRUTestable( $cacheMaxEntries );
- $this->fillCache( $cache, $entryToFill );
-
- $this->assertSame(
- $this->getExpectedCache( $cacheMaxEntries, $entryToFill ),
- $cache->getCache(),
- "Filling a $cacheMaxEntries entries cache with $entryToFill entries"
- );
- }
-
- /**
- * Provider for testFillingCache
- */
- public static function provideCacheFilling() {
- // ($cacheMaxEntries, $entryToFill, $msg='')
- return array(
- array( 1, 0 ),
- array( 1, 1 ),
- array( 1, 2 ), # overflow
- array( 5, 33 ), # overflow
- );
- }
-
- /**
- * Create a cache with only one remaining entry then update
- * the first inserted entry. Should bump it to the top.
- */
- public function testReplaceExistingKeyShouldBumpEntryToTop() {
- $maxEntries = 3;
-
- $cache = new ProcessCacheLRUTestable( $maxEntries );
- // Fill cache leaving just one remaining slot
- $this->fillCache( $cache, $maxEntries - 1 );
-
- // Set an existing cache key
- $cache->set( "cache-key-1", "prop-1", "new-value-for-1" );
-
- $this->assertSame(
- array(
- 'cache-key-2' => array( 'prop-2' => 'value-2' ),
- 'cache-key-1' => array( 'prop-1' => 'new-value-for-1' ),
- ),
- $cache->getCache()
- );
- }
-
- public function testRecentlyAccessedKeyStickIn() {
- $cache = new ProcessCacheLRUTestable( 2 );
- $cache->set( 'first', 'prop1', 'value1' );
- $cache->set( 'second', 'prop2', 'value2' );
-
- // Get first
- $cache->get( 'first', 'prop1' );
- // Cache a third value, should invalidate the least used one
- $cache->set( 'third', 'prop3', 'value3' );
-
- $this->assertFalse( $cache->has( 'second', 'prop2' ) );
- }
-
- /**
- * This first create a full cache then update the value for the 2nd
- * filled entry.
- * Given a cache having 1,2,3 as key, updating 2 should bump 2 to
- * the top of the queue with the new value: 1,3,2* (* = updated).
- */
- public function testReplaceExistingKeyInAFullCacheShouldBumpToTop() {
- $maxEntries = 3;
-
- $cache = new ProcessCacheLRUTestable( $maxEntries );
- $this->fillCache( $cache, $maxEntries );
-
- // Set an existing cache key
- $cache->set( "cache-key-2", "prop-2", "new-value-for-2" );
- $this->assertSame(
- array(
- 'cache-key-1' => array( 'prop-1' => 'value-1' ),
- 'cache-key-3' => array( 'prop-3' => 'value-3' ),
- 'cache-key-2' => array( 'prop-2' => 'new-value-for-2' ),
- ),
- $cache->getCache()
- );
- $this->assertEquals( 'new-value-for-2',
- $cache->get( 'cache-key-2', 'prop-2' )
- );
- }
-
- public function testBumpExistingKeyToTop() {
- $cache = new ProcessCacheLRUTestable( 3 );
- $this->fillCache( $cache, 3 );
-
- // Set the very first cache key to a new value
- $cache->set( "cache-key-1", "prop-1", "new value for 1" );
- $this->assertEquals(
- array(
- 'cache-key-2' => array( 'prop-2' => 'value-2' ),
- 'cache-key-3' => array( 'prop-3' => 'value-3' ),
- 'cache-key-1' => array( 'prop-1' => 'new value for 1' ),
- ),
- $cache->getCache()
- );
- }
-}
-
-/**
- * Overrides some ProcessCacheLRU methods and properties accessibility.
- */
-class ProcessCacheLRUTestable extends ProcessCacheLRU {
- public $cache = array();
-
- public function getCache() {
- return $this->cache;
- }
-
- public function getEntriesCount() {
- return count( $this->cache );
- }
-}
--- /dev/null
+<?php
+
+/**
+ * Test for ProcessCacheLRU class.
+ *
+ * Note that it uses the ProcessCacheLRUTestable class which extends some
+ * properties and methods visibility. That class is defined at the end of the
+ * file containing this class.
+ *
+ * @group Cache
+ */
+class ProcessCacheLRUTest extends MediaWikiTestCase {
+
+ /**
+ * Helper to verify emptiness of a cache object.
+ * Compare against an array so we get the cache content difference.
+ */
+ function assertCacheEmpty( $cache, $msg = 'Cache should be empty' ) {
+ $this->assertAttributeEquals( array(), 'cache', $cache, $msg );
+ }
+
+ /**
+ * Helper to fill a cache object passed by reference
+ */
+ function fillCache( &$cache, $numEntries ) {
+ // Fill cache with three values
+ for ( $i = 1; $i <= $numEntries; $i++ ) {
+ $cache->set( "cache-key-$i", "prop-$i", "value-$i" );
+ }
+ }
+
+ /**
+ * Generates an array of what would be expected in cache for a given cache
+ * size and a number of entries filled in sequentially
+ */
+ function getExpectedCache( $cacheMaxEntries, $entryToFill ) {
+ $expected = array();
+
+ if ( $entryToFill === 0 ) {
+ # The cache is empty!
+ return array();
+ } elseif ( $entryToFill <= $cacheMaxEntries ) {
+ # Cache is not fully filled
+ $firstKey = 1;
+ } else {
+ # Cache overflowed
+ $firstKey = 1 + $entryToFill - $cacheMaxEntries;
+ }
+
+ $lastKey = $entryToFill;
+
+ for ( $i = $firstKey; $i <= $lastKey; $i++ ) {
+ $expected["cache-key-$i"] = array( "prop-$i" => "value-$i" );
+ }
+
+ return $expected;
+ }
+
+ /**
+ * Highlight diff between assertEquals and assertNotSame
+ */
+ public function testPhpUnitArrayEquality() {
+ $one = array( 'A' => 1, 'B' => 2 );
+ $two = array( 'B' => 2, 'A' => 1 );
+ $this->assertEquals( $one, $two ); // ==
+ $this->assertNotSame( $one, $two ); // ===
+ }
+
+ /**
+ * @dataProvider provideInvalidConstructorArg
+ * @expectedException UnexpectedValueException
+ */
+ public function testConstructorGivenInvalidValue( $maxSize ) {
+ new ProcessCacheLRUTestable( $maxSize );
+ }
+
+ /**
+ * Value which are forbidden by the constructor
+ */
+ public static function provideInvalidConstructorArg() {
+ return array(
+ array( null ),
+ array( array() ),
+ array( new stdClass() ),
+ array( 0 ),
+ array( '5' ),
+ array( -1 ),
+ );
+ }
+
+ public function testAddAndGetAKey() {
+ $oneCache = new ProcessCacheLRUTestable( 1 );
+ $this->assertCacheEmpty( $oneCache );
+
+ // First set just one value
+ $oneCache->set( 'cache-key', 'prop1', 'value1' );
+ $this->assertEquals( 1, $oneCache->getEntriesCount() );
+ $this->assertTrue( $oneCache->has( 'cache-key', 'prop1' ) );
+ $this->assertEquals( 'value1', $oneCache->get( 'cache-key', 'prop1' ) );
+ }
+
+ public function testDeleteOldKey() {
+ $oneCache = new ProcessCacheLRUTestable( 1 );
+ $this->assertCacheEmpty( $oneCache );
+
+ $oneCache->set( 'cache-key', 'prop1', 'value1' );
+ $oneCache->set( 'cache-key', 'prop1', 'value2' );
+ $this->assertEquals( 'value2', $oneCache->get( 'cache-key', 'prop1' ) );
+ }
+
+ /**
+ * This test that we properly overflow when filling a cache with
+ * a sequence of always different cache-keys. Meant to verify we correclty
+ * delete the older key.
+ *
+ * @dataProvider provideCacheFilling
+ * @param $cacheMaxEntries Maximum entry the created cache will hold
+ * @param $entryToFill Number of entries to insert in the created cache.
+ */
+ public function testFillingCache( $cacheMaxEntries, $entryToFill, $msg = '' ) {
+ $cache = new ProcessCacheLRUTestable( $cacheMaxEntries );
+ $this->fillCache( $cache, $entryToFill );
+
+ $this->assertSame(
+ $this->getExpectedCache( $cacheMaxEntries, $entryToFill ),
+ $cache->getCache(),
+ "Filling a $cacheMaxEntries entries cache with $entryToFill entries"
+ );
+ }
+
+ /**
+ * Provider for testFillingCache
+ */
+ public static function provideCacheFilling() {
+ // ($cacheMaxEntries, $entryToFill, $msg='')
+ return array(
+ array( 1, 0 ),
+ array( 1, 1 ),
+ array( 1, 2 ), # overflow
+ array( 5, 33 ), # overflow
+ );
+ }
+
+ /**
+ * Create a cache with only one remaining entry then update
+ * the first inserted entry. Should bump it to the top.
+ */
+ public function testReplaceExistingKeyShouldBumpEntryToTop() {
+ $maxEntries = 3;
+
+ $cache = new ProcessCacheLRUTestable( $maxEntries );
+ // Fill cache leaving just one remaining slot
+ $this->fillCache( $cache, $maxEntries - 1 );
+
+ // Set an existing cache key
+ $cache->set( "cache-key-1", "prop-1", "new-value-for-1" );
+
+ $this->assertSame(
+ array(
+ 'cache-key-2' => array( 'prop-2' => 'value-2' ),
+ 'cache-key-1' => array( 'prop-1' => 'new-value-for-1' ),
+ ),
+ $cache->getCache()
+ );
+ }
+
+ public function testRecentlyAccessedKeyStickIn() {
+ $cache = new ProcessCacheLRUTestable( 2 );
+ $cache->set( 'first', 'prop1', 'value1' );
+ $cache->set( 'second', 'prop2', 'value2' );
+
+ // Get first
+ $cache->get( 'first', 'prop1' );
+ // Cache a third value, should invalidate the least used one
+ $cache->set( 'third', 'prop3', 'value3' );
+
+ $this->assertFalse( $cache->has( 'second', 'prop2' ) );
+ }
+
+ /**
+ * This first create a full cache then update the value for the 2nd
+ * filled entry.
+ * Given a cache having 1,2,3 as key, updating 2 should bump 2 to
+ * the top of the queue with the new value: 1,3,2* (* = updated).
+ */
+ public function testReplaceExistingKeyInAFullCacheShouldBumpToTop() {
+ $maxEntries = 3;
+
+ $cache = new ProcessCacheLRUTestable( $maxEntries );
+ $this->fillCache( $cache, $maxEntries );
+
+ // Set an existing cache key
+ $cache->set( "cache-key-2", "prop-2", "new-value-for-2" );
+ $this->assertSame(
+ array(
+ 'cache-key-1' => array( 'prop-1' => 'value-1' ),
+ 'cache-key-3' => array( 'prop-3' => 'value-3' ),
+ 'cache-key-2' => array( 'prop-2' => 'new-value-for-2' ),
+ ),
+ $cache->getCache()
+ );
+ $this->assertEquals( 'new-value-for-2',
+ $cache->get( 'cache-key-2', 'prop-2' )
+ );
+ }
+
+ public function testBumpExistingKeyToTop() {
+ $cache = new ProcessCacheLRUTestable( 3 );
+ $this->fillCache( $cache, 3 );
+
+ // Set the very first cache key to a new value
+ $cache->set( "cache-key-1", "prop-1", "new value for 1" );
+ $this->assertEquals(
+ array(
+ 'cache-key-2' => array( 'prop-2' => 'value-2' ),
+ 'cache-key-3' => array( 'prop-3' => 'value-3' ),
+ 'cache-key-1' => array( 'prop-1' => 'new value for 1' ),
+ ),
+ $cache->getCache()
+ );
+ }
+}
+
+/**
+ * Overrides some ProcessCacheLRU methods and properties accessibility.
+ */
+class ProcessCacheLRUTestable extends ProcessCacheLRU {
+ public $cache = array();
+
+ public function getCache() {
+ return $this->cache;
+ }
+
+ public function getEntriesCount() {
+ return count( $this->cache );
+ }
+}