1: <?php
2: /**
3: * APC storage engine for cache.
4: *
5: * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
6: * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7: *
8: * Licensed under The MIT License
9: * For full copyright and license information, please see the LICENSE.txt
10: * Redistributions of files must retain the above copyright notice.
11: *
12: * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13: * @link http://cakephp.org CakePHP(tm) Project
14: * @package Cake.Cache.Engine
15: * @since CakePHP(tm) v 1.2.0.4933
16: * @license http://www.opensource.org/licenses/mit-license.php MIT License
17: */
18:
19: /**
20: * APC storage engine for cache
21: *
22: * @package Cake.Cache.Engine
23: */
24: class ApcEngine extends CacheEngine {
25:
26: /**
27: * Contains the compiled group names
28: * (prefixed with the global configuration prefix)
29: *
30: * @var array
31: */
32: protected $_compiledGroupNames = array();
33:
34: /**
35: * Initialize the Cache Engine
36: *
37: * Called automatically by the cache frontend
38: * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
39: *
40: * @param array $settings array of setting for the engine
41: * @return boolean True if the engine has been successfully initialized, false if not
42: * @see CacheEngine::__defaults
43: */
44: public function init($settings = array()) {
45: if (!isset($settings['prefix'])) {
46: $settings['prefix'] = Inflector::slug(APP_DIR) . '_';
47: }
48: $settings += array('engine' => 'Apc');
49: parent::init($settings);
50: return function_exists('apc_dec');
51: }
52:
53: /**
54: * Write data for key into cache
55: *
56: * @param string $key Identifier for the data
57: * @param mixed $value Data to be cached
58: * @param integer $duration How long to cache the data, in seconds
59: * @return boolean True if the data was successfully cached, false on failure
60: */
61: public function write($key, $value, $duration) {
62: $expires = 0;
63: if ($duration) {
64: $expires = time() + $duration;
65: }
66: apc_store($key . '_expires', $expires, $duration);
67: return apc_store($key, $value, $duration);
68: }
69:
70: /**
71: * Read a key from the cache
72: *
73: * @param string $key Identifier for the data
74: * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
75: */
76: public function read($key) {
77: $time = time();
78: $cachetime = intval(apc_fetch($key . '_expires'));
79: if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
80: return false;
81: }
82: return apc_fetch($key);
83: }
84:
85: /**
86: * Increments the value of an integer cached key
87: *
88: * @param string $key Identifier for the data
89: * @param integer $offset How much to increment
90: * @return New incremented value, false otherwise
91: */
92: public function increment($key, $offset = 1) {
93: return apc_inc($key, $offset);
94: }
95:
96: /**
97: * Decrements the value of an integer cached key
98: *
99: * @param string $key Identifier for the data
100: * @param integer $offset How much to subtract
101: * @return New decremented value, false otherwise
102: */
103: public function decrement($key, $offset = 1) {
104: return apc_dec($key, $offset);
105: }
106:
107: /**
108: * Delete a key from the cache
109: *
110: * @param string $key Identifier for the data
111: * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
112: */
113: public function delete($key) {
114: return apc_delete($key);
115: }
116:
117: /**
118: * Delete all keys from the cache. This will clear every cache config using APC.
119: *
120: * @param boolean $check If true, nothing will be cleared, as entries are removed
121: * from APC as they expired. This flag is really only used by FileEngine.
122: * @return boolean True Returns true.
123: */
124: public function clear($check) {
125: if ($check) {
126: return true;
127: }
128: $info = apc_cache_info('user');
129: $cacheKeys = $info['cache_list'];
130: unset($info);
131: foreach ($cacheKeys as $key) {
132: if (strpos($key['info'], $this->settings['prefix']) === 0) {
133: apc_delete($key['info']);
134: }
135: }
136: return true;
137: }
138:
139: /**
140: * Returns the `group value` for each of the configured groups
141: * If the group initial value was not found, then it initializes
142: * the group accordingly.
143: *
144: * @return array
145: */
146: public function groups() {
147: if (empty($this->_compiledGroupNames)) {
148: foreach ($this->settings['groups'] as $group) {
149: $this->_compiledGroupNames[] = $this->settings['prefix'] . $group;
150: }
151: }
152:
153: $groups = apc_fetch($this->_compiledGroupNames);
154: if (count($groups) !== count($this->settings['groups'])) {
155: foreach ($this->_compiledGroupNames as $group) {
156: if (!isset($groups[$group])) {
157: apc_store($group, 1);
158: $groups[$group] = 1;
159: }
160: }
161: ksort($groups);
162: }
163:
164: $result = array();
165: $groups = array_values($groups);
166: foreach ($this->settings['groups'] as $i => $group) {
167: $result[] = $group . $groups[$i];
168: }
169: return $result;
170: }
171:
172: /**
173: * Increments the group value to simulate deletion of all keys under a group
174: * old values will remain in storage until they expire.
175: *
176: * @return boolean success
177: */
178: public function clearGroup($group) {
179: apc_inc($this->settings['prefix'] . $group, 1, $success);
180: return $success;
181: }
182:
183: }
184: