· 8 years ago · Apr 20, 2018, 12:46 PM
1<?php
2/**
3 * Memcached.php
4 *
5 * @author Sotaro Karasawa <sotaro.k /at/ gmail.com>
6 * @package Ethna
7 * @version $Id$
8 */
9
10/**
11 * ã‚ャッシュマãƒãƒ¼ã‚¸ãƒ£ã‚¯ãƒ©ã‚¹(pecl::memcached 版)
12 *
13 * @author Sotaro Karasawa <sotaro.k /at/ gmail.com>
14 * @access public
15 * @package Ethna
16 */
17class Ethna_Plugin_Cachemanager_Memcached extends Ethna_Plugin_Cachemanager
18{
19 /**#@+ @access private */
20
21 /** @var object Memcached Memcached オブジェクト */
22 private $m = null;
23
24 /** @var array plugin configure */
25 public $config_default = array(
26 'host' => 'localhost',
27 'port' => '11211',
28 'use_pconnect' => false,
29 'retry' => 3,
30 'timeout' => 3,
31 );
32
33 protected $_get_data_cache = array();
34
35 /**#@-*/
36
37 /**
38 * _load
39 *
40 * @access protected
41 */
42 function _load()
43 {
44 parent::_load();
45
46 if ($this->config['use_pconnect']) {
47 $this->m = new Memcached($this->ctl->getAppId());
48 }
49 else {
50 $this->m = new Memcached();
51 }
52
53 if (isset($this->config['servers']) && is_array($this->config['servers'])) {
54 $this->m->addServers($this->config['servers']);
55 }
56 else {
57 $this->m->addServer($this->config['host'], $this->config['port']);
58 }
59
60 if ($this->config['use_pconnect']) {
61 }
62 }
63
64 /**
65 * ã‚ャッシュã«è¨å®šã•れãŸå€¤ã‚’å–å¾—ã™ã‚‹
66 *
67 * ã‚ャッシュã«å€¤ãŒè¨å®šã•れã¦ã„ã‚‹å ´åˆã¯ã‚ャッシュ値
68 * ãŒæˆ»ã‚Šå€¤ã¨ãªã‚‹ã€‚ã‚ャッシュã«å€¤ãŒç„¡ã„å ´åˆã‚„lifetime
69 * ã‚’éŽãŽã¦ã„ã‚‹å ´åˆã€ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸå ´åˆã¯Ethna_Error
70 * ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæˆ»ã‚Šå€¤ã¨ãªã‚‹ã€‚
71 *
72 * @access public
73 * @param string $key ã‚ャッシュã‚ー
74 * @param int $lifetime ã‚ャッシュ有効期間
75 * @param string $namespace ã‚ャッシュãƒãƒ¼ãƒ スペース
76 * @return array ã‚ャッシュ値
77 */
78 function get($key, $lifetime = null, $namespace = null)
79 {
80 $cache_key = $this->_getCacheKey($namespace, $key);
81 if ($cache_key == null) {
82 return Ethna::raiseError('invalid cache key (too long?)', E_CACHE_NO_VALUE);
83 }
84
85 $value = $this->m->get($cache_key);
86 if (!$value) {
87 return Ethna::raiseError(
88 sprintf('no such cache, key="%s", message="%s"', $key, $this->m->getResultMessage()),
89 E_CACHE_NO_VALUE
90 );
91 }
92
93 $time = $value['time'];
94 $data = $value['data'];
95
96 // ライフタイムãƒã‚§ãƒƒã‚¯
97 if ($lifetime !== null) {
98 if (($time + $lifetime) < time()) {
99 return Ethna::raiseError('lifetime expired', E_CACHE_EXPIRED);
100 }
101 }
102
103 return $data;
104 }
105
106 /**
107 * ã‚ãƒ£ãƒƒã‚·ãƒ¥ã®æœ€çµ‚更新日時をå–å¾—ã™ã‚‹
108 *
109 * @access public
110 * @param string $key cache key
111 * @param string $namespace cache namespace
112 * @return int unixtime
113 */
114 function getLastModified($key, $namespace = null)
115 {
116 $cache_key = $this->_getCacheKey($namespace, $key);
117 if ($cache_key == null) {
118 return Ethna::raiseError('invalid cache key (too long?)', E_CACHE_NO_VALUE);
119 }
120
121 $value = $this->get($cache_key);
122 if (Ethna::isError($value)) {
123 return $value;
124 }
125
126 return $value['time'];
127 }
128
129 /**
130 * 値ãŒã‚ャッシュã•れã¦ã„ã‚‹ã‹ã©ã†ã‹ã‚’å–å¾—ã™ã‚‹
131 *
132 * @access public
133 * @param string $key ã‚ャッシュã‚ー
134 * @param int $lifetime ã‚ャッシュ有効期間
135 * @param string $namespace ã‚ャッシュãƒãƒ¼ãƒ スペース
136 */
137 function isCached($key, $lifetime = null, $namespace = null)
138 {
139 $r = $this->get($key, $lifetime, $namespace);
140
141 return Ethna::isError($r) ? false: true;
142 }
143
144 /**
145 * ã‚ャッシュã«å€¤ã‚’è¨å®šã™ã‚‹
146 *
147 * @access public
148 * @param string $key ã‚ャッシュã‚ー
149 * @param mixed $value ã‚ャッシュ値
150 * @param int $timestamp ã‚ャッシュ最終更新時刻(unixtime)
151 * @param string $namespace ã‚ャッシュãƒãƒ¼ãƒ スペース
152 * @param int $lifetime expiration
153 */
154 function set($key, $value, $timestamp = null, $namespace = null, $expiration = null)
155 {
156 $cache_key = $this->_getCacheKey($namespace, $key);
157 if ($cache_key === null) {
158 return Ethna::raiseError('invalid cache key (too long?)', E_CACHE_NO_VALUE);
159 }
160
161 $time = $timestamp ? $timestamp : time();
162 $expiration = $expiration ? $expiration : 0;
163 if (!$this->m->set($cache_key, array('time' => $time, 'data' => $value), $expiration)) {
164 return Ethna::raiseError(
165 sprintf('failed to set cache, key="%s", message="%s"', $key, $this->m->getResultMessage()),
166 E_CACHE_GENERAL
167 );
168 }
169
170 return true;
171 }
172
173 /**
174 * ã‚ャッシュ値を削除ã™ã‚‹
175 *
176 * @access public
177 * @param string $key ã‚ャッシュã‚ー
178 * @param string $namespace ã‚ャッシュãƒãƒ¼ãƒ スペース
179 */
180 public function clear($key, $namespace = null)
181 {
182 $cache_key = $this->_getCacheKey($namespace, $key);
183 if ($cache_key === null) {
184 return Ethna::raiseError('invalid cache key (too long?)', E_CACHE_NO_VALUE);
185 }
186
187 if (!$this->m->delete($cache_key)) {
188 return Ethna::raiseError(
189 sprintf('failed to clear cache, key="%s", message="%s"', $key, $this->m->getResultMessage()),
190 E_CACHE_NO_VALUE
191 );
192 }
193
194 return true;
195 }
196
197 /**
198 * ã‚ャッシュデータをãƒãƒƒã‚¯ã™ã‚‹
199 *
200 * @access public
201 * @param string $key ã‚ャッシュã‚ー
202 * @param int $timeout ãƒãƒƒã‚¯ã‚¿ã‚¤ãƒ アウト
203 * @param string $namespace ã‚ャッシュãƒãƒ¼ãƒ スペース
204 * @return bool true:æˆåŠŸ false:失敗
205 */
206 function lock($key, $timeout = 5, $namespace = null)
207 {
208 // not supported
209 return true;
210 }
211
212 /**
213 * ã‚ャッシュデータã®ãƒãƒƒã‚¯ã‚’解除ã™ã‚‹
214 *
215 * @access public
216 * @param string $key ã‚ャッシュã‚ー
217 * @param string $namespace ã‚ャッシュãƒãƒ¼ãƒ スペース
218 * @return bool true:æˆåŠŸ false:失敗
219 */
220 function unlock($key, $namespace = null)
221 {
222 // not supported
223 return true;
224 }
225
226 /**
227 * ãƒãƒ¼ãƒ スペースã‹ã‚‰ã‚ャッシュã‚ーを生æˆã™ã‚‹
228 *
229 * @access private
230 */
231 private function _getCacheKey($namespace, $key)
232 {
233 $namespace = $this->getNamespace($namespace);
234
235 $key = str_replace(":", "_", $key);
236 $cache_key = $namespace . "::" . $key;
237 if (strlen($cache_key) > 250) {
238 return null;
239 }
240 return $cache_key;
241 }
242}