| [ Index ] | PHP Cross Reference of Mambo 4.6.5 |
|
| [ Variables ] [ Functions ] [ Classes ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Fast, light and safe Cache Class 5 * 6 * Cache_Lite is a fast, light and safe cache system. It's optimized 7 * for file containers. It is fast and safe (because it uses file 8 * locking and/or anti-corruption tests). 9 * 10 * There are some examples in the 'docs/examples' file 11 * Technical choices are described in the 'docs/technical' file 12 * 13 * A tutorial is available in english at this url : 14 * http://www.pearfr.org/index.php/en/article/cache_lite 15 * (big thanks to Pierre-Alain Joye for the translation) 16 * 17 * The same tutorial is also available in french at this url : 18 * http://www.pearfr.org/index.php/fr/article/cache_lite 19 * 20 * Memory Caching is from an original idea of 21 * Mike BENOIT <ipso@snappymail.ca> 22 * 23 * @package Cache_Lite 24 * @category Caching 25 * @version $Id: Lite.php,v 1.1 2005/07/22 01:57:12 eddieajau Exp $ 26 * @author Fabien MARTY <fab@php.net> 27 */ 28 29 define('CACHE_LITE_ERROR_RETURN', 1); 30 define('CACHE_LITE_ERROR_DIE', 8); 31 32 class Cache_Lite 33 { 34 35 // --- Private properties --- 36 37 /** 38 * Directory where to put the cache files 39 * (make sure to add a trailing slash) 40 * 41 * @var string $_cacheDir 42 */ 43 var $_cacheDir = '/tmp/'; 44 45 /** 46 * Enable / disable caching 47 * 48 * (can be very usefull for the debug of cached scripts) 49 * 50 * @var boolean $_caching 51 */ 52 var $_caching = true; 53 54 /** 55 * Cache lifetime (in seconds) 56 * 57 * @var int $_lifeTime 58 */ 59 var $_lifeTime = 3600; 60 61 /** 62 * Enable / disable fileLocking 63 * 64 * (can avoid cache corruption under bad circumstances) 65 * 66 * @var boolean $_fileLocking 67 */ 68 var $_fileLocking = true; 69 70 /** 71 * Timestamp of the last valid cache 72 * 73 * @var int $_refreshTime 74 */ 75 var $_refreshTime; 76 77 /** 78 * File name (with path) 79 * 80 * @var string $_file 81 */ 82 var $_file; 83 84 /** 85 * Enable / disable write control (the cache is read just after writing to detect corrupt entries) 86 * 87 * Enable write control will lightly slow the cache writing but not the cache reading 88 * Write control can detect some corrupt cache files but maybe it's not a perfect control 89 * 90 * @var boolean $_writeControl 91 */ 92 var $_writeControl = true; 93 94 /** 95 * Enable / disable read control 96 * 97 * If enabled, a control key is embeded in cache file and this key is compared with the one 98 * calculated after the reading. 99 * 100 * @var boolean $_writeControl 101 */ 102 var $_readControl = true; 103 104 /** 105 * Type of read control (only if read control is enabled) 106 * 107 * Available values are : 108 * 'md5' for a md5 hash control (best but slowest) 109 * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice) 110 * 'strlen' for a length only test (fastest) 111 * 112 * @var boolean $_readControlType 113 */ 114 var $_readControlType = 'crc32'; 115 116 /** 117 * Pear error mode (when raiseError is called) 118 * 119 * (see PEAR doc) 120 * 121 * @see setToDebug() 122 * @var int $_pearErrorMode 123 */ 124 var $_pearErrorMode = CACHE_LITE_ERROR_RETURN; 125 126 /** 127 * Current cache id 128 * 129 * @var string $_id 130 */ 131 var $_id; 132 133 /** 134 * Current cache group 135 * 136 * @var string $_group 137 */ 138 var $_group; 139 140 /** 141 * Enable / Disable "Memory Caching" 142 * 143 * NB : There is no lifetime for memory caching ! 144 * 145 * @var boolean $_memoryCaching 146 */ 147 var $_memoryCaching = false; 148 149 /** 150 * Enable / Disable "Only Memory Caching" 151 * (be carefull, memory caching is "beta quality") 152 * 153 * @var boolean $_onlyMemoryCaching 154 */ 155 var $_onlyMemoryCaching = false; 156 157 /** 158 * Memory caching array 159 * 160 * @var array $_memoryCachingArray 161 */ 162 var $_memoryCachingArray = array(); 163 164 /** 165 * Memory caching counter 166 * 167 * @var int $memoryCachingCounter 168 */ 169 var $_memoryCachingCounter = 0; 170 171 /** 172 * Memory caching limit 173 * 174 * @var int $memoryCachingLimit 175 */ 176 var $_memoryCachingLimit = 1000; 177 178 /** 179 * File Name protection 180 * 181 * if set to true, you can use any cache id or group name 182 * if set to false, it can be faster but cache ids and group names 183 * will be used directly in cache file names so be carefull with 184 * special characters... 185 * 186 * @var boolean $fileNameProtection 187 */ 188 var $_fileNameProtection = true; 189 190 /** 191 * Enable / disable automatic serialization 192 * 193 * it can be used to save directly datas which aren't strings 194 * (but it's slower) 195 * 196 * @var boolean $_serialize 197 */ 198 var $_automaticSerialization = false; 199 200 // --- Public methods --- 201 202 /** 203 * Constructor 204 * 205 * $options is an assoc. Available options are : 206 * $options = array( 207 * 'cacheDir' => directory where to put the cache files (string), 208 * 'caching' => enable / disable caching (boolean), 209 * 'lifeTime' => cache lifetime in seconds (int), 210 * 'fileLocking' => enable / disable fileLocking (boolean), 211 * 'writeControl' => enable / disable write control (boolean), 212 * 'readControl' => enable / disable read control (boolean), 213 * 'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string), 214 * 'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int), 215 * 'memoryCaching' => enable / disable memory caching (boolean), 216 * 'onlyMemoryCaching' => enable / disable only memory caching (boolean), 217 * 'memoryCachingLimit' => max nbr of records to store into memory caching (int), 218 * 'fileNameProtection' => enable / disable automatic file name protection (boolean), 219 * 'automaticSerialization' => enable / disable automatic serialization (boolean) 220 * ); 221 * 222 * @param array $options options 223 * @access public 224 */ 225 function Cache_Lite($options = array(NULL)) 226 { 227 $availableOptions = array('automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode'); 228 foreach($options as $key => $value) { 229 if(in_array($key, $availableOptions)) { 230 $property = '_'.$key; 231 $this->$property = $value; 232 } 233 } 234 $this->_refreshTime = time() - $this->_lifeTime; 235 } 236 237 /** 238 * Test if a cache is available and (if yes) return it 239 * 240 * @param string $id cache id 241 * @param string $group name of the cache group 242 * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested 243 * @return string data of the cache (or false if no cache available) 244 * @access public 245 */ 246 function get($id, $group = 'default', $doNotTestCacheValidity = false) 247 { 248 $this->_id = $id; 249 $this->_group = $group; 250 $data = false; 251 if ($this->_caching) { 252 $this->_setFileName($id, $group); 253 if ($this->_memoryCaching) { 254 if (isset($this->_memoryCachingArray[$this->_file])) { 255 if ($this->_automaticSerialization) { 256 return unserialize($this->_memoryCachingArray[$this->_file]); 257 } else { 258 return $this->_memoryCachingArray[$this->_file]; 259 } 260 } else { 261 if ($this->_onlyMemoryCaching) { 262 return false; 263 } 264 } 265 } 266 if ($doNotTestCacheValidity) { 267 if (file_exists($this->_file)) { 268 $data = $this->_read(); 269 } 270 } else { 271 if (@filemtime($this->_file) > $this->_refreshTime) { 272 $data = $this->_read(); 273 } 274 } 275 if (($data) and ($this->_memoryCaching)) { 276 $this->_memoryCacheAdd($this->_file, $data); 277 } 278 if (($this->_automaticSerialization) and (is_string($data))) { 279 $data = unserialize($data); 280 } 281 return $data; 282 } 283 return false; 284 } 285 286 /** 287 * Save some data in a cache file 288 * 289 * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on) 290 * @param string $id cache id 291 * @param string $group name of the cache group 292 * @return boolean true if no problem 293 * @access public 294 */ 295 function save($data, $id = NULL, $group = 'default') 296 { 297 if ($this->_caching) { 298 if ($this->_automaticSerialization) { 299 $data = serialize($data); 300 } 301 if (isset($id)) { 302 $this->_setFileName($id, $group); 303 } 304 if ($this->_memoryCaching) { 305 $this->_memoryCacheAdd($this->_file, $data); 306 if ($this->_onlyMemoryCaching) { 307 return true; 308 } 309 } 310 if ($this->_writeControl) { 311 if (!$this->_writeAndControl($data)) { 312 @touch($this->_file, time() - 2*abs($this->_lifeTime)); 313 return false; 314 } else { 315 return true; 316 } 317 } else { 318 return $this->_write($data); 319 } 320 } 321 return false; 322 } 323 324 /** 325 * Remove a cache file 326 * 327 * @param string $id cache id 328 * @param string $group name of the cache group 329 * @return boolean true if no problem 330 * @access public 331 */ 332 function remove($id, $group = 'default') 333 { 334 $this->_setFileName($id, $group); 335 if (!@unlink($this->_file)) { 336 $this->raiseError('Cache_Lite : Unable to remove cache !', -3); 337 return false; 338 } 339 return true; 340 } 341 342 /** 343 * Clean the cache 344 * 345 * if no group is specified all cache files will be destroyed 346 * else only cache files of the specified group will be destroyed 347 * 348 * @param string $group name of the cache group 349 * @return boolean true if no problem 350 * @access public 351 */ 352 function clean($group = false) 353 { 354 if ($this->_fileNameProtection) { 355 $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_'; 356 } else { 357 $motif = ($group) ? 'cache_'.$group.'_' : 'cache_'; 358 } 359 if ($this->_memoryCaching) { 360 while (list($key, $value) = each($this->_memoryCaching)) { 361 if (strpos($key, $motif, 0)) { 362 unset($this->_memoryCaching[$key]); 363 $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1; 364 } 365 } 366 if ($this->_onlyMemoryCaching) { 367 return true; 368 } 369 } 370 if (!($dh = opendir($this->_cacheDir))) { 371 $this->raiseError('Cache_Lite : Unable to open cache directory !', -4); 372 return false; 373 } 374 while ($file = readdir($dh)) { 375 if (($file != '.') && ($file != '..')) { 376 $file = $this->_cacheDir . $file; 377 if (is_file($file)) { 378 if (strpos($file, $motif, 0)) { 379 if (!@unlink($file)) { 380 $this->raiseError('Cache_Lite : Unable to remove cache !', -3); 381 return false; 382 } 383 } 384 } 385 } 386 } 387 return true; 388 } 389 390 /** 391 * Set to debug mode 392 * 393 * When an error is found, the script will stop and the message will be displayed 394 * (in debug mode only). 395 * 396 * @access public 397 */ 398 function setToDebug() 399 { 400 $this->_pearErrorMode = CACHE_LITE_ERROR_DIE; 401 } 402 403 /** 404 * Set a new life time 405 * 406 * @param int $newLifeTime new life time (in seconds) 407 * @access public 408 */ 409 function setLifeTime($newLifeTime) 410 { 411 $this->_lifeTime = $newLifeTime; 412 $this->_refreshTime = time() - $newLifeTime; 413 } 414 415 /** 416 * 417 * @access public 418 */ 419 function saveMemoryCachingState($id, $group = 'default') 420 { 421 if ($this->_caching) { 422 $array = array( 423 'counter' => $this->_memoryCachingCounter, 424 'array' => $this->_memoryCachingState 425 ); 426 $data = serialize($array); 427 $this->save($data, $id, $group); 428 } 429 } 430 431 /** 432 * 433 * @access public 434 */ 435 function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false) 436 { 437 if ($this->_caching) { 438 if ($data = $this->get($id, $group, $doNotTestCacheValidity)) { 439 $array = unserialize($data); 440 $this->_memoryCachingCounter = $array['counter']; 441 $this->_memoryCachingArray = $array['array']; 442 } 443 } 444 } 445 446 /** 447 * Return the cache last modification time 448 * 449 * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY ! 450 * 451 * @return int last modification time 452 */ 453 function lastModified() { 454 return filemtime($this->_file); 455 } 456 457 /** 458 * Trigger a PEAR error 459 * 460 * To improve performances, the PEAR.php file is included dynamically. 461 * The file is so included only when an error is triggered. So, in most 462 * cases, the file isn't included and perfs are much better. 463 * 464 * @param string $msg error message 465 * @param int $code error code 466 * @access public 467 */ 468 function raiseError($msg, $code) 469 { 470 include_once('PEAR.php'); 471 PEAR::raiseError($msg, $code, $this->_pearErrorMode); 472 } 473 474 // --- Private methods --- 475 476 /** 477 * 478 * @access private 479 */ 480 function _memoryCacheAdd($id, $data) 481 { 482 $this->_memoryCachingArray[$this->_file] = $data; 483 if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) { 484 list($key, $value) = each($this->_memoryCachingArray); 485 unset($this->_memoryCachingArray[$key]); 486 } else { 487 $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1; 488 } 489 } 490 491 /** 492 * Make a file name (with path) 493 * 494 * @param string $id cache id 495 * @param string $group name of the group 496 * @access private 497 */ 498 function _setFileName($id, $group) 499 { 500 if ($this->_fileNameProtection) { 501 $this->_file = ($this->_cacheDir.'cache_'.md5($group).'_'.md5($id)); 502 } else { 503 $this->_file = $this->_cacheDir.'cache_'.$group.'_'.$id; 504 } 505 } 506 507 /** 508 * Read the cache file and return the content 509 * 510 * @return string content of the cache file 511 * @access private 512 */ 513 function _read() 514 { 515 $fp = @fopen($this->_file, "rb"); 516 if ($this->_fileLocking) @flock($fp, LOCK_SH); 517 if ($fp) { 518 clearstatcache(); // because the filesize can be cached by PHP itself... 519 $length = @filesize($this->_file); 520 $mqr = get_magic_quotes_runtime(); 521 set_magic_quotes_runtime(0); 522 if ($this->_readControl) { 523 $hashControl = @fread($fp, 32); 524 $length = $length - 32; 525 } 526 $data = @fread($fp, $length); 527 set_magic_quotes_runtime($mqr); 528 if ($this->_fileLocking) @flock($fp, LOCK_UN); 529 @fclose($fp); 530 if ($this->_readControl) { 531 $hashData = $this->_hash($data, $this->_readControlType); 532 if ($hashData != $hashControl) { 533 @touch($this->_file, time() - 2*abs($this->_lifeTime)); 534 return false; 535 } 536 } 537 return $data; 538 } 539 $this->raiseError('Cache_Lite : Unable to read cache !', -2); 540 return false; 541 } 542 543 /** 544 * Write the given data in the cache file 545 * 546 * @param string $data data to put in cache 547 * @return boolean true if ok 548 * @access private 549 */ 550 function _write($data) 551 { 552 $fp = @fopen($this->_file, "wb"); 553 if ($fp) { 554 if ($this->_fileLocking) @flock($fp, LOCK_EX); 555 if ($this->_readControl) { 556 @fwrite($fp, $this->_hash($data, $this->_readControlType), 32); 557 } 558 $len = strlen($data); 559 @fwrite($fp, $data, $len); 560 if ($this->_fileLocking) @flock($fp, LOCK_UN); 561 @fclose($fp); 562 return true; 563 } 564 $this->raiseError('Cache_Lite : Unable to write cache !', -1); 565 return false; 566 } 567 568 /** 569 * Write the given data in the cache file and control it just after to avoir corrupted cache entries 570 * 571 * @param string $data data to put in cache 572 * @return boolean true if the test is ok 573 * @access private 574 */ 575 function _writeAndControl($data) 576 { 577 $this->_write($data); 578 $dataRead = $this->_read($data); 579 return ($dataRead==$data); 580 } 581 582 /** 583 * Make a control key with the string containing datas 584 * 585 * @param string $data data 586 * @param string $controlType type of control 'md5', 'crc32' or 'strlen' 587 * @return string control key 588 * @access private 589 */ 590 function _hash($data, $controlType) 591 { 592 switch ($controlType) { 593 case 'md5': 594 return md5($data); 595 case 'crc32': 596 return sprintf('% 32d', crc32($data)); 597 case 'strlen': 598 return sprintf('% 32d', strlen($data)); 599 default: 600 $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5); 601 } 602 } 603 604 } 605 606 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Feb 8 00:05:01 2012 | Cross-referenced by PHPXref 0.7 |
| Mambo API: Mambo is Free software released under the GNU/General Public License, Version 2 |