1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Caching;
13:
14: use Nette;
15:
16:
17:
18: 19: 20: 21: 22:
23: class MemcachedStorage extends Nette\Object implements ICacheStorage
24: {
25:
26: const META_CALLBACKS = 'callbacks';
27: const META_DATA = 'data';
28: const META_DELTA = 'delta';
29:
30:
31:
32: private $memcache;
33:
34:
35: private $prefix;
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 = '')
51: {
52: if (!self::isAvailable()) {
53: throw new \Exception("PHP extension 'memcache' is not loaded.");
54: }
55:
56: $this->prefix = $prefix;
57: $this->memcache = new \Memcache;
58: $this->memcache->connect($host, $port);
59: }
60:
61:
62:
63: 64: 65: 66: 67:
68: public function read($key)
69: {
70: $key = $this->prefix . $key;
71: $meta = $this->memcache->get($key);
72: if (!$meta) return NULL;
73:
74:
75:
76:
77:
78:
79:
80:
81:
82: if (!empty($meta[self::META_CALLBACKS]) && !Cache::checkCallbacks($meta[self::META_CALLBACKS])) {
83: $this->memcache->delete($key, 0);
84: return NULL;
85: }
86:
87: if (!empty($meta[self::META_DELTA])) {
88: $this->memcache->replace($key, $meta, 0, $meta[self::META_DELTA] + time());
89: }
90:
91: return $meta[self::META_DATA];
92: }
93:
94:
95:
96: 97: 98: 99: 100: 101: 102:
103: public function write($key, $data, array $dp)
104: {
105: if (!empty($dp[Cache::TAGS]) || isset($dp[Cache::PRIORITY]) || !empty($dp[Cache::ITEMS])) {
106: throw new \NotSupportedException('Tags, priority and dependent items are not supported by MemcachedStorage.');
107: }
108:
109: $meta = array(
110: self::META_DATA => $data,
111: );
112:
113: $expire = 0;
114: if (isset($dp[Cache::EXPIRATION])) {
115: $expire = (int) $dp[Cache::EXPIRATION];
116: if (!empty($dp[Cache::SLIDING])) {
117: $meta[self::META_DELTA] = $expire;
118: }
119: }
120:
121: if (isset($dp[Cache::CALLBACKS])) {
122: $meta[self::META_CALLBACKS] = $dp[Cache::CALLBACKS];
123: }
124:
125: $this->memcache->set($this->prefix . $key, $meta, 0, $expire);
126: }
127:
128:
129:
130: 131: 132: 133: 134:
135: public function remove($key)
136: {
137: $this->memcache->delete($this->prefix . $key, 0);
138: }
139:
140:
141:
142: 143: 144: 145: 146:
147: public function clean(array $conds)
148: {
149: if (!empty($conds[Cache::ALL])) {
150: $this->memcache->flush();
151:
152: } elseif (isset($conds[Cache::TAGS]) || isset($conds[Cache::PRIORITY])) {
153: throw new \NotSupportedException('Tags and priority is not supported by MemcachedStorage.');
154: }
155: }
156:
157: }
158: