WordPress.org

Make WordPress Core

Changeset 6539


Ignore:
Timestamp:
01/02/2008 10:13:16 PM (10 years ago)
Author:
ryan
Message:

Remove persistent object cache. fixes #5570

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/cache.php

    r6247 r6539  
    22function wp_cache_add($key, $data, $flag = '', $expire = 0) {
    33    global $wp_object_cache;
    4     $data = unserialize(serialize($data));
    54
    65    return $wp_object_cache->add($key, $data, $flag, $expire);
     
    3938function wp_cache_replace($key, $data, $flag = '', $expire = 0) {
    4039    global $wp_object_cache;
    41     $data = unserialize(serialize($data));
    4240
    4341    return $wp_object_cache->replace($key, $data, $flag, $expire);
     
    4644function wp_cache_set($key, $data, $flag = '', $expire = 0) {
    4745    global $wp_object_cache;
    48     $data = unserialize(serialize($data));
    4946
    5047    return $wp_object_cache->set($key, $data, $flag, $expire);
    5148}
    5249
    53 define('CACHE_SERIAL_HEADER', "<?php\n/*");
    54 define('CACHE_SERIAL_FOOTER', "*/\n?".">");
    55 
    5650class 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;
    6251    var $cache = array ();
    63     var $dirty_objects = array ();
    6452    var $non_existant_objects = array ();
    6553    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;
    7055    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     }
    8156
    8257    function add($id, $data, $group = 'default', $expire = '') {
     
    9974        unset ($this->cache[$group][$id]);
    10075        $this->non_existant_objects[$group][$id] = true;
    101         $this->dirty_objects[$group][] = $id;
    10276        return true;
    10377    }
    10478
    10579    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();
    11380        $this->cache = array ();
    114         $this->dirty_objects = array ();
    115         $this->non_existant_objects = array ();
    116 
    117         $this->release_lock();
    11881
    11982        return true;
    12083    }
    12184
    122     function get($id, $group = 'default', $count_hits = true) {
     85    function get($id, $group = 'default') {
    12386        if (empty ($group))
    12487            $group = 'default';
    12588
    12689        if (isset ($this->cache[$group][$id])) {
    127             if ($count_hits)
    128                 $this->warm_cache_hits += 1;
     90            $this->cache_hits += 1;
    12991            return $this->cache[$group][$id];
    13092        }
    13193
    132         if (isset ($this->non_existant_objects[$group][$id]))
     94        if ( isset ($this->non_existant_objects[$group][$id]) )
    13395            return false;
    13496
    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;
    254100    }
    255101
     
    273119        $this->cache[$group][$id] = $data;
    274120        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;
    352121
    353122        return true;
     
    356125    function stats() {
    357126        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 />";
    360128        echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
    361129        echo "</p>";
     
    368136            print_r($cache);
    369137            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             }
    377138        }
    378139    }
     
    383144
    384145    function __construct() {
    385         global $blog_id;
    386 
    387146        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);
    422147    }
    423148
    424149    function __destruct() {
    425         $this->save();
    426150        return true;
    427151    }
Note: See TracChangeset for help on using the changeset viewer.