Skip to content

Commit 3c9c3ef

Browse files
committed
Implemented group read/write support for the ApcEngine
1 parent 58a59fd commit 3c9c3ef

File tree

4 files changed

+83
-2
lines changed

4 files changed

+83
-2
lines changed

lib/Cake/Cache/Cache.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ class Cache {
9191
* The following keys are used in core cache engines:
9292
*
9393
* - `duration` Specify how long items in this cache configuration last.
94+
* - `groups` List of groups or 'tags' associated to every key stored in this config.
95+
* handy for deleting a complete group from cache.
9496
* - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace
9597
* with either another cache config or another application.
9698
* - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable

lib/Cake/Cache/CacheEngine.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ abstract class CacheEngine {
2727
*/
2828
public $settings = array();
2929

30+
/**
31+
* Contains the compiled string with all groups
32+
* prefixes to be prepeded to every key in this cache engine
33+
*
34+
* @var string
35+
**/
36+
protected $groupPrefix = null;
37+
3038
/**
3139
* Initialize the cache engine
3240
*
@@ -37,10 +45,14 @@ abstract class CacheEngine {
3745
*/
3846
public function init($settings = array()) {
3947
$this->settings = array_merge(
40-
array('prefix' => 'cake_', 'duration' => 3600, 'probability' => 100),
48+
array('prefix' => 'cake_', 'duration' => 3600, 'probability' => 100, 'groups' => array()),
4149
$this->settings,
4250
$settings
4351
);
52+
if (!empty($this->settings['groups'])) {
53+
sort($this->settings['groups']);
54+
$this->groupPrefix = str_repeat('%s_', count($this->settings['groups']));
55+
}
4456
if (!is_numeric($this->settings['duration'])) {
4557
$this->settings['duration'] = strtotime($this->settings['duration']) - time();
4658
}
@@ -108,6 +120,17 @@ abstract public function delete($key);
108120
*/
109121
abstract public function clear($check);
110122

123+
/**
124+
* Does whatever initialization for each group is required
125+
* and returns the `group value` for each of them, this is
126+
* the token representing each group in the cache key
127+
*
128+
* @return array
129+
**/
130+
public function groups() {
131+
return $this->settings['groups'];
132+
}
133+
111134
/**
112135
* Cache Engine settings
113136
*
@@ -127,8 +150,14 @@ public function key($key) {
127150
if (empty($key)) {
128151
return false;
129152
}
153+
154+
$prefix = '';
155+
if (!empty($this->groupPrefix)) {
156+
$prefix = vsprintf($this->groupPrefix, $this->groups());
157+
}
158+
130159
$key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
131-
return $key;
160+
return $prefix . $key;
132161
}
133162

134163
}

lib/Cake/Cache/Engine/ApcEngine.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,30 @@ public function clear($check) {
127127
return true;
128128
}
129129

130+
/**
131+
* Returns the `group value` for each of the configured groups
132+
* If the group initial value was not found, then it initializes
133+
* the group accordingly.
134+
*
135+
* @return array
136+
**/
137+
public function groups() {
138+
$groups = apc_fetch($this->settings['groups']);
139+
140+
if (count($groups) !== count($this->settings['groups'])) {
141+
foreach ($this->settings['groups'] as $group) {
142+
if (!isset($groups[$group])) {
143+
apc_store($group, 1);
144+
$groups[$group] = 1;
145+
}
146+
}
147+
ksort($groups);
148+
}
149+
150+
$result = array();
151+
foreach ($groups as $group => $value) {
152+
$result[] = $group . $value;
153+
}
154+
return $result;
155+
}
130156
}

lib/Cake/Test/Case/Cache/Engine/ApcEngineTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public function setUp() {
4747
public function tearDown() {
4848
Configure::write('Cache.disable', $this->_cacheDisable);
4949
Cache::drop('apc');
50+
Cache::drop('apc_groups');
5051
Cache::config('default');
5152
}
5253

@@ -198,4 +199,27 @@ public function testClear() {
198199
$this->assertEquals('survive', apc_fetch('not_cake'));
199200
apc_delete('not_cake');
200201
}
202+
203+
/**
204+
* Tests that configuring groups for stored keys return the correct values when read/written
205+
* Shows that altering the group value is equivalent to deleting all keys under the same
206+
* group
207+
*
208+
* @return void
209+
*/
210+
public function testGroupsReadWrite() {
211+
Cache::config('apc_groups', array('engine' => 'Apc', 'duration' => 0, 'groups' => array('group_a', 'group_b')));
212+
$this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups'));
213+
$this->assertEquals('value', Cache::read('test_groups', 'apc_groups'));
214+
215+
apc_inc('group_a');
216+
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
217+
$this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups'));
218+
$this->assertEquals('value2', Cache::read('test_groups', 'apc_groups'));
219+
220+
apc_inc('group_b');
221+
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
222+
$this->assertTrue(Cache::write('test_groups', 'value3', 'apc_groups'));
223+
$this->assertEquals('value3', Cache::read('test_groups', 'apc_groups'));
224+
}
201225
}

0 commit comments

Comments
 (0)