MDL-40677: cachestore_session: implemented support for maxsize

This commit is contained in:
Sam Hemelryk 2013-07-16 11:50:27 +12:00
parent ffc3f5308b
commit cb3590091e
2 changed files with 122 additions and 4 deletions

View File

@ -116,6 +116,18 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
*/
protected $ttl = 0;
/**
* The maximum size for the store, or false if there isn't one.
* @var bool
*/
protected $maxsize = false;
/**
* The number of items currently being stored.
* @var int
*/
protected $storecount = 0;
/**
* Constructs the store instance.
*
@ -192,6 +204,12 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
$this->storeid = $definition->generate_definition_hash();
$this->store = &self::register_store_id($definition->get_id());
$this->ttl = $definition->get_ttl();
$maxsize = $definition->get_maxsize();
if ($maxsize !== null) {
// Must be a positive int.
$this->maxsize = abs((int)$maxsize);
$this->storecount = count($this->store);
}
}
/**
@ -260,15 +278,21 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
* Sets an item in the cache given its key and data value.
*
* @param string $key The key to use.
* @param mixed $data The data to set.
* @param mixed $data The data to set.* @param bool $testmaxsize If set to true then we test the maxsize arg and reduce if required.
* @return bool True if the operation was a success false otherwise.
*/
public function set($key, $data) {
public function set($key, $data, $testmaxsize = true) {
if ($this->ttl == 0) {
$this->store[$key][0] = $data;
} else {
$this->store[$key] = array($data, cache::now());
}
if ($testmaxsize && $this->maxsize !== false) {
$this->storecount++;
if ($this->storecount > $this->maxsize) {
$this->reduce_for_maxsize();
}
}
return true;
}
@ -283,9 +307,15 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
public function set_many(array $keyvaluearray) {
$count = 0;
foreach ($keyvaluearray as $pair) {
$this->set($pair['key'], $pair['value']);
$this->set($pair['key'], $pair['value'], false);
$count++;
}
if ($this->maxsize !== false) {
$this->storecount += $count;
if ($this->storecount > $this->maxsize) {
$this->reduce_for_maxsize();
}
}
return $count;
}
@ -356,6 +386,9 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
public function delete($key) {
$result = isset($this->store[$key]);
unset($this->store[$key]);
if ($this->maxsize !== false) {
$this->storecount--;
}
return $result;
}
@ -373,6 +406,9 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
}
unset($this->store[$key]);
}
if ($this->maxsize !== false) {
$this->storecount -= $count;
}
return $count;
}
@ -383,9 +419,25 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
*/
public function purge() {
$this->store = array();
// Don't worry about checking if we're using max size just set it as thats as fast as the check.
$this->storecount = 0;
return true;
}
/**
* Reduces the size of the array if maxsize has been hit.
* @return int
*/
protected function reduce_for_maxsize() {
$diff = $this->storecount - $this->maxsize;
if ($diff < 1) {
return 0;
}
$this->store = array_slice($this->store, $diff, null, true);
$this->storecount -= $diff;
return $diff;
}
/**
* Returns true if the user can add an instance of the store plugin.
*
@ -406,7 +458,7 @@ class cachestore_session extends session_data_store implements cache_is_key_awar
* Generates an instance of the cache store that can be used for testing.
*
* @param cache_definition $definition
* @return false
* @return cachestore_session
*/
public static function initialise_test_instance(cache_definition $definition) {
// Do something here perhaps.

View File

@ -44,4 +44,70 @@ class cachestore_session_test extends cachestore_tests {
protected function get_class_name() {
return 'cachestore_session';
}
/**
* Test the maxsize option.
*/
public function test_maxsize() {
$defid = 'phpunit/testmaxsize';
$config = cache_config_phpunittest::instance();
$config->phpunit_add_definition($defid, array(
'mode' => cache_store::MODE_SESSION,
'component' => 'phpunit',
'area' => 'testmaxsize',
'maxsize' => 3
));
$definition = cache_definition::load($defid, $config->get_definition_by_id($defid));
$instance = cachestore_session::initialise_test_instance($definition);
$this->assertTrue($instance->set('key1', 'value1'));
$this->assertTrue($instance->set('key2', 'value2'));
$this->assertTrue($instance->set('key3', 'value3'));
$this->assertTrue($instance->has('key1'));
$this->assertTrue($instance->has('key2'));
$this->assertTrue($instance->has('key3'));
$this->assertTrue($instance->set('key4', 'value4'));
$this->assertTrue($instance->set('key5', 'value5'));
$this->assertFalse($instance->has('key1'));
$this->assertFalse($instance->has('key2'));
$this->assertTrue($instance->has('key3'));
$this->assertTrue($instance->has('key4'));
$this->assertTrue($instance->has('key5'));
$this->assertFalse($instance->get('key1'));
$this->assertFalse($instance->get('key2'));
$this->assertEquals('value3', $instance->get('key3'));
$this->assertEquals('value4', $instance->get('key4'));
$this->assertEquals('value5', $instance->get('key5'));
// Test adding one more.
$this->assertTrue($instance->set('key6', 'value6'));
$this->assertFalse($instance->get('key3'));
// Test reducing and then adding to make sure we don't lost one.
$this->assertTrue($instance->delete('key6'));
$this->assertTrue($instance->set('key7', 'value7'));
$this->assertEquals('value4', $instance->get('key4'));
// Test adding many.
$this->assertEquals(3, $instance->set_many(array(
array('key' => 'keyA', 'value' => 'valueA'),
array('key' => 'keyB', 'value' => 'valueB'),
array('key' => 'keyC', 'value' => 'valueC')
)));
$this->assertEquals(array(
'key4' => false,
'key5' => false,
'key6' => false,
'key7' => false,
'keyA' => 'valueA',
'keyB' => 'valueB',
'keyC' => 'valueC'
), $instance->get_many(array(
'key4', 'key5', 'key6', 'key7', 'keyA', 'keyB', 'keyC'
)));
}
}