b2evolution

Multilingual multiuser multiblog engine

b2evolution Technical Documentation (CVS HEAD) [ class tree: evocore ] [ index: evocore ] [ all elements ]

Source for file _blockcache.class.php

Documentation is available at _blockcache.class.php

  1. <?php
  2. /**
  3.  * This file implements the BlockCache class, which caches HTML blocks/snippets genereated by the app.
  4.  *
  5.  * This file is part of the evoCore framework - {@link http://evocore.net/}
  6.  * See also {@link http://sourceforge.net/projects/evocms/}.
  7.  *
  8.  * @copyright (c)2003-2010 by Francois PLANQUE - {@link http://fplanque.net/}
  9.  *  Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
  10.  *
  11.  *  {@internal License choice
  12.  *  - If you have received this file as part of a package, please find the license.txt file in
  13.  *    the same folder or the closest folder above for complete license terms.
  14.  *  - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  15.  *    then you must choose one of the following licenses before using the file:
  16.  *    - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  17.  *    - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  18.  *  }}}
  19.  *
  20.  *  {@internal Open Source relicensing agreement:
  21.  *  }}}
  22.  *
  23.  * @package evocore
  24.  *
  25.  * @version $Id: _blockcache.class.php,v 1.11 2010/02/08 17:51:42 efy-yury Exp $ }}}
  26.  *
  27.  */
  28. if!defined('EVO_MAIN_INIT') ) die'Please, do not access this page directly.' );
  29.  
  30.  
  31. /**
  32.  * Block Cache.
  33.  *
  34.  * @package evocore
  35.  */
  36. class BlockCache
  37. {
  38.     var $type;
  39.     var $keys;
  40.     var $serialized_keys = '';
  41.  
  42.     /**
  43.      * After how many bytes should we output sth live while collecting cache content:
  44.      */
  45.     var $output_chunk_size = 2000;
  46.  
  47.     /**
  48.      * Progressively caching the content of the current page:
  49.      */
  50.     var $cached_page_content = '';
  51.     /**
  52.      * Are we currently recording cache contents
  53.      */
  54.     var $is_collecting = false;
  55.  
  56.  
  57.     /**
  58.      * Constructor
  59.      */
  60.     function BlockCache$type$keys )
  61.     {
  62.         $this->type = $type;
  63.  
  64.         // Make sure keys are always in the same order:
  65.         ksort$keys );
  66.         $this->keys = $keys;
  67.  
  68.         $this->serialized_keys = $type;
  69.         foreach$keys as $key => $val )
  70.         {
  71.             $this->serialized_keys .= '+'.$key.'='.$val;
  72.         }
  73.  
  74.         // echo $this->serialized_keys;
  75.     }
  76.  
  77.  
  78.  
  79.     /**
  80.      * Invalidate a special key
  81.      *
  82.      * All we do is store the timestamp of teh invalidation
  83.      *
  84.      */
  85.     function invalidate_key$key$val )
  86.     {
  87.         global $Debuglog$servertimenow;
  88.  
  89.         $lastchanged_key_name 'last_changed+'.$key.'='.$val;
  90.  
  91.         // Invalidate using the real time (seconds may have elapsed since $sertimenow)
  92.         // Add 1 second because of teh granularity that's down to teh second
  93.         // Worst case scenario: content will be collected/cahced several times for a whole second (as well as the first request after the end of that second)
  94.         BlockCache::cacheproviderstore$lastchanged_key_nametime()+);
  95.  
  96.         $Debuglog->add'Invalidated: '.$lastchanged_key_name.' @ '.(time()+1)'blockcache' );
  97.     }
  98.  
  99.  
  100.     /**
  101.      * Check if cache contents are available, otherwise start collecting output to be cached
  102.      *
  103.      * Basically we get all the invalidation dates we need, then we get the
  104.      * data and then we check if some invalidation occured after the data was cached.
  105.      * If an invalidation date is missing we consider the cache to be
  106.      * obsolete but we generate a new invalidation date for next time we try to retrieve.
  107.      *
  108.      * @return true if we found and have echoed content from the cache
  109.      */
  110.     function check()
  111.     {
  112.         global $Debuglog$servertimenow;
  113.  
  114.         $missing_date false;
  115.         $most_recent_invalidation_ts 0;
  116.         $most_recent_invaliating_key '';
  117.         foreach$this->keys as $key => $val )
  118.         {
  119.             $lastchanged_key_name 'last_changed+'.$key.'='.$val;
  120.             $last_changed_ts $this->cacheproviderretrieve$lastchanged_key_name$success );
  121.             if$success )
  122.             {    // We have lost the key! Recreate and keep going for other keys:
  123.                 $Debuglog->add'Missing: '.$lastchanged_key_name'blockcache' );
  124.                 $missing_date true;
  125.                 $this->cacheproviderstore$lastchanged_key_name$servertimenow );
  126.                 continue;
  127.             }
  128.  
  129.             if$last_changed_ts $most_recent_invalidation_ts )
  130.             {    // This is the new most recent invalidation date.
  131.                 $most_recent_invalidation_ts $last_changed_ts;
  132.                 $most_recent_invaliating_key $lastchanged_key_name;
  133.             }
  134.         }
  135.  
  136.         if!$missing_date && $this->retrieve$most_recent_invalidation_ts$most_recent_invaliating_key ) )
  137.         // cache was not invalidated yet and we could retrieve:
  138.             return true;
  139.         }
  140.  
  141.         $this->is_collecting = true;
  142.  
  143.         $Debuglog->add'Collecting: '.$this->serialized_keys'blockcache' );
  144.  
  145.         ob_startarray$this'output_handler')$this->output_chunk_size );
  146.  
  147.         return false;
  148.  
  149.     }
  150.  
  151.  
  152.     /**
  153.      * Retrieve and output cache
  154.      *
  155.      * @param integer oldest acceptable timestamp
  156.      * @return boolean true if we could retrieve
  157.      */
  158.     function retrieve$oldest_acceptable_ts NULL$most_recent_invaliating_key '' )
  159.     {
  160.         global $Debuglog;
  161.         global $servertimenow;
  162.  
  163.         // return false;
  164.  
  165.         $content $this->cacheproviderretrieve$this->serialized_keys$success );
  166.  
  167.         if$success )
  168.         {
  169.             return false;
  170.         }
  171.  
  172.         if!is_null($oldest_acceptable_ts) )
  173.         // We want to do timestamp checking:
  174.  
  175.  
  176.             //if( ! preg_match( '/^([0-9]+) (.*)$/ms', $content, $matches ) )
  177.             if$pos strpos$content' ' ) )
  178.             {    // Could not find timestamp
  179.                 $Debuglog->add'MISSING TIMESTAMP on retrieval of: '.$this->serialized_keys'blockcache' );
  180.                 return false;
  181.             }
  182.  
  183.             // if( $matches[1] < $oldest_acceptable_ts )
  184.             if( ($cache_ts substr$content0$pos )) $oldest_acceptable_ts )
  185.             {    // Timestamp too old (there has been an invalidation in between)
  186.                 $Debuglog->add'Retrieved INVALIDATED cached content: '.$this->serialized_keys
  187.                     .' (invalidated by '.$most_recent_invaliating_key.' - '.$cache_ts.' < '.$oldest_acceptable_ts.')''blockcache' );
  188.                 return false;
  189.             }
  190.  
  191.             // OK, we have content that is still valid:
  192.             // $content = $matches[2];
  193.             $content substr$content$pos+);
  194.         }
  195.  
  196.         $Debuglog->add'Retrieved: '.$this->serialized_keys'blockcache' );
  197.  
  198.         // SEND CONTENT!
  199.         echo $content;
  200.  
  201.         return true;
  202.     }
  203.  
  204.  
  205.     /**
  206.      * This is called every x bytes to provide real time output
  207.      */
  208.     function output_handler$buffer )
  209.     {
  210.         $this->cached_page_content .= $buffer;
  211.         return $buffer;
  212.     }
  213.  
  214.  
  215.     /**
  216.      * We are going to output personal data and we want to abort collecting the data for the cache.
  217.      */
  218.     function abort_collect()
  219.     {
  220.         global $Debuglog;
  221.  
  222.         if$this->is_collecting )
  223.         {    // We are not collecting anyway
  224.             return;
  225.         }
  226.  
  227.          $Debuglog->add'Aborting cache data collection...''blockcache' );
  228.  
  229.         ob_end_flush();
  230.  
  231.         // We are no longer collecting...
  232.         $this->is_collecting = false;
  233.     }
  234.  
  235.  
  236.     /**
  237.      * End collecting output to be cached
  238.      *
  239.      * We just concatenate all the individual keys to have a single one
  240.      * Then we store with the current timestamp
  241.      */
  242.     function end_collect()
  243.     {
  244.         global $Debuglog$servertimenow;
  245.  
  246.         if$this->is_collecting )
  247.         {    // We are not collecting
  248.             return;
  249.         }
  250.  
  251.         ob_end_flush();
  252.  
  253.         // We use servertimenow because we may have used data that was loaded at the very start of this page
  254.         $this->cacheproviderstore$this->serialized_keys$servertimenow.' '.$this->cached_page_content );
  255.     }
  256.  
  257.  
  258.     /**
  259.      * put your comment there...
  260.      *
  261.      * @todo dh> This method should get removed from here, it's not limited to BlockCache.
  262.      * @param mixed $key 
  263.      * @param mixed $payload 
  264.      */
  265.     function cacheproviderstore$key$payload )
  266.     {
  267.         $ttl 3600 24// TODO: dh> should become a param to the method?!
  268.  
  269.         iffunction_exists('apc_store') )
  270.             return apc_store$key$payload$ttl );
  271.  
  272.         iffunction_exists('xcache_set'&& ini_get('xcache.var_size')
  273.             return xcache_set$key$payload$ttl );
  274.  
  275.         iffunction_exists('eaccelerator_put') )
  276.             return eaccelerator_put$key$data$ttl );
  277.  
  278.         return NULL;
  279.     }
  280.  
  281.  
  282.     /**
  283.      * put your comment there...
  284.      *
  285.      * @todo dh> This method should get removed from here, it's not limited to BlockCache.
  286.      * @param mixed $key 
  287.      * @param mixed $success 
  288.      */
  289.     function cacheproviderretrieve$key$success )
  290.     {
  291.         iffunction_exists('apc_fetch') )
  292.             return apc_fetch$key$success );
  293.  
  294.         iffunction_exists('xcache_get'&& ini_get('xcache.var_size')
  295.             $r xcache_get($key);
  296.         elseiffunction_exists('eaccelerator_get') )
  297.             $r eaccelerator_get($key);
  298.  
  299.         ifisset($r) )
  300.         {
  301.             $success true;
  302.             return $r;
  303.         }
  304.  
  305.         $success false;
  306.         return NULL;
  307.     }
  308.  
  309. }
  310.  
  311.  
  312. /*
  313.  * $Log: _blockcache.class.php,v $
  314.  * Revision 1.11  2010/02/08 17:51:42  efy-yury
  315.  * copyright 2009 -> 2010
  316.  *
  317.  * Revision 1.10  2009/12/22 08:02:12  fplanque
  318.  * doc
  319.  *
  320.  * Revision 1.9  2009/12/22 03:43:10  blueyed
  321.  * todo
  322.  *
  323.  * Revision 1.8  2009/12/22 02:56:35  blueyed
  324.  * BlockCache: add support for xcache and eaccelerator
  325.  *
  326.  * Revision 1.7  2009/12/06 03:24:11  fplanque
  327.  * minor/doc/fixes
  328.  *
  329.  * Revision 1.6  2009/12/01 04:19:25  fplanque
  330.  * even more invalidation dimensions
  331.  *
  332.  * Revision 1.5  2009/12/01 03:33:19  fplanque
  333.  * Improved handling of invalidation dates
  334.  *
  335.  * Revision 1.4  2009/12/01 02:04:45  fplanque
  336.  * minor
  337.  *
  338.  * Revision 1.3  2009/12/01 01:33:21  blueyed
  339.  * Fix install: wrap apc_*
  340.  *
  341.  * Revision 1.2  2009/11/30 23:16:24  fplanque
  342.  * basic cache invalidation is working now
  343.  *
  344.  * Revision 1.1  2009/11/30 04:31:37  fplanque
  345.  * BlockCache Proof Of Concept
  346.  *
  347.  */
  348. ?>

Documentation generated on Sat, 06 Mar 2010 04:01:30 +0100 by phpDocumentor 1.4.2. This site is hosted and maintained by Daniel HAHLER (Contact).