Ticket #5570: no_persistent_cache.diff

File no_persistent_cache.diff, 9.9 kB (added by ryan, 9 months ago)
  • wp-includes/cache.php

    old new  
    11<?php 
    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); 
    76} 
     
    3837 
    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); 
    4442} 
    4543 
    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 = ''; 
    7256 
    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  
    8257        function add($id, $data, $group = 'default', $expire = '') { 
    8358                if (empty ($group)) 
    8459                        $group = 'default'; 
     
    9873 
    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 (); 
    11681 
    117                 $this->release_lock(); 
    118  
    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]; 
     97                $this->non_existant_objects[$group][$id] = true; 
     98                $this->cache_misses += 1; 
     99                return false; 
    172100        } 
    173101 
    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  
    256102        function replace($id, $data, $group = 'default', $expire = '') { 
    257103                if (empty ($group)) 
    258104                        $group = 'default'; 
     
    272118 
    273119                $this->cache[$group][$id] = $data; 
    274120                unset ($this->non_existant_objects[$group][$id]); 
    275                 $this->dirty_objects[$group][] = $id; 
    276121 
    277122                return true; 
    278123        } 
    279124 
    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  
    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>"; 
    362130 
     
    367135                        echo "<pre>"; 
    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        } 
    379140 
     
    382143        } 
    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        } 
    428152}