Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

cache.inc.php

Go to the documentation of this file.
00001 <?
00017 class CacheBot
00018 {
00022     private static $bot = null;
00023 
00027     private function __construct()
00028     {
00029     }
00030     
00036     public static function getBot()
00037     {
00038         //is it legit?
00039         if (self::$bot instanceOf EasyCache)
00040             return self::$bot;
00041         //nope, default to no caching.
00042         else
00043         {
00044             self::setBot(new NoCache());
00045             return self::getBot();
00046         }
00047     }
00048 
00054     public static function setBot($bot, $prefix = '')
00055     {
00056         if ($bot instanceOf EasyCache)
00057             self::$bot = $bot;
00058         else
00059             throw new Exception('Cachebots must be a derivitive of EasyCache');
00060     }
00061 
00072     public static function get($key, $life = null)
00073     {
00074         //if we're not null... set our life.
00075         if ($life !== null)
00076         {
00077             $oldLife = EasyCache::$life;
00078             EasyCache::$life = (int)$life;
00079         }
00080             
00081         $rval = self::$bot->get($key);
00082         
00083         //set the bot back to its old value.
00084         if (isset($oldLife))
00085             EasyCache::$life = $oldLife;
00086 
00087         return $rval;
00088     }
00089     
00098     public static function set($key, $data, $life = null)
00099     {
00100         //if we're not null... set our life.
00101         if ($life !== null)
00102         {
00103             $oldLife = EasyCache::$life;
00104             EasyCache::$life = (int)$life;
00105         }
00106             
00107         //save it.
00108         $rval = self::$bot->set($key, $data);
00109     
00110         //set the bot back to its old value.
00111         if (isset($oldLife))
00112             EasyCache::$life = $oldLife;
00113 
00114         //return it!
00115         return $rval;
00116     }
00117 
00122     public static function delete($key)
00123     {
00124         return self::$bot->delete($key);
00125     }
00126     
00131     public static function flush()
00132     {
00133         return self::$bot->flush();
00134     }
00135 }
00136 
00140 abstract class EasyCache
00141 {
00145     public static $life = 3600;
00146 
00150     public static $hits = 0;
00151 
00155     private static $keys = array();
00156 
00162     public function __construct($life = null)
00163     {
00164         if ($life)
00165             self::$life = (int)$life;
00166     }
00167     
00178     abstract public function get($key);
00179 
00188     abstract public function set($key, $data);
00189 
00195     abstract public function delete($key);
00196 
00200     abstract public function flush();
00201 
00209     public static function markCacheHit($key, $type = 'get')
00210     {
00211         //increment the total number
00212         self::$hits++;
00213 
00214         //add it to our array
00215         if (Config::get("bj_track_cache"))
00216         {
00217             self::$keys['keys'][] = $key;
00218             self::$keys['type'][] = $type;
00219         }
00220     }
00221 
00227     public static function drawCacheStats()
00228     {
00229         global $me;
00230         
00231         echo "<div class=\"cacheHits\">";
00232         foreach (self::$keys['keys'] AS $index => $key)
00233         {
00234             if (is_array($key))
00235             {
00236                 $links = array();
00237                 foreach ($key AS $val)
00238                     $links[] = $me->getLink("admin.viewcache?val=" . base64_encode($val), $val);
00239                 
00240                 echo "<p>Get Keyset:" . implode(", ", $links) . "</p>";
00241             }
00242             else
00243                 echo "<p>" . ucfirst(self::$keys['type'][$index]) . ": " . $me->getLink("admin.viewcache?key=" . base64_encode($key), $key) . "</p>\n";
00244         }
00245         echo "</div>";
00246     }
00247 }
00248 
00257 class EasyMemCache extends EasyCache
00258 {
00259     public $mc;
00260     
00267     public function __construct($servers = 'localhost:112211', $life = null)
00268     {
00269         //error checking.
00270         if (!class_exists('Memcache'))
00271             throw new Exception('Memcache is not installed in PHP.');
00272 
00273         //call mommy.
00274         parent::__construct($life);
00275         
00276         //create our cache object
00277         $this->mc = new Memcache;
00278         
00279         //did we get a string?
00280         if (is_string($servers))
00281             $servers = array($servers);
00282         
00283         //connect to servers.
00284         if (count($servers))
00285             foreach ($servers AS $server)
00286                 if (preg_match('/^(.*):([0-9]*)$/', $server, $matches))
00287                     $this->mc->addServer($matches[1], $matches[2]);
00288         else
00289             throw new Exception('Weird servers passed to EasyMemCache.');
00290     }
00291 
00292     public function get($key)
00293     {
00294         self::markCacheHit($key, 'get');
00295         
00296         //get an array of keys.
00297         if (is_array($key))
00298         {
00299             $ret = array();
00300 
00301             //only do something if its no empty
00302             if (count($key))
00303             {
00304                 //init.
00305                 foreach ($key AS $id)
00306                     $ret[$id] = false;
00307                 
00308                 //get all our keys.
00309                 $data = $this->mc->get($key);
00310                 
00311                 //save our data.
00312                 foreach ($data AS $index => $val)
00313                     $ret[$index] = $val;
00314             }
00315 
00316             return $ret;
00317         }
00318         //return our single value
00319         else
00320             return $this->mc->get($key);
00321     }
00322 
00323     public function set($key, $data)
00324     {
00325         self::markCacheHit($key, 'set');
00326         
00327         return $this->mc->set($key, $data, MEMCACHE_COMPRESSED, self::$life);
00328     }
00329 
00330     public function delete($key)
00331     {
00332         self::markCacheHit($key, 'delete');
00333         
00334         return $this->mc->delete($key);
00335     }
00336 
00337     public function flush()
00338     {
00339         $this->mc->flush();
00340     }
00341 }
00342 
00350 class EasyFileCache extends EasyCache
00351 {
00352     private $path;
00353     
00361     public function __construct($path = "/tmp/EasyCache/", $life = null)
00362     {
00363         parent::__construct($life);
00364         
00365         $this->path = $path;
00366 
00367         //make sure our cache directory exists.
00368         if (!is_dir($this->path))
00369             mkdir($this->path, 0777, true);
00370     }
00371     
00375     public function get($key)
00376     {
00377         //if its an array... then we want want to lookup all the caches
00378         if (is_array($key))
00379         {
00380             $ret = array();
00381 
00382             //if there are keys, look them up individually (this is the downfall of file cache)
00383             if (count($key))
00384                 foreach ($key AS $single)
00385                     $ret[$single] = $this->get($single);
00386         
00387             return $ret;
00388         }
00389         //nope, just a single key...
00390         else
00391         {
00392             //mark it here because arrays all go here.
00393             self::markCacheHit($key, 'get');
00394             
00395             //get the cache.
00396             if ($this->isCached($key))
00397             {
00398                 $data = file_get_contents($this->getCachePath($key));
00399                 return unserialize($data);
00400             }
00401             else
00402                 return null;
00403         }
00404     }
00405 
00414     public function set($key, $data)
00415     {
00416         self::markCacheHit($key, 'set');
00417         
00418         file_put_contents($this->getCachePath($key), serialize($data));
00419     }
00420 
00426     public function delete($key)
00427     {
00428         self::markCacheHit($key, 'delete');
00429         
00430         $file = $this->getCachePath($key);
00431 
00432         if (file_exists($file))
00433             unlink($file);
00434     }
00435 
00436     public function flush()
00437     {
00438         //delete everything on the path.
00439         $cmd = "find $this->path -type f | xargs rm";
00440         Util::shellExec($cmd);
00441     }
00442     
00450     protected function isCached($key)
00451     {
00452         $file = $this->getCachePath($key);
00453 
00454         //does it exist?
00455         if (file_exists($file))
00456         {
00457             //okay, now is it legit?
00458             $minAge = time() - self::$life;
00459             if (filemtime($file) >= $minAge)
00460                 return true;
00461             //nope, stale... kill it
00462             else
00463                 $this->delete($key);
00464         }
00465 
00466         return false;
00467     }
00468     
00474     protected function getCachePath($key)
00475     {
00476         return $this->path . sha1($key);
00477     }
00478 }
00479 
00487 class EasyDBCache extends EasyCache
00488 {
00489     private $table;
00490     
00497     public function __construct($table = "easy_cache", $life = null)
00498     {
00499         parent::__construct($life);
00500         
00501         $this->table = $table;
00502 
00503 //umm... we shoudl put this somewhere else.
00504 //      if (!BaseJumper::dbHasTable($this->table))
00505 //          $this->createTable();
00506     }
00507 
00508     protected function createTable()
00509     {
00510         dbQuery("
00511             CREATE TABLE $this->table
00512             (
00513                 `id` varchar(255) default '' not null,
00514                 `data` mediumtext default '' not null,
00515                 `expire_date` datetime not null,
00516                 KEY(id)
00517             ) ENGINE=InnoDB 
00518         ");
00519     }
00520     
00524     public function get($key)
00525     {
00526         self::markCacheHit($key, 'get');
00527         
00528         //if its an array, then get all the keys
00529         if (is_array($key))
00530         {
00531             //init our array.
00532             $rval = array();
00533             
00534             //make sure we got some.
00535             if (count($key))
00536             {
00537                 //init it incase we dont find it.
00538                 foreach ($key AS $id)
00539                     $rval[$id] = false; 
00540             
00541                 //do our query
00542                 $rs = dbQuery("
00543                     SELECT ec.*, ec.expire_date <= NOW() AS expired
00544                     FROM $this->table ec
00545                     WHERE ec.id IN ('" . implode("', '", $key) . "')
00546                 ");
00547 
00548                 //get them all
00549                 while ($ar = dbFetchAssoc($rs))
00550                 {
00551                     //what one?
00552                     $id = $ar['id'];
00553                     
00554                     //if we're expired... delete it.
00555                     if ((int)$ar['expired'])
00556                         $this->delete($id);
00557                     //nope, we go it.. save it.
00558                     else
00559                         $rval[$id] = unserialize($ar['data']);
00560                 }
00561             }
00562 
00563             //send the array of cached stuff back
00564             return $rval;
00565         }
00566         $ar = dbFetchAssoc(dbQuery("
00567             SELECT ec.*, ec.expire_date <= NOW() AS expired
00568             FROM $this->table ec
00569             WHERE id = '$key'
00570         "));
00571 
00572         if (is_array($ar))
00573         {
00574             //if we're expired... delete it.
00575             if ((int)$ar['expired'])
00576                 $this->delete($key);
00577             else
00578                 return unserialize($ar['data']);
00579         }
00580 
00581         //if we didnt return before, we will now =)
00582         return null;
00583     }
00584 
00593     public function set($key, $data)
00594     {
00595         self::markCacheHit($key, 'set');
00596         
00597         //first delete our old data.
00598         $this->delete($key);
00599 
00600         //format our data.
00601         $data = dbEscape(serialize($data));
00602 
00603         //insert it!
00604         dbExecute("
00605             INSERT INTO $this->table
00606                 (id, data, expire_date)
00607             VALUES
00608                 ('$key', '$data', DATE_ADD(NOW(), INTERVAL " . self::$life . " SECOND))
00609         ");
00610     } 
00611 
00617     public function delete($key)
00618     {
00619         self::markCacheHit($key, 'delete');
00620         
00621         dbExecute("
00622             DELETE FROM $this->table
00623             WHERE id = '$key'
00624         ");
00625     }
00626 
00627     public function flush()
00628     {
00629         dbExecute("
00630             DELETE FROM $this->table
00631         ");
00632     }
00633 }
00634 
00640 class NoCache extends EasyCache
00641 {
00642     public function get($key)
00643     {
00644         self::markCacheHit($key, 'get');
00645         return null;
00646     }
00647     
00648     public function set($key, $data)
00649     {
00650         self::markCacheHit($key, 'set');
00651         return true;
00652     }
00653     
00654     public function delete($key)
00655     {
00656         self::markCacheHit($key, 'delete');
00657         return true;
00658     }
00659 
00660     public function flush()
00661     {
00662         return true;
00663     }
00664 }
00665 
00667 ?>

Generated on Fri Oct 27 12:26:39 2006 for BaseJumper by doxygen 1.3.9.1