Cache
[ class tree: Cache ] [ index: Cache ] [ all elements ]

Source for file Container.php

Documentation is available at Container.php

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: Cache                                                        |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1997-2003 The PHP Group                                |
  6. // +----------------------------------------------------------------------+
  7. // | This source file is subject to version 2.0 of the PHP license,       |
  8. // | that is bundled with this package in the file LICENSE, and is        |
  9. // | available at through the world-wide-web at                           |
  10. // | http://www.php.net/license/2_02.txt.                                 |
  11. // | If you did not receive a copy of the PHP license and are unable to   |
  12. // | obtain it through the world-wide-web, please send a note to          |
  13. // | license@php.net so we can mail you a copy immediately.               |
  14. // +----------------------------------------------------------------------+
  15. // | Authors: Ulf Wendel <ulf.wendel@phpdoc.de>                           |
  16. // |          Sebastian Bergmann <sb@sebastian-bergmann.de>               |
  17. // |          Christian Stocker <chregu@phant.ch>                         |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Container.php,v 1.7 2005/01/26 09:47:28 dufuz Exp $
  21.  
  22. require_once 'Cache/Error.php';
  23.  
  24. /**
  25. * Common base class of all cache storage container.
  26. * To speed up things we do a preload you should know about, otherwise it might
  27. * play you a trick. The Cache controller classes (Cache/Cache, Cache/Output, ...)
  28. * usually do something like is (isCached($id) && !isExpired($id)) return $container->load($id).
  29. * if you implement isCached(), isExpired() and load() straight ahead, each of this
  30. * functions will result in a storage medium (db, file,...) access. This generates too much load.
  31. * Now, a simple speculative preload should saves time in most cases. Whenever
  32. * one of the mentioned methods is invoked we preload the cached dataset into class variables.
  33. * That means that we have only one storage medium access for the sequence
  34. *  (isCached($id) && !isExpired($id)) return $container->load($id).
  35. * The bad thing is that the preloaded data might be outdated meanwhile, which is
  36. * unlikely but for you power users, be warned. If you do not want the preload
  37. * you should switch it off by setting the class variable $preload to false. Anyway, this is
  38. * not recommended!
  39. @author   Ulf Wendel <ulf.wendel@phpdoc.de>
  40. @version  $Id: Container.php,v 1.7 2005/01/26 09:47:28 dufuz Exp $
  41. @package  Cache
  42. @access   public
  43. @abstract
  44. */
  45. {
  46.  
  47.     /**
  48.     * Flag indicating wheter to preload datasets.
  49.     *
  50.     * See the class description for more details.
  51.     *
  52.     * @var  boolean 
  53.     */
  54.     var $preload = true;
  55.  
  56.     /**
  57.     * ID of a preloaded dataset
  58.     *
  59.     * @var  string 
  60.     */
  61.     var $id = '';
  62.  
  63.     /**
  64.     * Cache group of a preloaded dataset
  65.     *
  66.     * @var  string 
  67.     */
  68.     var $group = '';
  69.  
  70.     /**
  71.     * Expiration timestamp of a preloaded dataset.
  72.     * 
  73.     * @var  integer 0 means never, endless
  74.     */
  75.     var $expires = 0;
  76.  
  77.     /**
  78.     * Value of a preloaded dataset.
  79.     * 
  80.     * @var  string 
  81.     */
  82.     var $cachedata = '';
  83.  
  84.     /**
  85.     * Preloaded userdata field.
  86.     * 
  87.     * @var  string 
  88.     */
  89.     var $userdata = '';
  90.  
  91.     /**
  92.     * Flag indicating that the dataset requested for preloading is unknown.
  93.     *  
  94.     * @var  boolean 
  95.     */
  96.     var $unknown = true;
  97.  
  98.     /**
  99.     * Encoding mode for cache data: base64 or addslashes() (slash).
  100.     *
  101.     * @var  string  base64 or slash
  102.     */
  103.     var $encoding_mode = 'base64';
  104.     
  105.     /**
  106.     * Highwater mark - maximum space required by all cache entries.
  107.     * 
  108.     * Whenever the garbage collection runs it checks the amount of space
  109.     * required by all cache entries. If it's more than n (highwater) bytes
  110.     * the garbage collection deletes as many entries as necessary to reach the
  111.     * lowwater mark.
  112.     * 
  113.     * @var  int 
  114.     * @see  lowwater
  115.     */
  116.     var $highwater = 2048000; 
  117.     
  118.     
  119.     /**
  120.     * Lowwater mark
  121.     *
  122.     * @var  int 
  123.     * @see  highwater
  124.     */
  125.     var $lowwater = 1536000;
  126.     
  127.     
  128.     /**
  129.     * Options that can be set in every derived class using it's constructor.
  130.     * 
  131.     * @var  array 
  132.     */
  133.     var $allowed_options = array('encoding_mode''highwater''lowwater');
  134.     
  135.     
  136.     /**
  137.     * Loads a dataset from the cache.
  138.     * 
  139.     * @param    string  dataset ID
  140.     * @param    string  cache group
  141.     * @return   mixed   dataset value or null on failure
  142.     * @access   public
  143.     */
  144.     function load($id$group)
  145.     {
  146.         if ($this->preload{
  147.             if ($this->id != $id || $this->group != $group{
  148.                 $this->preload($id$group);
  149.             }
  150.             return $this->cachedata;
  151.         else {
  152.             list$data$this->fetch($id$group);
  153.             return $data;
  154.         }
  155.     // end func load
  156.  
  157.     /**
  158.     * Returns the userdata field of a cached data set.
  159.     *
  160.     * @param    string  dataset ID
  161.     * @param    string  cache group
  162.     * @return   string  userdata
  163.     * @access   public
  164.     */
  165.     function getUserdata($id$group)
  166.     {
  167.         if ($this->preload{
  168.             if ($this->id != $id || $this->group != $group{
  169.                 $this->preload($id$group);
  170.             }
  171.             return $this->userdata;
  172.         else {
  173.             list, , $userdata$this->fetch($id$group);
  174.             return $userdata;
  175.         }
  176.     // end func getUserdata
  177.  
  178.     /**
  179.     * Checks if a dataset is expired.
  180.     * 
  181.     * @param    string  dataset ID
  182.     * @param    string  cache group
  183.     * @param    integer maximum age timestamp
  184.     * @return   boolean 
  185.     * @access   public
  186.     */
  187.     function isExpired($id$group$max_age)
  188.     {
  189.         if ($this->preload{
  190.             if ($this->id != $id || $this->group != $group{
  191.                 $this->preload($id$group);
  192.             }
  193.             if ($this->unknown{
  194.                 return false;
  195.             }
  196.         else {
  197.             // check if at all it is cached
  198.             if (!$this->isCached($id$group)) {
  199.                 return false;
  200.             }
  201.             // I'm lazy...
  202.             list($this->expires, , $this->fetch($id$group);
  203.         }
  204.  
  205.         // endless
  206.         if (0 == $this->expires{
  207.             return false;
  208.         }
  209.         // you feel fine, Ulf?
  210.         if ($expired  ($this->expires <= time(|| ($max_age && ($this->expires <= $max_age))) ) {
  211.  
  212.            $this->remove($id$group);
  213.            $this->flushPreload();
  214.         }
  215.         return $expired;
  216.     // end func isExpired
  217.  
  218.     /**
  219.     * Checks if a dataset is cached.
  220.     *
  221.     * @param    string  dataset ID
  222.     * @param    string  cache group
  223.     * @return   boolean 
  224.     */
  225.     function isCached($id$group)
  226.     {
  227.         if ($this->preload{
  228.             if ($this->id != $id || $this->group != $group{
  229.                 $this->preload($id$group);
  230.             }
  231.             return !($this->unknown);
  232.         }
  233.         return $this->idExists($id$group);
  234.     // end func isCached
  235.  
  236.     //
  237.     // abstract methods
  238.     //
  239.  
  240.     /**
  241.     * Fetches a dataset from the storage medium.
  242.     *
  243.     * @param    string  dataset ID
  244.     * @param    string  cache group
  245.     * @return   array   format: [expire date, cached data, user data]
  246.     * @throws   Cache_Error
  247.     * @abstract
  248.     */
  249.     function fetch($id$group)
  250.     {
  251.         return array(nullnullnull);
  252.     // end func fetch
  253.  
  254.     /**
  255.     * Stores a dataset.
  256.     * 
  257.     * @param    string  dataset ID
  258.     * @param    mixed   data to store
  259.     * @param    mixed   userdefined expire date
  260.     * @param    string  cache group
  261.     * @param    string  additional userdefined data
  262.     * @return   boolean 
  263.     * @throws   Cache_Error
  264.     * @access   public
  265.     * @abstract
  266.     */
  267.     function save($id$data$expire$group$userdata)
  268.     {
  269.         // QUESTION: Should we update the preload buffer instead?
  270.         // Don't think so as the sequence save()/load() is unlikely.
  271.         $this->flushPreload($id$group);
  272.         return null;
  273.     // end func save
  274.  
  275.     /**
  276.     * Removes a dataset.
  277.     * 
  278.     * @param    string  dataset ID
  279.     * @param    string  cache group
  280.     * @return   boolean 
  281.     * @access   public
  282.     * @abstract
  283.     */     
  284.     function remove($id$group)
  285.     {
  286.         $this->flushPreload($id$group);
  287.         return null;
  288.     // end func remove
  289.  
  290.     /**
  291.     * Flushes the cache - removes all caches datasets from the cache.
  292.     * 
  293.     * @param    string      If a cache group is given only the group will be flushed
  294.     * @return   integer     Number of removed datasets, -1 on failure
  295.     * @access   public
  296.     * @abstract
  297.     */
  298.     function flush($group)
  299.     {
  300.         $this->flushPreload();
  301.         return null;
  302.     // end func flush
  303.  
  304.     /**
  305.     * Checks if a dataset exists.
  306.     * 
  307.     * @param    string  dataset ID
  308.     * @param    string  cache group
  309.     * @return   boolean 
  310.     * @access   public
  311.     * @abstract
  312.     */
  313.     function idExists($id$group)
  314.     {
  315.         return null;
  316.     // end func idExists
  317.  
  318.     /**
  319.     * Starts the garbage collection.
  320.     * 
  321.     * @access   public
  322.     * @abstract
  323.     */
  324.     function garbageCollection()
  325.     {
  326.         $this->flushPreload();
  327.     // end func garbageCollection
  328.  
  329.     /**
  330.     * Does a speculative preload of a dataset
  331.     *
  332.     * @param    string  dataset ID
  333.     * @param    string  cache group
  334.     * @return   boolean 
  335.     */ 
  336.     function preload($id$group)
  337.     {
  338.         // whatever happens, remember the preloaded ID
  339.         $this->id = $id;
  340.         $this->group = $group;        
  341.  
  342.         list($this->expires$this->cachedata$this->userdata$this->fetch($id$group);
  343.  
  344.         if ($this->expires === null{
  345.             // Uuups, unknown ID
  346.             $this->flushPreload();
  347.             return false;
  348.         }
  349.  
  350.         $this->unknown = false;
  351.  
  352.         return true;
  353.     // end func preload
  354.  
  355.     /**
  356.     * Flushes the internal preload buffer.
  357.     *
  358.     * save(), remove() and flush() must call this method
  359.     * to preevent differences between the preloaded values and
  360.     * the real cache contents.
  361.     *
  362.     * @param    string  dataset ID, if left out the preloaded values will be flushed.
  363.     *                    If given the preloaded values will only be flushed if they are
  364.     *                    equal to the given id and group
  365.     * @param    string  cache group
  366.     * @see  preload()
  367.     */
  368.     function flushPreload($id ''$group 'default')
  369.     {
  370.         if (!$id || ($this->id == $id && $this->group == $group)) {
  371.             // clear the internal preload values
  372.             $this->id = '';
  373.             $this->group = '';
  374.             $this->cachedata = '';
  375.             $this->userdata = '';
  376.             $this->expires = -1;
  377.             $this->unknown = true;
  378.         }
  379.     // end func flushPreload
  380.  
  381.     /**
  382.     * Imports the requested datafields as object variables if allowed
  383.     * 
  384.     * @param    array   List of fields to be imported as object variables
  385.     * @param    array   List of allowed datafields
  386.     */
  387.     function setOptions($requested$allowed)
  388.     {
  389.         foreach ($allowed as $k => $field{
  390.             if (isset($requested[$field])) {
  391.                 $this->$field $requested[$field];
  392.             }
  393.         }      
  394.     // end func setOptions
  395.  
  396.     /**
  397.     * Encodes the data for the storage container.
  398.     * 
  399.     * @var  mixed data to encode
  400.     */
  401.     function encode($data)
  402.     {
  403.         if ($this->encoding_mode == 'base64'
  404.             return base64_encode(serialize($data));
  405.         else 
  406.             return serialize($data);
  407.         }
  408.     // end func encode
  409.  
  410.     
  411.     /**
  412.     * Decodes the data from the storage container.
  413.     * 
  414.     * @var  mixed 
  415.     */
  416.     function decode($data)
  417.     {
  418.         if ($this->encoding_mode == 'base64'{
  419.             return unserialize(base64_decode($data));
  420.         else {
  421.             return unserialize($data);
  422.         }
  423.     // end func decode
  424.  
  425.     
  426.     /**
  427.     * Translates human readable/relative times in unixtime
  428.     *
  429.     * @param  mixed   can be in the following formats:
  430.     *                human readable          : yyyymmddhhmm[ss]] eg: 20010308095100
  431.     *                relative in seconds (1) : +xx              eg: +10
  432.     *                relative in seconds (2) : x <  946681200   eg: 10
  433.     *                absolute unixtime       : x < 2147483648   eg: 2147483648
  434.     *                see comments in code for details
  435.     * @return integer unix timestamp
  436.     */
  437.     function getExpiresAbsolute($expires)
  438.     {
  439.         if (!$expires{
  440.             return 0;
  441.         }
  442.         //for api-compatibility, one has not to provide a "+",
  443.         // if integer is < 946681200 (= Jan 01 2000 00:00:00)
  444.         if ($expires[0== '+' || $expires < 946681200{
  445.             return(time($expires);
  446.         elseif ($expires < 100000000000{
  447.             //if integer is < 100000000000 (= in 3140 years),
  448.             // it must be an absolut unixtime
  449.             // (since the "human readable" definition asks for a higher number)
  450.             return $expires;
  451.         else {
  452.             // else it's "human readable";
  453.             $year substr($expires04);
  454.             $month substr($expires42);
  455.             $day substr($expires62);
  456.             $hour substr($expires82);
  457.             $minute substr($expires102);
  458.             $second substr($expires122);
  459.             return mktime($hour$minute$second$month$day$year);
  460.         }
  461.         
  462.     // end func getExpireAbsolute
  463.     
  464. // end class Container
  465. ?>

Documentation generated on Mon, 11 Mar 2019 14:14:36 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.