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