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

Source for file shm.php

Documentation is available at shm.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. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: shm.php 316194 2011-09-05 20:35:25Z cweiske $
  20.  
  21. require_once 'Cache/Container.php';
  22.  
  23. /**
  24. * Stores cache data into shared memory.
  25. *
  26. * Well, this is not a very efficient implementation. Indeed it's much
  27. * slower than the file container as far as my tests showed. Files are
  28. * cached by most operating systems and it will be hard to write a faster
  29. * caching algorithm using PHP.
  30. *
  31. @author   Ulf Wendel <ulf.wendel@phpdoc.de>
  32. @version  $Id: shm.php 316194 2011-09-05 20:35:25Z cweiske $
  33. @package  Cache
  34. */
  35. {
  36.     /**
  37.     * Key of the semaphore used to sync the SHM access
  38.     * 
  39.     * @var  int 
  40.     */
  41.     var $sem_key = null;
  42.  
  43.     /**
  44.     * Permissions of the semaphore used to sync the SHM access
  45.     * 
  46.     * @var  int 
  47.     */
  48.     var $sem_perm = 0644;
  49.  
  50.     /**
  51.     * Semaphore handler
  52.     * 
  53.     * @var  resource 
  54.     */
  55.     var $sem_id = null;
  56.  
  57.     /**
  58.     * Key of the shared memory block used to store cache data
  59.     *
  60.     * @var  int 
  61.     */
  62.     var $shm_key = null;
  63.  
  64.     /**
  65.     * Size of the shared memory block used
  66.     * 
  67.     * Note: the container does only use _one_ shm block no more!
  68.     * 
  69.     * @var  int 
  70.     */        
  71.     var $shm_size = 131072;
  72.  
  73.     /**
  74.     * Permissions of the shared memory block
  75.     * 
  76.     * @var  int 
  77.     */
  78.     var $shm_perm = 0644;
  79.  
  80.     /**
  81.     * Shared memory handler
  82.     * 
  83.     * @var resource 
  84.     */
  85.     var $shm_id = null;
  86.  
  87.     /**
  88.     * Hash of cache entries
  89.     * 
  90.     * Used by the garbage collection to find old entries.
  91.     *
  92.     * @var  array 
  93.     */
  94.     var $entries = array();
  95.  
  96.     /**
  97.     * Number of bytes consumed by the cache
  98.     * 
  99.     * @var  int 
  100.     */
  101.     var $total_size = 0;
  102.  
  103.     /**
  104.     * Creates a shared memory container
  105.     *
  106.     * @param array    shm_key, sem_key, shm_size, sem_perm, shm_perm
  107.     */    
  108.     function Cache_Container_shm($options = null)
  109.     {
  110.         $this->setAllowedOptions(
  111.             array('shm_key',  'sem_key'
  112.                   'shm_size''sem_perm',
  113.                   'shm_perm'
  114.                  )
  115.         );
  116.         $this->setOptions($options)
  117.  
  118.         // Cache::Container high- and lowwater defaults should be overridden if
  119.         // not already done by the user
  120.         if (!$this->hasBeenSet('highwater')) 
  121.             $this->highwater = round(0.75 * 131072);
  122.         }
  123.         if (!$this->hasBeenSet('lowwater')) {
  124.             $this->lowwater = round(0.5 * 131072);
  125.         }
  126.         if (!$this->hasBeenSet('shm_size')) {
  127.             $this->shm_size = 131072;
  128.         }
  129.         //get SHM and Semaphore handles
  130.         if (!($this->shm_id = shmop_open($this->shm_key'c'$this->shm_perm$this->shm_size))) {
  131.             new Cache_Error("Can't open SHM segment '{$this->shm_key}', size '{$this->shm_size}'.",
  132.                             __FILE__,
  133.                             __LINE__
  134.                            );
  135.         }
  136.         if (!($this->sem_id = sem_get($this->sem_key1$this->sem_perm))) {
  137.             new Cache_Error("Can't get semaphore '{$this->sem_key}' using perms '{$this->sem_perm}'.",
  138.                             __FILE__,
  139.                             __LINE__
  140.                            );
  141.         }
  142.     } // end constructor
  143.     function fetch($id, $group)
  144.     {
  145.         sem_acquire($this->sem_id);
  146.  
  147.         $cachedata = shmop_read($this->shm_id0$this->shm_size);
  148.  
  149.         sem_release($this->sem_id);
  150.  
  151.         $cachedata $this->decode($cachedata);
  152.  
  153.         if (!isset($cachedata[$group][$id])) {
  154.             return array(null, null, null);
  155.         } else {
  156.             $cachedata = $cachedata[$group][$id];
  157.         }
  158.         return array($cachedata['expire'],
  159.                      $cachedata['cachedata'],
  160.                      $cachedata['userdata']
  161.                     );
  162.     } // end func fetch
  163.     function save($id, $data, $expire, $group, $userdata)
  164.     {
  165.         $this->flushPreload($id$group);
  166.  
  167.         sem_acquire($this->sem_id);
  168.  
  169.         $cachedata $this->decode(shmop_read($this->shm_id0$this->shm_size));
  170.         $cachedata[$group][$id= array('expire'    => $this->getExpiresAbsolute($expire),
  171.                                         'cachedata' => $data,
  172.                                         'userdata'  => $userdata,
  173.                                         'changed'   => time()
  174.                                        );
  175.  
  176.         if (strlen($newdata $this->encode($cachedata)) $this->shm_size{
  177.             $cachedata = $this->garbageCollection(time()$cachedata);
  178.         }
  179.         shmop_write($this->shm_id$newdata0);
  180.  
  181.         sem_release($this->sem_id);
  182.  
  183.         return true;
  184.     } // end func save
  185.     function remove($id, $group)
  186.     {
  187.         $this->flushPreload($id$group);
  188.  
  189.         sem_acquire($this->sem_id);
  190.  
  191.         $cachedata $this->decode(shmop_read($this->shm_id0$this->shm_size));
  192.         unset($cachedata[$group][$id]);
  193.         shmop_write($this->shm_id$this->encode($cachedata)0);
  194.  
  195.         sem_release($this->sem_id);
  196.     } // end func remove
  197.     function flush($group = '')
  198.     {
  199.         $this->flushPreload();
  200.  
  201.         sem_acquire($this->sem_id);
  202.  
  203.         shmop_write($this->shm_id$this->encode(array())0);
  204.  
  205.         sem_release($this->sem_id);
  206.     } // end func flush
  207.     function idExists($id, $group)
  208.     {
  209.         sem_acquire($this->sem_id);
  210.  
  211.         $cachedata = shm_read($this->shm_id0$this->shm_size);
  212.  
  213.         sem_release($this->sem_id);
  214.  
  215.         $cachedata $this->decode($cachedata);
  216.  
  217.         return isset($cachedata[$group][$id]);
  218.     } // end func isExists
  219.     function garbageCollection($maxlifetime, $cachedata = array())
  220.     {
  221.         if ($lock = empty($cachedata)) {
  222.             sem_acquire($this->sem_id);
  223.             $cachedata $this->decode(shmop_read($this->shm_id0$this->shm_size));
  224.         }
  225.  
  226.         $this->doGarbageCollection($maxlifetime$cachedata);
  227.         if ($this->total_size > $this->highwater{
  228.             krsort($this->entries);
  229.             reset($this->entries);
  230.  
  231.             while ($this->total_size > $this->lowwater && list($size$entries= each($this->entries)) {
  232.                 reset($entries);
  233.  
  234.                 while (list($k, $entry) = each($entries)) {
  235.                     unset($cachedata[$entry['group']][$entry['id']]);
  236.                     $this->total_size -= $size;
  237.                 }
  238.             }
  239.         }
  240.  
  241.         if ($lock) {
  242.             sem_release($this->sem_id);
  243.         }
  244.         $this->entries = array();
  245.         $this->total_size = 0;
  246.  
  247.         return $cachedata;           
  248.     } // end func garbageCollection
  249.     function doGarbageCollection($maxlifetime, &$cachedata)
  250.     {
  251.         $changed = time() - $maxlifetime;
  252.         $removed = 0;
  253.  
  254.         reset($cachedata);
  255.  
  256.         while (list($group, $groupdata) = each($cachedata)) {
  257.             reset($groupdata);
  258.  
  259.             while (list($id, $data) = each($groupdata)) {
  260.                 if ($data['expire'] < time() || $data['changed'] < $changed) {
  261.                     unset($cachedata[$group][$id]);
  262.                 }
  263.             }
  264.  
  265.             // ugly but simple to implement :/
  266.             $size = strlen($this->encode($data));
  267.             $this->entries[$size][= array(
  268.                 'group' => $group,
  269.                 'id'    => $id
  270.             );
  271.  
  272.             $this->total_size += $size;
  273.         }
  274.  
  275.         return $removed;
  276.     }  // end func doGarbageCollection
  277. } // end class Cache_Container_shm

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