[ Index ]

WordPress Source Cross Reference

title

Body

[close]

/wp-includes/ -> cache.php (source)

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

Your comment here...

Name: Location:
Comments:


List: Classes | Functions | Variables | Constants | Tables

Generated: Sat Jul 15 11:57:04 2006 Courtesy of Taragana