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

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