Skip to content

Commit

Permalink
Implemented group read/write support for the ApcEngine
Browse files Browse the repository at this point in the history
  • Loading branch information
lorenzo committed Mar 25, 2012
1 parent 58a59fd commit 3c9c3ef
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/Cake/Cache/Cache.php
Expand Up @@ -91,6 +91,8 @@ class Cache {
* The following keys are used in core cache engines:
*
* - `duration` Specify how long items in this cache configuration last.
* - `groups` List of groups or 'tags' associated to every key stored in this config.
* handy for deleting a complete group from cache.
* - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace
* with either another cache config or another application.
* - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable
Expand Down
33 changes: 31 additions & 2 deletions lib/Cake/Cache/CacheEngine.php
Expand Up @@ -27,6 +27,14 @@ abstract class CacheEngine {
*/
public $settings = array();

/**
* Contains the compiled string with all groups
* prefixes to be prepeded to every key in this cache engine
*
* @var string
**/
protected $groupPrefix = null;

/**
* Initialize the cache engine
*
Expand All @@ -37,10 +45,14 @@ abstract class CacheEngine {
*/
public function init($settings = array()) {
$this->settings = array_merge(
array('prefix' => 'cake_', 'duration' => 3600, 'probability' => 100),
array('prefix' => 'cake_', 'duration' => 3600, 'probability' => 100, 'groups' => array()),
$this->settings,
$settings
);
if (!empty($this->settings['groups'])) {
sort($this->settings['groups']);
$this->groupPrefix = str_repeat('%s_', count($this->settings['groups']));
}
if (!is_numeric($this->settings['duration'])) {
$this->settings['duration'] = strtotime($this->settings['duration']) - time();
}
Expand Down Expand Up @@ -108,6 +120,17 @@ abstract public function delete($key);
*/
abstract public function clear($check);

/**
* Does whatever initialization for each group is required
* and returns the `group value` for each of them, this is
* the token representing each group in the cache key
*
* @return array
**/
public function groups() {
return $this->settings['groups'];
}

/**
* Cache Engine settings
*
Expand All @@ -127,8 +150,14 @@ public function key($key) {
if (empty($key)) {
return false;
}

$prefix = '';
if (!empty($this->groupPrefix)) {
$prefix = vsprintf($this->groupPrefix, $this->groups());
}

$key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
return $key;
return $prefix . $key;
}

}
26 changes: 26 additions & 0 deletions lib/Cake/Cache/Engine/ApcEngine.php
Expand Up @@ -127,4 +127,30 @@ public function clear($check) {
return true;
}

/**
* Returns the `group value` for each of the configured groups
* If the group initial value was not found, then it initializes
* the group accordingly.
*
* @return array
**/
public function groups() {
$groups = apc_fetch($this->settings['groups']);

if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->settings['groups'] as $group) {
if (!isset($groups[$group])) {
apc_store($group, 1);
$groups[$group] = 1;
}
}
ksort($groups);
}

$result = array();
foreach ($groups as $group => $value) {
$result[] = $group . $value;
}
return $result;
}
}
24 changes: 24 additions & 0 deletions lib/Cake/Test/Case/Cache/Engine/ApcEngineTest.php
Expand Up @@ -47,6 +47,7 @@ public function setUp() {
public function tearDown() {
Configure::write('Cache.disable', $this->_cacheDisable);
Cache::drop('apc');
Cache::drop('apc_groups');
Cache::config('default');
}

Expand Down Expand Up @@ -198,4 +199,27 @@ public function testClear() {
$this->assertEquals('survive', apc_fetch('not_cake'));
apc_delete('not_cake');
}

/**
* Tests that configuring groups for stored keys return the correct values when read/written
* Shows that altering the group value is equivalent to deleting all keys under the same
* group
*
* @return void
*/
public function testGroupsReadWrite() {
Cache::config('apc_groups', array('engine' => 'Apc', 'duration' => 0, 'groups' => array('group_a', 'group_b')));
$this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'apc_groups'));

apc_inc('group_a');
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups'));
$this->assertEquals('value2', Cache::read('test_groups', 'apc_groups'));

apc_inc('group_b');
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value3', 'apc_groups'));
$this->assertEquals('value3', Cache::read('test_groups', 'apc_groups'));
}
}

0 comments on commit 3c9c3ef

Please sign in to comment.