統計
| ブランチ: | リビジョン:

pictcode_admin / lib / Cake / Cache / Engine / RedisEngine.php @ 5ad38a95

履歴 | 表示 | アノテート | ダウンロード (6.354 KB)

1
<?php
2
/**
3
 * Redis 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 2.2
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18

    
19
/**
20
 * Redis storage engine for cache.
21
 *
22
 * @package       Cake.Cache.Engine
23
 */
24
class RedisEngine extends CacheEngine {
25

    
26
/**
27
 * Redis wrapper.
28
 *
29
 * @var Redis
30
 */
31
        protected $_Redis = null;
32

    
33
/**
34
 * Settings
35
 *
36
 *  - server = string URL or ip to the Redis server host
37
 *  - database = integer database number to use for connection
38
 *  - port = integer port number to the Redis server (default: 6379)
39
 *  - timeout = float timeout in seconds (default: 0)
40
 *  - persistent = boolean Connects to the Redis server with a persistent connection (default: true)
41
 *  - unix_socket = path to the unix socket file (default: false)
42
 *
43
 * @var array
44
 */
45
        public $settings = array();
46

    
47
/**
48
 * Initialize the Cache Engine
49
 *
50
 * Called automatically by the cache frontend
51
 * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
52
 *
53
 * @param array $settings array of setting for the engine
54
 * @return bool True if the engine has been successfully initialized, false if not
55
 */
56
        public function init($settings = array()) {
57
                if (!class_exists('Redis')) {
58
                        return false;
59
                }
60
                parent::init(array_merge(array(
61
                        'engine' => 'Redis',
62
                        'prefix' => Inflector::slug(APP_DIR) . '_',
63
                        'server' => '127.0.0.1',
64
                        'database' => 0,
65
                        'port' => 6379,
66
                        'password' => false,
67
                        'timeout' => 0,
68
                        'persistent' => true,
69
                        'unix_socket' => false
70
                        ), $settings)
71
                );
72

    
73
                return $this->_connect();
74
        }
75

    
76
/**
77
 * Connects to a Redis server
78
 *
79
 * @return bool True if Redis server was connected
80
 */
81
        protected function _connect() {
82
                try {
83
                        $this->_Redis = new Redis();
84
                        if (!empty($this->settings['unix_socket'])) {
85
                                $return = $this->_Redis->connect($this->settings['unix_socket']);
86
                        } elseif (empty($this->settings['persistent'])) {
87
                                $return = $this->_Redis->connect($this->settings['server'], $this->settings['port'], $this->settings['timeout']);
88
                        } else {
89
                                $persistentId = $this->settings['port'] . $this->settings['timeout'] . $this->settings['database'];
90
                                $return = $this->_Redis->pconnect($this->settings['server'], $this->settings['port'], $this->settings['timeout'], $persistentId);
91
                        }
92
                } catch (RedisException $e) {
93
                        $return = false;
94
                }
95
                if (!$return) {
96
                        return false;
97
                }
98
                if ($this->settings['password'] && !$this->_Redis->auth($this->settings['password'])) {
99
                        return false;
100
                }
101
                return $this->_Redis->select($this->settings['database']);
102
        }
103

    
104
/**
105
 * Write data for key into cache.
106
 *
107
 * @param string $key Identifier for the data
108
 * @param mixed $value Data to be cached
109
 * @param int $duration How long to cache the data, in seconds
110
 * @return bool True if the data was successfully cached, false on failure
111
 */
112
        public function write($key, $value, $duration) {
113
                if (!is_int($value)) {
114
                        $value = serialize($value);
115
                }
116
                if ($duration === 0) {
117
                        return $this->_Redis->set($key, $value);
118
                }
119

    
120
                return $this->_Redis->setex($key, $duration, $value);
121
        }
122

    
123
/**
124
 * Read a key from the cache
125
 *
126
 * @param string $key Identifier for the data
127
 * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
128
 */
129
        public function read($key) {
130
                $value = $this->_Redis->get($key);
131
                if (ctype_digit($value)) {
132
                        $value = (int)$value;
133
                }
134
                if ($value !== false && is_string($value)) {
135
                        $value = unserialize($value);
136
                }
137
                return $value;
138
        }
139

    
140
/**
141
 * Increments the value of an integer cached key
142
 *
143
 * @param string $key Identifier for the data
144
 * @param int $offset How much to increment
145
 * @return New incremented value, false otherwise
146
 * @throws CacheException when you try to increment with compress = true
147
 */
148
        public function increment($key, $offset = 1) {
149
                return (int)$this->_Redis->incrBy($key, $offset);
150
        }
151

    
152
/**
153
 * Decrements the value of an integer cached key
154
 *
155
 * @param string $key Identifier for the data
156
 * @param int $offset How much to subtract
157
 * @return New decremented value, false otherwise
158
 * @throws CacheException when you try to decrement with compress = true
159
 */
160
        public function decrement($key, $offset = 1) {
161
                return (int)$this->_Redis->decrBy($key, $offset);
162
        }
163

    
164
/**
165
 * Delete a key from the cache
166
 *
167
 * @param string $key Identifier for the data
168
 * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
169
 */
170
        public function delete($key) {
171
                return $this->_Redis->delete($key) > 0;
172
        }
173

    
174
/**
175
 * Delete all keys from the cache
176
 *
177
 * @param bool $check Whether or not expiration keys should be checked. If
178
 *   true, no keys will be removed as cache will rely on redis TTL's.
179
 * @return bool True if the cache was successfully cleared, false otherwise
180
 */
181
        public function clear($check) {
182
                if ($check) {
183
                        return true;
184
                }
185
                $keys = $this->_Redis->getKeys($this->settings['prefix'] . '*');
186
                $this->_Redis->del($keys);
187

    
188
                return true;
189
        }
190

    
191
/**
192
 * Returns the `group value` for each of the configured groups
193
 * If the group initial value was not found, then it initializes
194
 * the group accordingly.
195
 *
196
 * @return array
197
 */
198
        public function groups() {
199
                $result = array();
200
                foreach ($this->settings['groups'] as $group) {
201
                        $value = $this->_Redis->get($this->settings['prefix'] . $group);
202
                        if (!$value) {
203
                                $value = 1;
204
                                $this->_Redis->set($this->settings['prefix'] . $group, $value);
205
                        }
206
                        $result[] = $group . $value;
207
                }
208
                return $result;
209
        }
210

    
211
/**
212
 * Increments the group value to simulate deletion of all keys under a group
213
 * old values will remain in storage until they expire.
214
 *
215
 * @param string $group The group name to clear.
216
 * @return bool success
217
 */
218
        public function clearGroup($group) {
219
                return (bool)$this->_Redis->incr($this->settings['prefix'] . $group);
220
        }
221

    
222
/**
223
 * Disconnects from the redis server
224
 */
225
        public function __destruct() {
226
                if (!$this->settings['persistent']) {
227
                        $this->_Redis->close();
228
                }
229
        }
230
}