PHP Cross Reference of WordPress Subversion HEAD

[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]

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      $data = unserialize(serialize($data));
   5  
   6      return $wp_object_cache->add($key, $data, $flag, $expire);
   7  }
   8  
   9  function wp_cache_close() {
  10      global $wp_object_cache;
  11  
  12      if ( ! isset($wp_object_cache) )
  13          return;
  14      return $wp_object_cache->save();
  15  }
  16  
  17  function wp_cache_delete($id, $flag = '') {
  18      global $wp_object_cache;
  19  
  20      return $wp_object_cache->delete($id, $flag);
  21  }
  22  
  23  function wp_cache_flush() {
  24      global $wp_object_cache;
  25  
  26      return $wp_object_cache->flush();
  27  }
  28  
  29  function wp_cache_get($id, $flag = '') {
  30      global $wp_object_cache;
  31  
  32      return $wp_object_cache->get($id, $flag);
  33  }
  34  
  35  function wp_cache_init() {
  36      $GLOBALS['wp_object_cache'] =& new WP_Object_Cache();
  37  }
  38  
  39  function wp_cache_replace($key, $data, $flag = '', $expire = 0) {
  40      global $wp_object_cache;
  41      $data = unserialize(serialize($data));
  42  
  43      return $wp_object_cache->replace($key, $data, $flag, $expire);
  44  }
  45  
  46  function wp_cache_set($key, $data, $flag = '', $expire = 0) {
  47      global $wp_object_cache;
  48      $data = unserialize(serialize($data));
  49  
  50      return $wp_object_cache->set($key, $data, $flag, $expire);
  51  }
  52  
  53  define('CACHE_SERIAL_HEADER', "<?php\n/*");
  54  define('CACHE_SERIAL_FOOTER', "*/\n?".">");
  55  
  56  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      var $cache = array ();
  63      var $dirty_objects = array ();
  64      var $non_existant_objects = array ();
  65      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;
  70      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  
  82  	function add($id, $data, $group = 'default', $expire = '') {
  83          if (empty ($group))
  84              $group = 'default';
  85  
  86          if (false !== $this->get($id, $group, false))
  87              return false;
  88  
  89          return $this->set($id, $data, $group, $expire);
  90      }
  91  
  92  	function delete($id, $group = 'default', $force = false) {
  93          if (empty ($group))
  94              $group = 'default';
  95  
  96          if (!$force && false === $this->get($id, $group, false))
  97              return false;
  98  
  99          unset ($this->cache[$group][$id]);
 100          $this->non_existant_objects[$group][$id] = true;
 101          $this->dirty_objects[$group][] = $id;
 102          return true;
 103      }
 104  
 105  	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          $this->cache = array ();
 114          $this->dirty_objects = array ();
 115          $this->non_existant_objects = array ();
 116  
 117          $this->release_lock();
 118  
 119          return true;
 120      }
 121  
 122  	function get($id, $group = 'default', $count_hits = true) {
 123          if (empty ($group))
 124              $group = 'default';
 125  
 126          if (isset ($this->cache[$group][$id])) {
 127              if ($count_hits)
 128                  $this->warm_cache_hits += 1;
 129              return $this->cache[$group][$id];
 130          }
 131  
 132          if (isset ($this->non_existant_objects[$group][$id]))
 133              return false;
 134  
 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);
 254      }
 255  
 256  	function replace($id, $data, $group = 'default', $expire = '') {
 257          if (empty ($group))
 258              $group = 'default';
 259  
 260          if (false === $this->get($id, $group, false))
 261              return false;
 262  
 263          return $this->set($id, $data, $group, $expire);
 264      }
 265  
 266  	function set($id, $data, $group = 'default', $expire = '') {
 267          if (empty ($group))
 268              $group = 'default';
 269  
 270          if (NULL === $data)
 271              $data = '';
 272  
 273          $this->cache[$group][$id] = $data;
 274          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  
 353          return true;
 354      }
 355  
 356  	function stats() {
 357          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 />";
 360          echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
 361          echo "</p>";
 362  
 363          foreach ($this->cache as $group => $cache) {
 364              echo "<p>";
 365              echo "<strong>Group:</strong> $group<br />";
 366              echo "<strong>Cache:</strong>";
 367              echo "<pre>";
 368              print_r($cache);
 369              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          }
 378      }
 379  
 380  	function WP_Object_Cache() {
 381          return $this->__construct();
 382      }
 383  
 384  	function __construct() {
 385          global $blog_id;
 386  
 387          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          else
 402              // Using the correct separator eliminates some cache flush errors on Windows
 403              $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          else
 419              $this->secret = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH;
 420  
 421          $this->blog_id = $this->hash($blog_id);
 422      }
 423  
 424  	function __destruct() {
 425          $this->save();
 426          return true;
 427      }
 428  }
 429  ?>


Generated Thu Dec 6 06:47:08 2007 for RedAlt XRefs Cross-referenced by PHPXref 0.6 and RedAlt