shm.php

来自「视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.」· PHP 代码 · 共 277 行

PHP
277
字号
<?php// +----------------------------------------------------------------------+// | PEAR :: Cache                                                        |// +----------------------------------------------------------------------+// | Copyright (c) 1997-2003 The PHP Group                                |// +----------------------------------------------------------------------+// | This source file is subject to version 2.0 of the PHP license,       |// | that is bundled with this package in the file LICENSE, and is        |// | available at through the world-wide-web at                           |// | http://www.php.net/license/2_02.txt.                                 |// | If you did not receive a copy of the PHP license and are unable to   |// | obtain it through the world-wide-web, please send a note to          |// | license@php.net so we can mail you a copy immediately.               |// +----------------------------------------------------------------------+// | Authors: Ulf Wendel <ulf.wendel@phpdoc.de>                           |// |          Sebastian Bergmann <sb@sebastian-bergmann.de>               |// +----------------------------------------------------------------------+//// $Id: shm.php,v 1.3 2003/01/04 11:54:46 mj Exp $require_once 'Cache/Container.php';/*** Stores cache data into shared memory.** Well, this is not a very efficient implementation. Indeed it's much * slower than the file container as far as my tests showed. Files are * cached by most operating systems and it will be hard to write a faster * caching algorithm using PHP.** @author   Ulf Wendel <ulf.wendel@phpdoc.de>* @version  $Id: shm.php,v 1.3 2003/01/04 11:54:46 mj Exp $* @package  Cache*/class Cache_Container_shm extends Cache_Container {    /**    * Key of the semaphore used to sync the SHM access    *     * @var  int    */    var $sem_key = NULL;    /**    * Permissions of the semaphore used to sync the SHM access    *     * @var  int    */    var $sem_perm = 0644;    /**    * Semaphore handler    *     * @var  resource    */    var $sem_id = NULL;    /**    * Key of the shared memory block used to store cache data    *    * @var  int    */    var $shm_key = NULL;    /**    * Size of the shared memory block used    *     * Note: the container does only use _one_ shm block no more!    *     * @var  int    */            var $shm_size = 131072;    /**    * Permissions of the shared memory block    *     * @var  int    */    var $shm_perm = 0644;    /**    * Shared memory handler    *     * @var resource    */    var $shm_id = NULL;    /**    * Hash of cache entries    *     * Used by the garbage collection to find old entries.    *    * @var  array    */    var $entries = array();    /**    * Number of bytes consumed by the cache    *     * @var  int    */    var $total_size = 0;    /**    * Creates a shared memory container    *    * @param array    shm_key, sem_key, shm_size, sem_perm, shm_perm    */        function Cache_Container_shm($options = '') {        if (is_array($options))            $this->setOptions($options, array_merge($this->allowed_options,                                                     array('shm_key',  'sem_key',                                                           'shm_size', 'sem_perm',                                                          'shm_perm'                                                         )                                        )                               );        // Cache::Container high- and lowwater defaults should be overridden if        // not already done by the user        if (!isset($options['highwater']))             $this->highwater = round(0.75 * 131072);        if (!isset($options['lowwater']))            $this->lowwater = round(0.5 * 131072);        if (!isset($options['shm_size']))            $this->shm_size = 131072;        //get SHM and Semaphore handles        if (!($this->shm_id = shmop_open($this->shm_key, 'c', $this->shm_perm, $this->shm_size)))            new Cache_Error("Can't open SHM segment '{$this->shm_key}', size '{$this->shm_size}'.",                            __FILE__,                            __LINE__                           );        if (!($this->sem_id = sem_get($this->sem_key, 1, $this->sem_perm)))            new Cache_Error("Can't get semaphore '{$this->sem_key}' using perms '{$this->sem_perm}'.",                            __FILE__,                            __LINE__                           );    } // end constructor    function fetch($id, $group) {        sem_acquire($this->sem_id);        $cachedata = shmop_read($this->shm_id, 0, $this->shm_size);        sem_release($this->sem_id);        $cachedata = $this->decode($cachedata);        if (!isset($cachedata[$group][$id]))            return array(NULL, NULL, NULL);        else             $cachedata = $cachedata[$group][$id];        return array($cachedata['expire'],                     $cachedata['cachedata'],                     $cachedata['userdata']                    );    } // end func fetch    function save($id, $data, $expire, $group, $userdata) {        $this->flushPreload($id, $group);        sem_acquire($this->sem_id);        $cachedata = $this->decode(shmop_read($this->shm_id, 0, $this->shm_size));        $cachedata[$group][$id] = array('expire'    => $this->getExpiresAbsolute($expire),                                        'cachedata' => $data,                                        'userdata'  => $userdata,                                        'changed'   => time()                                       );        if (strlen($newdata = $this->encode($cachedata)) > $this->shm_size)            $cachedata = $this->garbageCollection(time(), $cachedata);        shmop_write($this->shm_id, $newdata, 0);        sem_release($this->sem_id);        return true;    } // end func save    function remove($id, $group) {        $this->flushPreload($id, $group);        sem_acquire($this->sem_id);        $cachedata = $this->decode(shmop_read($this->shm_id, 0, $this->shm_size));        unset($cachedata[$group][$id]);        shmop_write($this->shm_id, $this->encode($cachedata), 0);        sem_release($this->sem_id);    } // end func remove    function flush($group = '') {        $this->flushPreload();        sem_acquire($this->sem_id);        shmop_write($this->shm_id, $this->encode(array()), 0);        sem_release($this->sem_id);    } // end func flush    function idExists($id, $group) {        sem_acquire($this->sem_id);        $cachedata = shm_read($this->shm_id, 0, $this->shm_size);        sem_release($this->sem_id);        $cachedata = $this->decode($cachedata);        return isset($cachedata[$group][$id]);    } // end func isExists    function garbageCollection($maxlifetime, $cachedata = array()) {        if ($lock = empty($cachedata)) {            sem_acquire($this->sem_id);            $cachedata = $this->decode(shmop_read($this->shm_id, 0, $this->shm_size));        }        $this->doGarbageCollection($maxlifetime, &$cachedata);        if ($this->total_size > $this->highwater) {            krsort($this->entries);            reset($this->entries);            while ($this->total_size > $this->lowwater && list($size, $entries) = each($this->entries)) {                reset($entries);                while (list($k, $entry) = each($entries)) {                    unset($cachedata[$entry['group']][$entry['id']]);                    $this->total_size -= $size;                }            }        }        if ($lock)            sem_release($this->sem_id);        $this->entries = array();        $this->total_size = 0;        return $cachedata;               } // end func garbageCollection    function doGarbageCollection($maxlifetime, &$cachedata) {        $changed = time() - $maxlifetime;        $removed = 0;        reset($cachedata);        while (list($group, $groupdata) = each($cachedata)) {            reset($groupdata);            while (list($id, $data) = each($groupdata)) {                if ($data['expire'] < time() || $data['changed'] < $changed) {                    unset($cachedata[$group][$id]);                }            }            // ugly but simple to implement :/            $size = strlen($this->encode($data));            $this->entries[$size][] = array('group' => $group,                                            'id'    => $id                                           );            $this->total_size += $size;        }        return $removed;    }  // end func doGarbageCollection} // end class Cache_Container_shm?>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?