Source for file MemcachedStorage.php

Documentation is available at MemcachedStorage.php

  1. 1: <?php
  2. 2:  
  3. 3: /**
  4. 4:  * Nette Framework
  5. 5:  *
  6. 6:  * Copyright (c) 2004, 2009 David Grudl (http://davidgrudl.com)
  7. 7:  *
  8. 8:  * This source file is subject to the "Nette license" that is bundled
  9. 9:  * with this package in the file license.txt.
  10. 10:  *
  11. 11:  * For more information please see https://nette.org
  12. 12:  *
  13. 13:  * @copyright  Copyright (c) 2004, 2009 David Grudl
  14. 14:  * @license    https://nette.org/license  Nette license
  15. 15:  * @link       https://nette.org
  16. 16:  * @category   Nette
  17. 17:  * @package    Nette\Caching
  18. 18:  * @version    $Id$
  19. 19:  */
  20. 20:  
  21. 21:  
  22. 22:  
  23. 23: require_once dirname(__FILE__'/../Object.php';
  24. 24:  
  25. 25: require_once dirname(__FILE__'/../Caching/ICacheStorage.php';
  26. 26:  
  27. 27:  
  28. 28:  
  29. 29: /**
  30. 30:  * Memcached storage.
  31. 31:  *
  32. 32:  * @author     David Grudl
  33. 33:  * @copyright  Copyright (c) 2004, 2009 David Grudl
  34. 34:  * @package    Nette\Caching
  35. 35:  */
  36. 36: class MemcachedStorage extends Object implements ICacheStorage
  37. 37: {
  38. 38:     /**#@+ internal cache structure */
  39. 39:     const META_CONSTS = 'consts';
  40. 40:     const META_DATA = 'data';
  41. 41:     const META_DELTA = 'delta';
  42. 42:     const META_FILES = 'df';
  43. 43:     /**#@-*/
  44. 44:  
  45. 45:     /** @var Memcache */
  46. 46:     protected $memcache;
  47. 47:  
  48. 48:     /** @var string */
  49. 49:     protected $prefix;
  50. 50:  
  51. 51:  
  52. 52:  
  53. 53:     /**
  54. 54:      * Checks if Memcached extension is available.
  55. 55:      * @return bool 
  56. 56:      */
  57. 57:     public static function isAvailable()
  58. 58:     {
  59. 59:         return extension_loaded('memcache');
  60. 60:     }
  61. 61:  
  62. 62:  
  63. 63:  
  64. 64:     public function __construct($host 'localhost'$port 11211$prefix '')
  65. 65:     {
  66. 66:         if (!self::isAvailable()) {
  67. 67:             throw new Exception("PHP extension 'memcache' is not loaded.");
  68. 68:         }
  69. 69:  
  70. 70:         $this->prefix = $prefix;
  71. 71:         $this->memcache = new Memcache;
  72. 72:         $this->memcache->connect($host$port);
  73. 73:     }
  74. 74:  
  75. 75:  
  76. 76:  
  77. 77:     /**
  78. 78:      * Read from cache.
  79. 79:      * @param  string key
  80. 80:      * @return mixed|NULL
  81. 81:      */
  82. 82:     public function read($key)
  83. 83:     {
  84. 84:         $key $this->prefix . $key;
  85. 85:         $meta $this->memcache->get($key);
  86. 86:         if (!$metareturn NULL;
  87. 87:  
  88. 88:         // meta structure:
  89. 89:         // array(
  90. 90:         //     data => stored data
  91. 91:         //     delta => relative (sliding) expiration
  92. 92:         //     df => array of dependent files (file => timestamp)
  93. 93:         //     consts => array of constants (const => [value])
  94. 94:         // )
  95. 95:  
  96. 96:         // verify dependencies
  97. 97:         if (!empty($meta[self::META_CONSTS])) {
  98. 98:             foreach ($meta[self::META_CONSTSas $const => $value{
  99. 99:                 if (!defined($const|| constant($const!== $value{
  100. 100:                     $this->memcache->delete($key);
  101. 101:                     return NULL;
  102. 102:                 }
  103. 103:             }
  104. 104:         }
  105. 105:  
  106. 106:         if (!empty($meta[self::META_FILES])) {
  107. 107:             //clearstatcache();
  108. 108:             foreach ($meta[self::META_FILESas $depFile => $time{
  109. 109:                 if (@filemtime($depFile<> $time{
  110. 110:                     $this->memcache->delete($key);
  111. 111:                     return NULL;
  112. 112:                 }
  113. 113:             }
  114. 114:         }
  115. 115:  
  116. 116:         if (!empty($meta[self::META_DELTA])) {
  117. 117:             $this->memcache->replace($key$meta0$meta[self::META_DELTAtime());
  118. 118:         }
  119. 119:  
  120. 120:         return $meta[self::META_DATA];
  121. 121:     }
  122. 122:  
  123. 123:  
  124. 124:  
  125. 125:     /**
  126. 126:      * Writes item into the cache.
  127. 127:      * @param  string key
  128. 128:      * @param  mixed  data
  129. 129:      * @param  array  dependencies
  130. 130:      * @return bool  TRUE if no problem
  131. 131:      */
  132. 132:     public function write($key$dataarray $dp)
  133. 133:     {
  134. 134:         if (!empty($dp[Cache::TAGS]|| isset($dp[Cache::PRIORITY]|| !empty($dp[Cache::ITEMS])) {
  135. 135:             throw new NotSupportedException('Tags, priority and dependent items are not supported by MemcachedStorage.');
  136. 136:         }
  137. 137:  
  138. 138:         $meta array(
  139. 139:             self::META_DATA => $data,
  140. 140:         );
  141. 141:  
  142. 142:         $expire 0;
  143. 143:         if (!empty($dp[Cache::EXPIRE])) {
  144. 144:             $expire = (int) $dp[Cache::EXPIRE];
  145. 145:             if ($expire <= Tools::YEAR{
  146. 146:                 $expire += time();
  147. 147:             }
  148. 148:             if (!empty($dp[Cache::REFRESH])) {
  149. 149:                 $meta[self::META_DELTA$expire time()// sliding time
  150. 150:             }
  151. 151:         }
  152. 152:  
  153. 153:         if (!empty($dp[Cache::FILES])) {
  154. 154:             //clearstatcache();
  155. 155:             foreach ((array) $dp[Cache::FILESas $depFile{
  156. 156:                 $meta[self::META_FILES][$depFile@filemtime($depFile)// intentionally @
  157. 157:             }
  158. 158:         }
  159. 159:  
  160. 160:         if (!empty($dp[Cache::CONSTS])) {
  161. 161:             foreach ((array) $dp[Cache::CONSTSas $const{
  162. 162:                 $meta[self::META_CONSTS][$constconstant($const);
  163. 163:             }
  164. 164:         }
  165. 165:  
  166. 166:         return $this->memcache->set($this->prefix $key$meta0$expire);
  167. 167:     }
  168. 168:  
  169. 169:  
  170. 170:  
  171. 171:     /**
  172. 172:      * Removes item from the cache.
  173. 173:      * @param  string key
  174. 174:      * @return bool  TRUE if no problem
  175. 175:      */
  176. 176:     public function remove($key)
  177. 177:     {
  178. 178:         return $this->memcache->delete($this->prefix $key);
  179. 179:     }
  180. 180:  
  181. 181:  
  182. 182:  
  183. 183:     /**
  184. 184:      * Removes items from the cache by conditions & garbage collector.
  185. 185:      * @param  array  conditions
  186. 186:      * @return bool  TRUE if no problem
  187. 187:      */
  188. 188:     public function clean(array $conds)
  189. 189:     {
  190. 190:         if (!empty($conds[Cache::ALL])) {
  191. 191:             $this->memcache->flush();
  192. 192:  
  193. 193:         elseif (isset($conds[Cache::TAGS]|| isset($conds[Cache::PRIORITY])) {
  194. 194:             throw new NotSupportedException('Tags and priority is not supported by MemcachedStorage.');
  195. 195:         }
  196. 196:  
  197. 197:         return TRUE;
  198. 198:     }
  199. 199: