Changeset 6539
- Timestamp:
- 01/02/2008 10:13:16 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/wp-includes/cache.php
r6247 r6539 2 2 function wp_cache_add($key, $data, $flag = '', $expire = 0) { 3 3 global $wp_object_cache; 4 $data = unserialize(serialize($data));5 4 6 5 return $wp_object_cache->add($key, $data, $flag, $expire); … … 39 38 function wp_cache_replace($key, $data, $flag = '', $expire = 0) { 40 39 global $wp_object_cache; 41 $data = unserialize(serialize($data));42 40 43 41 return $wp_object_cache->replace($key, $data, $flag, $expire); … … 46 44 function wp_cache_set($key, $data, $flag = '', $expire = 0) { 47 45 global $wp_object_cache; 48 $data = unserialize(serialize($data));49 46 50 47 return $wp_object_cache->set($key, $data, $flag, $expire); 51 48 } 52 49 53 define('CACHE_SERIAL_HEADER', "<?php\n/*");54 define('CACHE_SERIAL_FOOTER', "*/\n?".">");55 56 50 class WP_Object_Cache { 57 var $cache_dir;58 var $cache_enabled = false;59 var $expiration_time = 900;60 var $flock_filename = 'wp_object_cache.lock';61 var $mutex;62 51 var $cache = array (); 63 var $dirty_objects = array ();64 52 var $non_existant_objects = array (); 65 53 var $global_groups = array ('users', 'userlogins', 'usermeta'); 66 var $non_persistent_groups = array('comment'); 67 var $blog_id; 68 var $cold_cache_hits = 0; 69 var $warm_cache_hits = 0; 54 var $cache_hits = 0; 70 55 var $cache_misses = 0; 71 var $secret = '';72 73 function acquire_lock() {74 // Acquire a write lock.75 $this->mutex = @fopen($this->cache_dir.$this->flock_filename, 'w');76 if ( false == $this->mutex)77 return false;78 flock($this->mutex, LOCK_EX);79 return true;80 }81 56 82 57 function add($id, $data, $group = 'default', $expire = '') { … … 99 74 unset ($this->cache[$group][$id]); 100 75 $this->non_existant_objects[$group][$id] = true; 101 $this->dirty_objects[$group][] = $id;102 76 return true; 103 77 } 104 78 105 79 function flush() { 106 if ( !$this->cache_enabled )107 return true;108 109 if ( ! $this->acquire_lock() )110 return false;111 112 $this->rm_cache_dir();113 80 $this->cache = array (); 114 $this->dirty_objects = array ();115 $this->non_existant_objects = array ();116 117 $this->release_lock();118 81 119 82 return true; 120 83 } 121 84 122 function get($id, $group = 'default' , $count_hits = true) {85 function get($id, $group = 'default') { 123 86 if (empty ($group)) 124 87 $group = 'default'; 125 88 126 89 if (isset ($this->cache[$group][$id])) { 127 if ($count_hits) 128 $this->warm_cache_hits += 1; 90 $this->cache_hits += 1; 129 91 return $this->cache[$group][$id]; 130 92 } 131 93 132 if ( isset ($this->non_existant_objects[$group][$id]))94 if ( isset ($this->non_existant_objects[$group][$id]) ) 133 95 return false; 134 96 135 // If caching is not enabled, we have to fall back to pulling from the DB. 136 if (!$this->cache_enabled) { 137 if (!isset ($this->cache[$group])) 138 $this->load_group_from_db($group); 139 140 if (isset ($this->cache[$group][$id])) { 141 $this->cold_cache_hits += 1; 142 return $this->cache[$group][$id]; 143 } 144 145 $this->non_existant_objects[$group][$id] = true; 146 $this->cache_misses += 1; 147 return false; 148 } 149 150 $cache_file = $this->cache_dir.$this->get_group_dir($group)."/".$this->hash($id).'.php'; 151 if (!file_exists($cache_file)) { 152 $this->non_existant_objects[$group][$id] = true; 153 $this->cache_misses += 1; 154 return false; 155 } 156 157 // If the object has expired, remove it from the cache and return false to force 158 // a refresh. 159 $now = time(); 160 if ((filemtime($cache_file) + $this->expiration_time) <= $now) { 161 $this->cache_misses += 1; 162 $this->delete($id, $group, true); 163 return false; 164 } 165 166 $this->cache[$group][$id] = unserialize(base64_decode(substr(@ file_get_contents($cache_file), strlen(CACHE_SERIAL_HEADER), -strlen(CACHE_SERIAL_FOOTER)))); 167 if (false === $this->cache[$group][$id]) 168 $this->cache[$group][$id] = ''; 169 170 $this->cold_cache_hits += 1; 171 return $this->cache[$group][$id]; 172 } 173 174 function get_group_dir($group) { 175 if (false !== array_search($group, $this->global_groups)) 176 return $group; 177 178 return "{$this->blog_id}/$group"; 179 } 180 181 function hash($data) { 182 if ( function_exists('hash_hmac') ) { 183 return hash_hmac('md5', $data, $this->secret); 184 } else { 185 return md5($data . $this->secret); 186 } 187 } 188 189 function load_group_from_db($group) { 190 return; 191 } 192 193 function make_group_dir($group, $perms) { 194 $group_dir = $this->get_group_dir($group); 195 $make_dir = ''; 196 foreach (split('/', $group_dir) as $subdir) { 197 $make_dir .= "$subdir/"; 198 if (!file_exists($this->cache_dir.$make_dir)) { 199 if (! @ mkdir($this->cache_dir.$make_dir)) 200 break; 201 @ chmod($this->cache_dir.$make_dir, $perms); 202 } 203 204 if (!file_exists($this->cache_dir.$make_dir."index.php")) { 205 $file_perms = $perms & 0000666; 206 @ touch($this->cache_dir.$make_dir."index.php"); 207 @ chmod($this->cache_dir.$make_dir."index.php", $file_perms); 208 } 209 } 210 211 return $this->cache_dir."$group_dir/"; 212 } 213 214 function rm_cache_dir() { 215 $dir = $this->cache_dir; 216 $dir = rtrim($dir, DIRECTORY_SEPARATOR); 217 $top_dir = $dir; 218 $stack = array($dir); 219 $index = 0; 220 221 while ($index < count($stack)) { 222 # Get indexed directory from stack 223 $dir = $stack[$index]; 224 225 $dh = @ opendir($dir); 226 if (!$dh) 227 return false; 228 229 while (($file = @ readdir($dh)) !== false) { 230 if ($file == '.' or $file == '..') 231 continue; 232 233 if (@ is_dir($dir . DIRECTORY_SEPARATOR . $file)) 234 $stack[] = $dir . DIRECTORY_SEPARATOR . $file; 235 else if (@ is_file($dir . DIRECTORY_SEPARATOR . $file)) 236 @ unlink($dir . DIRECTORY_SEPARATOR . $file); 237 } 238 239 $index++; 240 } 241 242 $stack = array_reverse($stack); // Last added dirs are deepest 243 foreach($stack as $dir) { 244 if ( $dir != $top_dir) 245 @ rmdir($dir); 246 } 247 248 } 249 250 function release_lock() { 251 // Release write lock. 252 flock($this->mutex, LOCK_UN); 253 fclose($this->mutex); 97 $this->non_existant_objects[$group][$id] = true; 98 $this->cache_misses += 1; 99 return false; 254 100 } 255 101 … … 273 119 $this->cache[$group][$id] = $data; 274 120 unset ($this->non_existant_objects[$group][$id]); 275 $this->dirty_objects[$group][] = $id;276 277 return true;278 }279 280 function save() {281 //$this->stats();282 283 if (!$this->cache_enabled)284 return true;285 286 if (empty ($this->dirty_objects))287 return true;288 289 // Give the new dirs the same perms as wp-content.290 $stat = stat(ABSPATH.'wp-content');291 $dir_perms = $stat['mode'] & 0007777; // Get the permission bits.292 $file_perms = $dir_perms & 0000666; // Remove execute bits for files.293 294 // Make the base cache dir.295 if (!file_exists($this->cache_dir)) {296 if (! @ mkdir($this->cache_dir))297 return false;298 @ chmod($this->cache_dir, $dir_perms);299 }300 301 if (!file_exists($this->cache_dir."index.php")) {302 @ touch($this->cache_dir."index.php");303 @ chmod($this->cache_dir."index.php", $file_perms);304 }305 306 if ( ! $this->acquire_lock() )307 return false;308 309 // Loop over dirty objects and save them.310 $errors = 0;311 foreach ($this->dirty_objects as $group => $ids) {312 if ( in_array($group, $this->non_persistent_groups) )313 continue;314 315 $group_dir = $this->make_group_dir($group, $dir_perms);316 317 $ids = array_unique($ids);318 foreach ($ids as $id) {319 $cache_file = $group_dir.$this->hash($id).'.php';320 321 // Remove the cache file if the key is not set.322 if (!isset ($this->cache[$group][$id])) {323 if (file_exists($cache_file))324 @ unlink($cache_file);325 continue;326 }327 328 $temp_file = tempnam($group_dir, 'tmp');329 $serial = CACHE_SERIAL_HEADER.base64_encode(serialize($this->cache[$group][$id])).CACHE_SERIAL_FOOTER;330 $fd = @fopen($temp_file, 'w');331 if ( false === $fd ) {332 $errors++;333 continue;334 }335 fputs($fd, $serial);336 fclose($fd);337 if (!@ rename($temp_file, $cache_file)) {338 if (!@ copy($temp_file, $cache_file))339 $errors++;340 @ unlink($temp_file);341 }342 @ chmod($cache_file, $file_perms);343 }344 }345 346 $this->dirty_objects = array();347 348 $this->release_lock();349 350 if ( $errors )351 return false;352 121 353 122 return true; … … 356 125 function stats() { 357 126 echo "<p>"; 358 echo "<strong>Cold Cache Hits:</strong> {$this->cold_cache_hits}<br />"; 359 echo "<strong>Warm Cache Hits:</strong> {$this->warm_cache_hits}<br />"; 127 echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />"; 360 128 echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />"; 361 129 echo "</p>"; … … 368 136 print_r($cache); 369 137 echo "</pre>"; 370 if (isset ($this->dirty_objects[$group])) {371 echo "<strong>Dirty Objects:</strong>";372 echo "<pre>";373 print_r(array_unique($this->dirty_objects[$group]));374 echo "</pre>";375 echo "</p>";376 }377 138 } 378 139 } … … 383 144 384 145 function __construct() { 385 global $blog_id;386 387 146 register_shutdown_function(array(&$this, "__destruct")); 388 389 if (defined('DISABLE_CACHE'))390 return;391 392 if ( ! defined('ENABLE_CACHE') )393 return;394 395 // Disable the persistent cache if safe_mode is on.396 if ( ini_get('safe_mode') && ! defined('ENABLE_CACHE') )397 return;398 399 if (defined('CACHE_PATH'))400 $this->cache_dir = CACHE_PATH;401 else402 // Using the correct separator eliminates some cache flush errors on Windows403 $this->cache_dir = ABSPATH.'wp-content'.DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR;404 405 if (is_writable($this->cache_dir) && is_dir($this->cache_dir)) {406 $this->cache_enabled = true;407 } else {408 if (is_writable(ABSPATH.'wp-content')) {409 $this->cache_enabled = true;410 }411 }412 413 if (defined('CACHE_EXPIRATION_TIME'))414 $this->expiration_time = CACHE_EXPIRATION_TIME;415 416 if ( defined('WP_SECRET') )417 $this->secret = WP_SECRET;418 else419 $this->secret = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH;420 421 $this->blog_id = $this->hash($blog_id);422 147 } 423 148 424 149 function __destruct() { 425 $this->save();426 150 return true; 427 151 }
Note: See TracChangeset
for help on using the changeset viewer.