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