1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20:
21: class NMemcachedStorage extends NObject implements ICacheStorage
22: {
23:
24: const META_CALLBACKS = 'callbacks',
25: META_DATA = 'data',
26: META_DELTA = 'delta';
27:
28:
29: private $memcache;
30:
31:
32: private $prefix;
33:
34:
35: private $journal;
36:
37:
38:
39: 40: 41: 42:
43: public static function isAvailable()
44: {
45: return extension_loaded('memcache');
46: }
47:
48:
49:
50: public function __construct($host = 'localhost', $port = 11211, $prefix = '', ICacheJournal $journal = NULL)
51: {
52: if (!self::isAvailable()) {
53: throw new NotSupportedException("PHP extension 'memcache' is not loaded.");
54: }
55:
56: $this->prefix = $prefix;
57: $this->journal = $journal;
58: $this->memcache = new Memcache;
59: if ($host) {
60: $this->addServer($host, $port);
61: }
62: }
63:
64:
65:
66: public function addServer($host = 'localhost', $port = 11211, $timeout = 1)
67: {
68: if ($this->memcache->addServer($host, $port, TRUE, 1, $timeout) === FALSE) {
69: $error = error_get_last();
70: throw new InvalidStateException("Memcache::addServer(): $error[message].");
71: }
72: }
73:
74:
75:
76: 77: 78:
79: public function getConnection()
80: {
81: return $this->memcache;
82: }
83:
84:
85:
86: 87: 88: 89: 90:
91: public function read($key)
92: {
93: $key = $this->prefix . $key;
94: $meta = $this->memcache->get($key);
95: if (!$meta) {
96: return NULL;
97: }
98:
99:
100:
101:
102:
103:
104:
105:
106:
107: if (!empty($meta[self::META_CALLBACKS]) && !NCache::checkCallbacks($meta[self::META_CALLBACKS])) {
108: $this->memcache->delete($key, 0);
109: return NULL;
110: }
111:
112: if (!empty($meta[self::META_DELTA])) {
113: $this->memcache->replace($key, $meta, 0, $meta[self::META_DELTA] + time());
114: }
115:
116: return $meta[self::META_DATA];
117: }
118:
119:
120:
121: 122: 123: 124: 125:
126: public function lock($key)
127: {
128: }
129:
130:
131:
132: 133: 134: 135: 136: 137: 138:
139: public function write($key, $data, array $dp)
140: {
141: if (isset($dp[NCache::ITEMS])) {
142: throw new NotSupportedException('Dependent items are not supported by MemcachedStorage.');
143: }
144:
145: $key = $this->prefix . $key;
146: $meta = array(
147: self::META_DATA => $data,
148: );
149:
150: $expire = 0;
151: if (isset($dp[NCache::EXPIRATION])) {
152: $expire = (int) $dp[NCache::EXPIRATION];
153: if (!empty($dp[NCache::SLIDING])) {
154: $meta[self::META_DELTA] = $expire;
155: }
156: }
157:
158: if (isset($dp[NCache::CALLBACKS])) {
159: $meta[self::META_CALLBACKS] = $dp[NCache::CALLBACKS];
160: }
161:
162: if (isset($dp[NCache::TAGS]) || isset($dp[NCache::PRIORITY])) {
163: if (!$this->journal) {
164: throw new InvalidStateException('CacheJournal has not been provided.');
165: }
166: $this->journal->write($key, $dp);
167: }
168:
169: $this->memcache->set($key, $meta, 0, $expire);
170: }
171:
172:
173:
174: 175: 176: 177: 178:
179: public function remove($key)
180: {
181: $this->memcache->delete($this->prefix . $key, 0);
182: }
183:
184:
185:
186: 187: 188: 189: 190:
191: public function clean(array $conds)
192: {
193: if (!empty($conds[NCache::ALL])) {
194: $this->memcache->flush();
195:
196: } elseif ($this->journal) {
197: foreach ($this->journal->clean($conds) as $entry) {
198: $this->memcache->delete($entry, 0);
199: }
200: }
201: }
202:
203: }
204: