Dotclear

Changeset 982


Ignore:
Timestamp:
04/02/09 12:46:50 (14 years ago)
Author:
pep
Message:

MemCache? : commited actual (and revised) version

Location:
plugins/memCache
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • plugins/memCache/README

    r186 r982  
    66You may add the following constants in your main config.php file: 
    77 
    8 DC_MC_CACHE_ENABLE : set to false to disable caching system (default true) 
    9 DC_MC_CACHE_HOST   : hostname of the server hosting the memcached instance (default localhost) 
    10 DC_MC_CACHE_PORT   : port of the memcached instance (default 11211) 
     8DC_MC_CACHE_ENABLE       : set to false to disable caching system (default true) 
     9DC_MC_CACHE_HOST         : hostname of the server hosting the memcached instance (default localhost) 
     10DC_MC_CACHE_PORT         : port of the memcached instance (default 11211) 
     11DC_MC_CACHE_PERSISTENT   : establish a persistent connection to memcached 
     12DC_MC_CACHE_SCHEDULED    : ensure posts scheduling compatibiliy 
     13 
     14 
     15HINTS 
     16----- 
     17 
     18If you want cache to be called before *any* connection to database, add a 
     19require statement to _post_config.php at the end of your configuration file. 
  • plugins/memCache/_define.php

    r217 r982  
    22# -- BEGIN LICENSE BLOCK ---------------------------------- 
    33# 
    4 # This file is part of Dotclear 2. 
     4# This file is part of MemCache, a plugin for Dotclear 2. 
    55# 
    6 # Copyright (c) 2003-2008 Olivier Meunier and contributors 
     6# Copyright (c) 2008-2009 Alain Vagner, Pep and contributors 
    77# Licensed under the GPL version 2.0 license. 
    88# See LICENSE file or 
     
    1010# 
    1111# -- END LICENSE BLOCK ------------------------------------ 
     12if (!defined('DC_RC_PATH')) { return; } 
    1213 
    1314$this->registerModule( 
    1415     /* Name */               "MemCache", 
    1516     /* Description*/         "Blog pages cache using memcached", 
    16      /* Author */             "Olivier Meunier and contributors", 
    17      /* Version */            '0.1', 
     17     /* Author */             "Alain Vagner, Pep and contributors", 
     18     /* Version */            '1.0-beta2', 
    1819     /* Permissions */        null 
    1920); 
  • plugins/memCache/_prepend.php

    r217 r982  
    22# -- BEGIN LICENSE BLOCK ---------------------------------- 
    33# 
    4 # This file is part of Dotclear 2. 
     4# This file is part of MemCache, a plugin for Dotclear 2. 
    55# 
    6 # Copyright (c) 2003-2008 Olivier Meunier and contributors 
     6# Copyright (c) 2008-2009 Alain Vagner, Pep and contributors 
    77# Licensed under the GPL version 2.0 license. 
    88# See LICENSE file or 
     
    1010# 
    1111# -- END LICENSE BLOCK ------------------------------------ 
     12if (!defined('DC_RC_PATH')) { return; } 
    1213 
    1314if (!defined('DC_MC_CACHE_ENABLE')) { 
    14      define('DC_MC_CACHE_ENABLE',true); 
     15     define('DC_MC_CACHE_ENABLE',class_exists('Memcache')); 
    1516} 
    1617 
     
    2324} 
    2425 
    25  
    26 if (!DC_MC_CACHE_ENABLE) { 
    27      return; 
     26if (!defined('DC_MC_CACHE_PERSISTENT')) { 
     27     define('DC_MC_CACHE_PERSISTENT', false); 
    2828} 
    2929 
    30 # We need touch function 
    31 if (!class_exists('Memcache')) { 
    32      return; 
     30if (!defined('DC_MC_CACHE_SCHEDULED')) { 
     31     define('DC_MC_CACHE_SCHEDULED',false); 
    3332} 
     33 
     34if (!DC_MC_CACHE_ENABLE) return; 
    3435 
    3536$GLOBALS['__autoload']['dcMemCache'] = dirname(__FILE__).'/class.cache.php'; 
    3637 
    37 $core->addBehavior('urlHandlerServeDocument',array('dcMemCacheBehaviors','urlHandlerServeDocument')); 
    38 $core->addBehavior('publicBeforeDocument',array('dcMemCacheBehaviors','publicBeforeDocument')); 
     38$core->addBehavior('urlHandlerServeDocument',     array('dcMemCacheBehaviors','urlHandlerServeDocument')); 
     39$core->addBehavior('publicBeforeDocument',        array('dcMemCacheBehaviors','publicBeforeDocument')); 
     40$core->addBehavior('coreBlogAfterTriggerBlog',    array('dcMemCacheBehaviors','coreBlogAfterTriggerBlog')); 
    3941 
    4042class dcMemCacheBehaviors 
     
    4446          try 
    4547          { 
    46                $cache = new dcMemCache(DC_MC_CACHE_HOST, DC_MC_CACHE_PORT); 
     48               $cache = new dcMemCache($_SERVER['REQUEST_URI'],DC_MC_CACHE_HOST,DC_MC_CACHE_PORT,DC_MC_CACHE_PERSISTENT); 
    4749                
    4850               $do_cache = true; 
    4951                
    5052               # We have POST data, no cache 
    51                if (!empty($_POST)) { 
    52                     $do_cache = false; 
    53                } 
     53               if (!empty($_POST)) $do_cache = false; 
    5454                
    5555               # This is a post with a password, no cache 
     
    5858               } 
    5959                
    60                if ($do_cache) 
    61                { 
     60               if ($do_cache) { 
    6261                    # No POST data or COOKIE, do cache 
    63                     $cache->storePage($_SERVER['REQUEST_URI'],$result['content_type'],$result['content'],$result['blogupddt']); 
     62                    $cache->storePage($result['content_type'],$result['content'],$result['blogupddt']); 
    6463               } 
    65                else 
    66                { 
     64               else { 
    6765                    # Remove cache file 
    68                     $cache->dropPage($_SERVER['REQUEST_URI']); 
     66                    $cache->dropPage(); 
    6967               } 
    7068          } 
     
    7472     public static function publicBeforeDocument(&$core) 
    7573     { 
    76           if (!empty($_POST)) { 
    77                return; 
    78           } 
     74          if (!empty($_POST)) return; 
    7975           
    80           try 
    81           { 
    82                $cache = new dcMemCache(DC_MC_CACHE_HOST, DC_MC_CACHE_PORT); 
    83                $ts = $cache->getPageMTime($_SERVER['REQUEST_URI']); 
     76          try { 
     77               $cache = new dcMemCache($_SERVER['REQUEST_URI'],DC_MC_CACHE_HOST,DC_MC_CACHE_PORT,DC_MC_CACHE_PERSISTENT); 
     78               $ts = $cache->getPageMTime(); 
    8479                
    85                if ($ts !== false) 
    86                { 
    87                     $mod_ts = array_merge(array($ts), $GLOBALS['mod_ts']); 
    88                     self::cache($mod_ts); 
    89                     if ($cache->fetchPage($_SERVER['REQUEST_URI'],$GLOBALS['core']->blog->upddt)) { 
     80               if ($ts !== false) { 
     81                    if (DC_MC_CACHE_SCHEDULED) { 
     82                         if ($core->blog->url == http::getSelfURI()) { 
     83                              $core->blog->publishScheduledEntries(); 
     84                         } 
     85                    } 
     86                    $blog_ts = $GLOBALS['core']->blog->upddt; 
     87                    dcMemCache::httpCache(array($ts,$blog_ts)); 
     88                    if ($cache->fetchPage($blog_ts)) { 
    9089                         exit; 
    9190                    } 
     
    9594     } 
    9695      
    97      public static function cache($mod_ts=array()) 
    98      {     
    99           rsort($mod_ts); 
    100           $ts = $mod_ts[0]; 
     96     public static function coreBlogAfterTriggerBlog($cur) 
     97     { 
     98          global $core; 
    10199           
    102           $since = NULL; 
    103           if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { 
    104                $since = $_SERVER['HTTP_IF_MODIFIED_SINCE']; 
    105                $since = preg_replace ('/^(.*)(Mon|Tue|Wed|Thu|Fri|Sat|Sun)(.*)(GMT)(.*)/', '$2$3 GMT', $since); 
    106                $since = strtotime($since); 
     100          try { 
     101               $cache = new dcMemCache(null,DC_MC_CACHE_HOST,DC_MC_CACHE_PORT,DC_MC_CACHE_PERSISTENT); 
     102               $host = preg_replace('#^(http://(?:.+?))/(.*)$#','$1',$core->blog->url); 
     103               $cache->setBlogMTime($host,$core->blog->id); 
    107104          } 
    108            
    109           # Common headers list 
    110           $headers[] = 'Last-Modified: '.gmdate('D, d M Y H:i:s',$ts).' GMT'; 
    111           $headers[] = 'Cache-Control: must-revalidate, max-age=0';         
    112           $headers[] = 'Pragma:'; 
    113            
    114           if ($since >= $ts) 
    115           { 
    116                http::head(304,'Not Modified'); 
    117                foreach ($headers as $v) { 
    118                     header($v); 
    119                } 
    120                exit; 
    121           } 
    122           else 
    123           { 
    124                header('Date: '.gmdate('D, d M Y H:i:s').' GMT'); 
    125                foreach ($headers as $v) { 
    126                     header($v); 
    127                } 
    128           } 
     105          catch (Exception $e) {} 
    129106     } 
    130107} 
  • plugins/memCache/class.cache.php

    r217 r982  
    22# -- BEGIN LICENSE BLOCK ---------------------------------- 
    33# 
    4 # This file is part of Dotclear 2. 
     4# This file is part of MemCache, a plugin for Dotclear 2. 
    55# 
    6 # Copyright (c) 2003-2008 Olivier Meunier and contributors 
     6# Copyright (c) 2008-2009 Alain Vagner, Pep and contributors 
    77# Licensed under the GPL version 2.0 license. 
    88# See LICENSE file or 
     
    1313class dcMemCache 
    1414{ 
    15      /** 
    16       * Memcache connexion 
    17       */ 
    18      private $con = null; 
    19      /** 
    20       * Memcache host 
    21       */   
    22      protected $cache_host; 
    23      /** 
    24       * Memcache port 
    25       */   
    26      protected $cache_port;    
    27      /** 
    28       * compression active ? 
    29       */        
    30      const compress = 0; 
    31      /** 
    32       * expiration? see memcached doc 
    33       */        
    34      const expiration = 0;     
     15     private   $mc = null; 
     16     protected $memcache_host; 
     17     protected $memcache_port; 
     18     protected $memcache_key; 
     19     protected $memcache_slot; 
     20 
     21     public function __construct($uri, $cache_host = 'localhost', $cache_port = 11211, $persist = false) 
     22     { 
     23          $this->mc = new Memcache(); 
     24          $mc_con_func = ($persist) ? 'pconnect' : 'connect'; 
     25          if (!$this->mc->$mc_con_func($cache_host, $cache_port)) { 
     26               throw new Exception('cmpCache: Unable to connect to memcached.'); 
     27          } 
     28          $this->memcache_host = $cache_host; 
     29          $this->memcache_port = $cache_port; 
     30          $this->memcache_key  = md5(http::getHost().$uri); 
     31     } 
     32 
     33     public function setBlogMTime($host,$blogid) 
     34     { 
     35          $key = md5('bmt:'.$host.':'.$blogid); 
     36          return $this->mc->set($key,time()); 
     37     } 
    3538      
    36      public function __construct($cache_host, $cache_port) 
     39     public function getBlogMTime($blogid) 
    3740     { 
    38           $this->con = new Memcache(); 
    39           if (!$this->con->connect($cache_host, $cache_port)) { 
    40                throw new Exception('MemCache: Unable to connect to memcached.');                
     41          $key = md5('bmt:'.http::getHost().':'.$blogid); 
     42          return $this->mc->get($key); 
     43     } 
     44      
     45     public function storePage($content_type,$content,$mtime) 
     46     { 
     47          $val = array($mtime,$content_type,$content); 
     48          if (!$this->mc->set($this->memcache_key,serialize($val),false,0)) { 
     49               throw new Exception('cmpCache: unable to set a value'); 
     50          } 
     51     } 
     52 
     53     public function fetchPage($mtime) 
     54     { 
     55          if ($result = $this->getSlotData()) { 
     56               $content_mtime = (integer)$result[0]; 
     57               $content_type  = $result[1]; 
     58               $content       = $result[2]; 
     59 
     60               if ($mtime > $content_mtime) { 
     61                    return false; 
     62               } 
     63 
     64               header('Content-Type: '.$content_type.'; charset=UTF-8'); 
     65               header('X-Dotclear-Cmp-Cache: true; mtime: '.date('c',$content_mtime)); 
     66               echo $content; 
     67               return true; 
     68          } 
     69          return false; 
     70     } 
     71 
     72     public function dropPage() 
     73     { 
     74          $this->memcache_slot = null; 
     75          if (!$this->mc->delete($this->memcache_key,0)) { 
     76               throw new Exception('cmpCache: unable to drop a page.'); 
    4177          } 
    4278     } 
    43       
    44      public function storePage($key,$content_type,$content,$mtime) 
     79 
     80     public function getPageMTime() 
    4581     { 
    46           $val = $mtime."|".$content_type."|".$content; 
    47      if (!$this->con->set(md5($key), $val, self::compress, self::expiration)) { 
    48           throw new Exception('MemCache: unable to set a value'); 
    49           } 
     82          if ($result = $this->getSlotData()) { 
     83               return (integer)$result[0]; 
     84          } 
     85          return false; 
    5086     } 
    51       
    52      public function fetchPage($key,$mtime) 
    53      {          
    54      $result = $this->con->get(md5($key)); 
    55      if (empty($result)) { 
    56           return false; 
    57      }     
    58      $lim = strpos($result, '|'); 
    59      $page_mtime = substr($result, 0, $lim); 
    60      $result = substr($result, $lim+1, strlen($result)); 
    61      $lim = strpos($result, '|'); 
    62      $content_type = substr($result, 0, $lim); 
    63      $content = substr($result, $lim+1, strlen($result)); 
    64       
    6587 
    66           if ($mtime > $page_mtime) { 
     88     protected function getSlotData() 
     89     { 
     90          if (!$this->memcache_slot) { 
     91               $this->memcache_slot = @unserialize($this->mc->get($this->memcache_key)); 
     92          } 
     93          if (!$this->memcache_slot || !(is_array($this->memcache_slot) && count($this->memcache_slot) == 3)) { 
    6794               return false; 
    6895          } 
     96          return $this->memcache_slot; 
     97     } 
     98 
     99     public static function httpCache($mod_ts=array()) 
     100     {     
     101          rsort($mod_ts); 
     102          $ts = $mod_ts[0]; 
    69103           
    70           header('Content-Type: '.$content_type.'; charset=UTF-8'); 
    71           header('X-Dotclear-Mem-Cache: true; mtime: '.$page_mtime); 
    72           echo $content; 
    73           return true; 
    74      } 
    75       
    76      public function dropPage($key) 
    77      {     
    78           if (!$this->con->delete(md5($key))) { 
    79                throw new Exception('Memcache: unable to drop a page.'); 
     104          $since = NULL; 
     105          if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { 
     106               $since = $_SERVER['HTTP_IF_MODIFIED_SINCE']; 
     107               $since = preg_replace ('/^(.*)(Mon|Tue|Wed|Thu|Fri|Sat|Sun)(.*)(GMT)(.*)/', '$2$3 GMT', $since); 
     108               $since = strtotime($since); 
    80109          } 
    81      } 
    82       
    83      public function getPageMTime($key) 
    84      {          
    85      $result = $this->con->get(md5($key)); 
    86      if (empty($result)) { 
    87           return false; 
    88      }     
    89      $lim = strpos($result, '|'); 
    90      return (int) substr($result, 0, $lim); 
     110           
     111          # Common headers list 
     112          $headers[] = 'Last-Modified: '.gmdate('D, d M Y H:i:s',$ts).' GMT'; 
     113          $headers[] = 'Cache-Control: must-revalidate, max-age=0';         
     114          $headers[] = 'Pragma:'; 
     115           
     116          if ($since >= $ts) 
     117          { 
     118               http::head(304,'Not Modified'); 
     119               foreach ($headers as $v) { 
     120                    header($v); 
     121               } 
     122               exit; 
     123          } 
     124          else 
     125          { 
     126               header('Date: '.gmdate('D, d M Y H:i:s').' GMT'); 
     127               foreach ($headers as $v) { 
     128                    header($v); 
     129               } 
     130          } 
    91131     } 
    92132} 
Note: See TracChangeset for help on using the changeset viewer.

Sites map