objectcache.php

Go to the documentation of this file.
00001 <?php
00002 
00003 /*******************************************************************************
00004  * Aliro - the modern, accessible content management system
00005  *
00006  * Aliro is open source software, free to use, and licensed under GPL.
00007  * You can find the full licence at http://www.gnu.org/copyleft/gpl.html GNU/GPL
00008  *
00009  * The author freely draws attention to the fact that Aliro derives from Mambo,
00010  * software that is controlled by the Mambo Foundation.  However, this section
00011  * of code is totally new.  If it should contain any fragments that are similar
00012  * to Mambo, please bear in mind (1) there are only so many ways to do things
00013  * and (2) the author of Aliro is also the author and copyright owner for large
00014  * parts of Mambo 4.6.
00015  *
00016  * Tribute should be paid to all the developers who took Mambo to the stage
00017  * it had reached at the time Aliro was created.  It is a feature rich system
00018  * that contains a good deal of innovation.
00019  *
00020  * Your attention is also drawn to the fact that Aliro relies on other items of
00021  * open source software, which is very much in the spirit of open source.  Aliro
00022  * wishes to give credit to those items of code.  Please refer to
00023  * http://aliro.org/credits for details.  The credits are not included within
00024  * the Aliro package simply to avoid providing a marker that allows hackers to
00025  * identify the system.
00026  *
00027  * Copyright in this code is strictly reserved by its author, Martin Brampton.
00028  * If it seems appropriate, the copyright will be vested in the Aliro Organisation
00029  * at a suitable time.
00030  *
00031  * Copyright (c) 2007 Martin Brampton
00032  *
00033  * http://aliro.org
00034  *
00035  * counterpoint@aliro.org
00036  *
00037  * These classes provide cache logic, and for no special reason, the profiling
00038  * logic that supports the timing of operations, aliroProfiler.
00039  *
00040  * cachedSingleton is the base for building a singleton class whose internal
00041  * data is cached.  It is used extensively within the core, especially for the
00042  * handlers that look after information about the main building blocks of the
00043  * CMS, such as menus, components, modules, etc.  It provides common code for
00044  * them so that it becomes simple to create a cached singleton object.
00045  *
00046  * aliroBasicCache is the class containing rudimentary cache operations.  It
00047  * was initially independently developed, and subsequently modified to contain
00048  * the features of CacheLite.  Except that a number of decisions have been
00049  * taken as well as the code being exclusively PHP5 - these factors make the
00050  * code a lot simpler.
00051  *
00052  * aliroSingletonObjectCache does any special operations needed in the handling
00053  * of cached singletons, extending aliroBasicCache.
00054  *
00055  * Further cache related code that emulates the services of CacheLite (more or
00056  * less) is found elsewhere (in aliroCentral.php at the time of writing).
00057  *
00058  */
00059 
00060 class aliroProfiler {
00061     private $start=0;
00062     private $prefix='';
00063 
00064     function __construct ( $prefix='' ) {
00065         $this->start = $this->getmicrotime();
00066         $this->prefix = $prefix;
00067     }
00068 
00069     public function reset () {
00070         $this->start = $this->getmicrotime();
00071     }
00072 
00073     public function mark( $label ) {
00074         return sprintf ( "\n$this->prefix %.3f $label", $this->getmicrotime() - $this->start );
00075     }
00076 
00077     public function getElapsed () {
00078         return $this->getmicrotime() - $this->start;
00079     }
00080 
00081     private function getmicrotime(){
00082         list($usec, $sec) = explode(" ",microtime());
00083         return ((float)$usec + (float)$sec);
00084     }
00085 }
00086 
00087 abstract class cachedSingleton {
00088 
00089     protected function __clone () { /* Enforce singleton */ }
00090 
00091     protected static function getCachedSingleton ($class) {
00092         $objectcache = aliroSingletonObjectCache::getInstance();
00093         $object = $objectcache->retrieve($class);
00094         if ($object == null) {
00095             $object = new $class();
00096             $objectcache->store($object);
00097         }
00098         return $object;
00099     }
00100 
00101     public function clearCache ($immediate=false) {
00102         $objectcache = aliroSingletonObjectCache::getInstance();
00103         $classname = get_class($this);
00104         $objectcache->delete($classname);
00105         if ($immediate) {
00106             $instancevar = $classname.'::$instance';
00107             eval("$instancevar = '$classname';");
00108         }
00109     }
00110     
00111     public function cacheNow () {
00112         aliroSingletonObjectCache::getInstance()->store($this);
00113     }
00114 
00115 }
00116 
00117 abstract class aliroBasicCache {
00118     private static $mops = array();
00119     protected $basepath = '';
00120     protected $sizelimit = 0;
00121     protected $timeout = 0;
00122 
00123     public function __construct () {
00124         $this->basepath = _ALIRO_CLASS_BASE.'/cache/';
00125     }
00126     
00127     public function __destruct () {
00128         foreach (self::$mops as $mop) if ($mop) shmop_close($mop);
00129     }
00130 
00131     abstract protected function getCachePath ($name);
00132 
00133     public function store ($object, $cachename='') {
00134         $path = $this->getCachePath($cachename ? $cachename : get_class($object));
00135         if (is_object($object)) $object->aliroCacheTimer = time();
00136         else {
00137             $givendata = $object;
00138             $object = new stdClass();
00139             $object->aliroCacheData = $givendata;
00140             $object->aliroCacheTimer = -time();
00141         }
00142         $s = serialize($object);
00143         $s .= md5($s);
00144         if (strlen($s) > $this->sizelimit) return false;
00145         return is_writeable(dirname($path)) ? file_put_contents($path, $s, LOCK_EX) : false;
00146     }
00147 
00148     public function retrieve ($class, $time_limit = 0) {
00149         // $timer = class_exists('aliroProfiler') ? new aliroProfiler() : null;
00150         $result = null;
00151         $path = $this->getCachePath($class);
00152         if (file_exists($path) AND ($string = @file_get_contents($path))) {
00153             $s = substr($string, 0, -32);
00154             $object = ($s AND (md5($s) == substr($string, -32))) ? unserialize($s) : null;
00155             if (is_object($object)) {
00156                 $time_limit = $time_limit ? $time_limit : $this->timeout;
00157                 $stamp = @$object->aliroCacheTimer;
00158                 if ((time() - abs($stamp)) <= $time_limit) $result = $stamp > 0 ? $object : @$object->aliroCacheData;
00159             }
00160             // if ($object AND $timer) echo "<br />Loaded $class in ".$timer->getElapsed().' secs';
00161         }
00162         return $result;
00163     }
00164 
00165     // Worked but slightly slower than using file system
00166     /*
00167     private function memStore ($string, $name) {
00168         $size = strlen($name);
00169         if ($mop = $this->memGetToken($name, $size+8)) {
00170             return shmop_write($mop, str_pad((string) $size, 8, '0', STR_PAD_LEFT).$string, $size+8);
00171         }
00172         else return false;
00173     }
00174 
00175     private function memRetrieve ($name) {
00176         if ($mop = $this->memGetToken($name)) {
00177             return shmop_read($mop, 8, intval(shmop_read($mop, 0, 8)));
00178         }
00179         return null;
00180     }
00181     
00182     private function memGetToken ($name, $minsize=0) {
00183         if (function_exists('ftok') AND function_exists('shmop_open')) {
00184             $id = ftok($name, 'R');
00185             $mop = isset(self::$mops[$id]) ? self::$mops[$id] : (self::$mops[$id] = @shmop_open($id, 'w', 0600, 0));
00186             if ($mop) {
00187                 if ($minsize <= shmop_size($mop)) return $mop;
00188                 shmop_delete($mop);
00189             }
00190             return @shmop_open($id, 'c', 0600, $minsize+128);
00191         }
00192         return false;
00193     }
00194     */
00195 }
00196 
00197 class aliroSingletonObjectCache extends aliroBasicCache {
00198     protected static $instance = __CLASS__;
00199     protected $timeout = _ALIRO_OBJECT_CACHE_TIME_LIMIT;
00200     protected $sizelimit = _ALIRO_OBJECT_CACHE_SIZE_LIMIT;
00201 
00202     public static function getInstance () {
00203         return is_object(self::$instance) ? self::$instance : (self::$instance = new self::$instance);
00204     }
00205 
00206     protected function getCachePath ($name) {
00207         return $this->basepath.'singleton/'.$name;
00208     }
00209 
00210     public function delete () {
00211         $classes = func_get_args();
00212         foreach ($classes as $class) {
00213             $cachepath = $this->getCachePath($class);
00214             if (file_exists($cachepath)) unlink($cachepath);
00215         }
00216     }
00217 
00218     public function deleteByExtension ($type) {
00219         $caches = array (
00220         'component' => 'aliroComponentHandler',
00221         'module' => 'aliroModuleHandler',
00222         'mambot' => 'aliroMambotHandler'
00223         );
00224         if (isset($caches[$type])) $this->delete($caches[$type]);
00225     }
00226 
00227 }

Generated on Thu Apr 17 13:03:27 2008 for ALIRO by  doxygen 1.5.5