PageRenderTime 76ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/Doduo/WebKitSite/blog/wp-includes/cache.php

https://github.com/weissms/owb-mirror
PHP | 429 lines | 325 code | 91 blank | 13 comment | 67 complexity | d41fbdd711e442f9760b754ecfd60027 MD5 | raw file
  1. <?php
  2. function wp_cache_add($key, $data, $flag = '', $expire = 0) {
  3. global $wp_object_cache;
  4. $data = unserialize(serialize($data));
  5. return $wp_object_cache->add($key, $data, $flag, $expire);
  6. }
  7. function wp_cache_close() {
  8. global $wp_object_cache;
  9. if ( ! isset($wp_object_cache) )
  10. return;
  11. return $wp_object_cache->save();
  12. }
  13. function wp_cache_delete($id, $flag = '') {
  14. global $wp_object_cache;
  15. return $wp_object_cache->delete($id, $flag);
  16. }
  17. function wp_cache_flush() {
  18. global $wp_object_cache;
  19. return $wp_object_cache->flush();
  20. }
  21. function wp_cache_get($id, $flag = '') {
  22. global $wp_object_cache;
  23. return $wp_object_cache->get($id, $flag);
  24. }
  25. function wp_cache_init() {
  26. $GLOBALS['wp_object_cache'] =& new WP_Object_Cache();
  27. }
  28. function wp_cache_replace($key, $data, $flag = '', $expire = 0) {
  29. global $wp_object_cache;
  30. $data = unserialize(serialize($data));
  31. return $wp_object_cache->replace($key, $data, $flag, $expire);
  32. }
  33. function wp_cache_set($key, $data, $flag = '', $expire = 0) {
  34. global $wp_object_cache;
  35. $data = unserialize(serialize($data));
  36. return $wp_object_cache->set($key, $data, $flag, $expire);
  37. }
  38. define('CACHE_SERIAL_HEADER', "<?php\n/*");
  39. define('CACHE_SERIAL_FOOTER', "*/\n?".">");
  40. class WP_Object_Cache {
  41. var $cache_dir;
  42. var $cache_enabled = false;
  43. var $expiration_time = 900;
  44. var $flock_filename = 'wp_object_cache.lock';
  45. var $mutex;
  46. var $cache = array ();
  47. var $dirty_objects = array ();
  48. var $non_existant_objects = array ();
  49. var $global_groups = array ('users', 'userlogins', 'usermeta');
  50. var $non_persistent_groups = array('comment');
  51. var $blog_id;
  52. var $cold_cache_hits = 0;
  53. var $warm_cache_hits = 0;
  54. var $cache_misses = 0;
  55. var $secret = '';
  56. function acquire_lock() {
  57. // Acquire a write lock.
  58. $this->mutex = @fopen($this->cache_dir.$this->flock_filename, 'w');
  59. if ( false == $this->mutex)
  60. return false;
  61. flock($this->mutex, LOCK_EX);
  62. return true;
  63. }
  64. function add($id, $data, $group = 'default', $expire = '') {
  65. if (empty ($group))
  66. $group = 'default';
  67. if (false !== $this->get($id, $group, false))
  68. return false;
  69. return $this->set($id, $data, $group, $expire);
  70. }
  71. function delete($id, $group = 'default', $force = false) {
  72. if (empty ($group))
  73. $group = 'default';
  74. if (!$force && false === $this->get($id, $group, false))
  75. return false;
  76. unset ($this->cache[$group][$id]);
  77. $this->non_existant_objects[$group][$id] = true;
  78. $this->dirty_objects[$group][] = $id;
  79. return true;
  80. }
  81. function flush() {
  82. if ( !$this->cache_enabled )
  83. return true;
  84. if ( ! $this->acquire_lock() )
  85. return false;
  86. $this->rm_cache_dir();
  87. $this->cache = array ();
  88. $this->dirty_objects = array ();
  89. $this->non_existant_objects = array ();
  90. $this->release_lock();
  91. return true;
  92. }
  93. function get($id, $group = 'default', $count_hits = true) {
  94. if (empty ($group))
  95. $group = 'default';
  96. if (isset ($this->cache[$group][$id])) {
  97. if ($count_hits)
  98. $this->warm_cache_hits += 1;
  99. return $this->cache[$group][$id];
  100. }
  101. if (isset ($this->non_existant_objects[$group][$id]))
  102. return false;
  103. // If caching is not enabled, we have to fall back to pulling from the DB.
  104. if (!$this->cache_enabled) {
  105. if (!isset ($this->cache[$group]))
  106. $this->load_group_from_db($group);
  107. if (isset ($this->cache[$group][$id])) {
  108. $this->cold_cache_hits += 1;
  109. return $this->cache[$group][$id];
  110. }
  111. $this->non_existant_objects[$group][$id] = true;
  112. $this->cache_misses += 1;
  113. return false;
  114. }
  115. $cache_file = $this->cache_dir.$this->get_group_dir($group)."/".$this->hash($id).'.php';
  116. if (!file_exists($cache_file)) {
  117. $this->non_existant_objects[$group][$id] = true;
  118. $this->cache_misses += 1;
  119. return false;
  120. }
  121. // If the object has expired, remove it from the cache and return false to force
  122. // a refresh.
  123. $now = time();
  124. if ((filemtime($cache_file) + $this->expiration_time) <= $now) {
  125. $this->cache_misses += 1;
  126. $this->delete($id, $group, true);
  127. return false;
  128. }
  129. $this->cache[$group][$id] = unserialize(base64_decode(substr(@ file_get_contents($cache_file), strlen(CACHE_SERIAL_HEADER), -strlen(CACHE_SERIAL_FOOTER))));
  130. if (false === $this->cache[$group][$id])
  131. $this->cache[$group][$id] = '';
  132. $this->cold_cache_hits += 1;
  133. return $this->cache[$group][$id];
  134. }
  135. function get_group_dir($group) {
  136. if (false !== array_search($group, $this->global_groups))
  137. return $group;
  138. return "{$this->blog_id}/$group";
  139. }
  140. function hash($data) {
  141. if ( function_exists('hash_hmac') ) {
  142. return hash_hmac('md5', $data, $this->secret);
  143. } else {
  144. return md5($data . $this->secret);
  145. }
  146. }
  147. function load_group_from_db($group) {
  148. return;
  149. }
  150. function make_group_dir($group, $perms) {
  151. $group_dir = $this->get_group_dir($group);
  152. $make_dir = '';
  153. foreach (split('/', $group_dir) as $subdir) {
  154. $make_dir .= "$subdir/";
  155. if (!file_exists($this->cache_dir.$make_dir)) {
  156. if (! @ mkdir($this->cache_dir.$make_dir))
  157. break;
  158. @ chmod($this->cache_dir.$make_dir, $perms);
  159. }
  160. if (!file_exists($this->cache_dir.$make_dir."index.php")) {
  161. $file_perms = $perms & 0000666;
  162. @ touch($this->cache_dir.$make_dir."index.php");
  163. @ chmod($this->cache_dir.$make_dir."index.php", $file_perms);
  164. }
  165. }
  166. return $this->cache_dir."$group_dir/";
  167. }
  168. function rm_cache_dir() {
  169. $dir = $this->cache_dir;
  170. $dir = rtrim($dir, DIRECTORY_SEPARATOR);
  171. $top_dir = $dir;
  172. $stack = array($dir);
  173. $index = 0;
  174. while ($index < count($stack)) {
  175. # Get indexed directory from stack
  176. $dir = $stack[$index];
  177. $dh = @ opendir($dir);
  178. if (!$dh)
  179. return false;
  180. while (($file = @ readdir($dh)) !== false) {
  181. if ($file == '.' or $file == '..')
  182. continue;
  183. if (@ is_dir($dir . DIRECTORY_SEPARATOR . $file))
  184. $stack[] = $dir . DIRECTORY_SEPARATOR . $file;
  185. else if (@ is_file($dir . DIRECTORY_SEPARATOR . $file))
  186. @ unlink($dir . DIRECTORY_SEPARATOR . $file);
  187. }
  188. $index++;
  189. }
  190. $stack = array_reverse($stack); // Last added dirs are deepest
  191. foreach($stack as $dir) {
  192. if ( $dir != $top_dir)
  193. @ rmdir($dir);
  194. }
  195. }
  196. function release_lock() {
  197. // Release write lock.
  198. flock($this->mutex, LOCK_UN);
  199. fclose($this->mutex);
  200. }
  201. function replace($id, $data, $group = 'default', $expire = '') {
  202. if (empty ($group))
  203. $group = 'default';
  204. if (false === $this->get($id, $group, false))
  205. return false;
  206. return $this->set($id, $data, $group, $expire);
  207. }
  208. function set($id, $data, $group = 'default', $expire = '') {
  209. if (empty ($group))
  210. $group = 'default';
  211. if (NULL == $data)
  212. $data = '';
  213. $this->cache[$group][$id] = $data;
  214. unset ($this->non_existant_objects[$group][$id]);
  215. $this->dirty_objects[$group][] = $id;
  216. return true;
  217. }
  218. function save() {
  219. //$this->stats();
  220. if (!$this->cache_enabled)
  221. return true;
  222. if (empty ($this->dirty_objects))
  223. return true;
  224. // Give the new dirs the same perms as wp-content.
  225. $stat = stat(ABSPATH.'wp-content');
  226. $dir_perms = $stat['mode'] & 0007777; // Get the permission bits.
  227. $file_perms = $dir_perms & 0000666; // Remove execute bits for files.
  228. // Make the base cache dir.
  229. if (!file_exists($this->cache_dir)) {
  230. if (! @ mkdir($this->cache_dir))
  231. return false;
  232. @ chmod($this->cache_dir, $dir_perms);
  233. }
  234. if (!file_exists($this->cache_dir."index.php")) {
  235. @ touch($this->cache_dir."index.php");
  236. @ chmod($this->cache_dir."index.php", $file_perms);
  237. }
  238. if ( ! $this->acquire_lock() )
  239. return false;
  240. // Loop over dirty objects and save them.
  241. $errors = 0;
  242. foreach ($this->dirty_objects as $group => $ids) {
  243. if ( in_array($group, $this->non_persistent_groups) )
  244. continue;
  245. $group_dir = $this->make_group_dir($group, $dir_perms);
  246. $ids = array_unique($ids);
  247. foreach ($ids as $id) {
  248. $cache_file = $group_dir.$this->hash($id).'.php';
  249. // Remove the cache file if the key is not set.
  250. if (!isset ($this->cache[$group][$id])) {
  251. if (file_exists($cache_file))
  252. @ unlink($cache_file);
  253. continue;
  254. }
  255. $temp_file = tempnam($group_dir, 'tmp');
  256. $serial = CACHE_SERIAL_HEADER.base64_encode(serialize($this->cache[$group][$id])).CACHE_SERIAL_FOOTER;
  257. $fd = @fopen($temp_file, 'w');
  258. if ( false === $fd ) {
  259. $errors++;
  260. continue;
  261. }
  262. fputs($fd, $serial);
  263. fclose($fd);
  264. if (!@ rename($temp_file, $cache_file)) {
  265. if (!@ copy($temp_file, $cache_file))
  266. $errors++;
  267. @ unlink($temp_file);
  268. }
  269. @ chmod($cache_file, $file_perms);
  270. }
  271. }
  272. $this->dirty_objects = array();
  273. $this->release_lock();
  274. if ( $errors )
  275. return false;
  276. return true;
  277. }
  278. function stats() {
  279. echo "<p>";
  280. echo "<strong>Cold Cache Hits:</strong> {$this->cold_cache_hits}<br />";
  281. echo "<strong>Warm Cache Hits:</strong> {$this->warm_cache_hits}<br />";
  282. echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
  283. echo "</p>";
  284. foreach ($this->cache as $group => $cache) {
  285. echo "<p>";
  286. echo "<strong>Group:</strong> $group<br />";
  287. echo "<strong>Cache:</strong>";
  288. echo "<pre>";
  289. print_r($cache);
  290. echo "</pre>";
  291. if (isset ($this->dirty_objects[$group])) {
  292. echo "<strong>Dirty Objects:</strong>";
  293. echo "<pre>";
  294. print_r(array_unique($this->dirty_objects[$group]));
  295. echo "</pre>";
  296. echo "</p>";
  297. }
  298. }
  299. }
  300. function WP_Object_Cache() {
  301. return $this->__construct();
  302. }
  303. function __construct() {
  304. global $blog_id;
  305. register_shutdown_function(array(&$this, "__destruct"));
  306. if (defined('DISABLE_CACHE'))
  307. return;
  308. if ( ! defined('ENABLE_CACHE') )
  309. return;
  310. // Disable the persistent cache if safe_mode is on.
  311. if ( ini_get('safe_mode') && ! defined('ENABLE_CACHE') )
  312. return;
  313. if (defined('CACHE_PATH'))
  314. $this->cache_dir = CACHE_PATH;
  315. else
  316. // Using the correct separator eliminates some cache flush errors on Windows
  317. $this->cache_dir = ABSPATH.'wp-content'.DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR;
  318. if (is_writable($this->cache_dir) && is_dir($this->cache_dir)) {
  319. $this->cache_enabled = true;
  320. } else {
  321. if (is_writable(ABSPATH.'wp-content')) {
  322. $this->cache_enabled = true;
  323. }
  324. }
  325. if (defined('CACHE_EXPIRATION_TIME'))
  326. $this->expiration_time = CACHE_EXPIRATION_TIME;
  327. if ( defined('WP_SECRET') )
  328. $this->secret = WP_SECRET;
  329. else
  330. $this->secret = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH;
  331. $this->blog_id = $this->hash($blog_id);
  332. }
  333. function __destruct() {
  334. $this->save();
  335. return true;
  336. }
  337. }
  338. ?>