phpgroupware-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Phpgroupware-cvs] phpgwapi/inc class.shm.inc.php


From: Sigurd Nes
Subject: [Phpgroupware-cvs] phpgwapi/inc class.shm.inc.php
Date: Tue, 04 Jul 2006 13:06:12 +0000

CVSROOT:        /sources/phpgwapi
Module name:    phpgwapi
Changes by:     Sigurd Nes <sigurdne>   06/07/04 13:06:12

Added files:
        inc            : class.shm.inc.php 

Log message:
        Support for loading data into shared memory

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/phpgwapi/inc/class.shm.inc.php?cvsroot=phpgwapi&rev=1.1

Patches:
Index: class.shm.inc.php
===================================================================
RCS file: class.shm.inc.php
diff -N class.shm.inc.php
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ class.shm.inc.php   4 Jul 2006 13:06:12 -0000       1.1
@@ -0,0 +1,315 @@
+<?php
+/*
+                       Release under the GNU public license
+                       Copyright Adam Stevenson adamstevenson@ _no_spam_  
gmail.com (www.adamstevenson.net)
+                       If you use this script please send me an email, and let 
me know how it works for you,
+                       or any bugs you find. Also, if you want to link to my 
site I won't complain.
+
+                       Basically this is just a hash table over shared memory 
for caching php pages and 
+                       serialized objects.  You need to have php compiled with 
shared memory enabled.
+                       Simple garbage collection is implemented, but is only 
run when storing data in the
+                       cache and not returning pages to improve performance.
+
+                       It is very very fast.
+                       When caching was in place I was getting 55k byte pages 
returned over a local network
+                       in 0.02 ms, where before it was about 2.00 seconds.
+
+                       There is some support for debugging, but it is all 
commented out to gain a little
+                       more in performance.
+
+
+                       Note:  Versions of Windows previous to Windows 2000 do 
not support shared memory. 
+                       Under Windows, Shmop will only work when PHP is running 
as a web server module, 
+                       such as Apache or IIS (CLI and CGI will not work).
+
+                       Basic usage:
+
+                       For caching php rendered pages
+                               include 'mycached.php';
+                               do_cache();
+
+                       do_cache will automatically handle the garbage 
collection when storing pages.
+
+
+                       For caching php objects, you can use the store_value 
and get_value functions.
+
+                       store_value takes a key and value like any hashtable, 
and get_value just takes
+                       the key and returns the value if there is one.
+
+                       store_value('my_unique_key', $var);
+                       $var = get_value('my_unique_key');
+
+                       Directly accessing the store_value and get_value 
function does not do any
+                       garbage collection.  You can do this yourself by 
calling garbage_collection();
+                       in your scripts.
+
+
+                       To clear all the shared memory when testing, or what 
not you can use the unix
+                       command ipcs, and ipcrm.  Here is what I use which 
removes the shared memory
+                       segments, and also semaphores
+                       ipcs | cut -d" " -f2 | xargs -n1 ipcrm -s
+                       ipcs | cut -d" " -f2 | xargs -n1 ipcrm -m
+
+
+                       For even more robust caching, check out 
http://www.danga.com/memcached/
+
+*/
+       /**
+       * Handles shared memory
+       * @author Adam Stevenson <adamstevenson@ _no_spam_  gmail.com>
+       * @author Sigurd Nes <address@hidden>
+       * @copyright Copyright (C) 2003-2005 Free Software Foundation, Inc. 
http://www.fsf.org/
+       * @license http://www.gnu.org/licenses/gpl.html GNU General Public 
License
+       * @internal Development of this application was funded by 
http://www.bergen.kommune.no/bbb_/ekstern/
+       * @package phpgwapi
+       * @subpackage application
+       * @version $Id: class.shm.inc.php,v 1.1 2006/07/04 13:06:12 sigurdne 
Exp $
+       */
+
+       class shm
+       {
+               /**
+                * @var string $hashid the hash_table_key - example: 'lang_en'
+                */
+               var $hashid;
+               
+               function shm()
+               {
+
+                       DEFINE('CACHE_SECONDS', 60 * 60);
+                       DEFINE('LOG', false);
+                       DEFINE('LOG_FILE', '/tmp/debug.log' );
+                       DEFINE('HASH_PRIME', 2147483647); //2^31 -1
+                       DEFINE('LOCK', '/');
+               //      DEFINE('HASHID', 'hash_table_key');
+               }
+ 
+               function log_this($log_string)
+               {
+                       if(!LOG) return;
+                       $file = fopen(LOG_FILE, "a");
+                       fwrite($file, $log_string);
+                       fclose($file);
+                       return;
+               }
+
+               function delete_mem($id)
+               {
+                       if (!shmop_delete($id))
+                       {
+                               //$this->log_this("Couldn't mark shared memory 
block for deletion.\n");
+                       }
+               }
+
+               function &read_mem($id)
+               {
+                       return shmop_read($id, 0, shmop_size($id));
+               }
+
+               function write_mem($id, $data)
+               {
+                       if(shmop_size($id)< strlen($data))
+                       {
+                               return false;
+                       }
+                       
+                       if(!shmop_write($id, $data, 0))
+                       {
+                               //$this->log_this("Could not write to shared 
memory segment\n");
+                               return false;
+                       }
+                       return true;
+               }
+
+               function create_mem($key, $size)
+               {
+                       $id = @shmop_open($key, "n", 0644, $size);
+                       if (!$id) 
+                       {
+                               //$this->log_this("Couldn't create shared 
memory segment with key = $key\n");
+                       }
+                       return $id;
+               }
+
+               function mem_exist($key)
+               {
+                       if(!$id = @shmop_open($key, "a", 0644, 100))
+                       {
+                               //$this->log_this("Couldn't find shared memory 
segment with key = $key\n");
+                               return 0;
+                       }
+                       //$this->log_this("Memory segment exists with key = 
$key\n");
+                       return $id;
+               }
+
+               function close_mem($id)
+               {
+                       if($id!=0) shmop_close($id);
+               }
+
+               function &get_value($key)
+               {
+                       $hash_id =& $this->hash($key);
+                       $value = array();
+                       $id =& $this->mem_exist($hash_id);
+                       while($value['key']!=$key)
+                       {
+                               if($id!=0)
+                               {
+                                       $value =& 
unserialize($this->read_mem($id));
+                                       if($value['key']!=$key) $id =& 
$this->mem_exist($this->hash($hash_id));
+                               }
+                               else
+                               {
+                                       //$this->log_this("no key in hash 
table\n");
+                                       $this->close_mem($id);
+                                       return "";
+                               }
+                       }
+                       $this->close_mem($id);
+                       return $value['value'];
+               }
+
+               function store_value($key,$value)
+               {
+                       $SHM_KEY = ftok(LOCK, 'R');
+                       $shmid = @sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
+                       sem_acquire($shmid);
+                       $hash_id = $this->hash($key);
+                       $store_value = array();
+                       $store_value['key'] = trim($key);
+                       $store_value['value'] = $value;
+                       $store_value['time'] = time();
+                       $id = $this->mem_exist($hash_id);
+                       while($id!=0)
+                       {
+                               $value = unserialize($this->read_mem($id));
+                               if($value['key']==$key)
+                               {
+                                       //$this->log_this("Key " . $key . "   
$hash_id(" . dechex($hash_id) .") already in hash table, replacing with new 
contents\n");
+                                       $this->delete_mem($id);
+                                       $this->close_mem($id);
+                                       $contents = serialize($store_value);
+                                       $id = 
$this->create_mem($hash_id,strlen($contents));
+                                       $this->write_mem($id, $contents); // 
place into memory
+                                       $this->close_mem($id);
+                                       sem_release($shmid);
+                                       return $hash_id;
+                               }
+                               $this->close_mem($id);
+                               //$this->log_this("Collision while trying to 
store key=$key in hash table\n");
+                               $hash_id = $this->hash($hash_id);
+                               $id = $this->mem_exist($hash_id);
+                       }
+                       $contents = serialize($store_value);
+                       $id = $this->create_mem($hash_id,strlen($contents));
+                       $this->write_mem($id, &$contents); // place into memory
+                       $this->close_mem($id);
+                       sem_release($shmid);
+                       return $hash_id;
+               }
+
+               function update_keys($key, $id)
+               {
+                       $SHM_KEY = ftok(LOCK, 'R');
+                       $shmid = @sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
+                       sem_acquire($shmid);
+                       $temp =& $this->get_value($this->hashid);
+                       $temp[$key] = array('shmid' => $id, 'time' => time());
+                       $this->store_value($this->hashid,$temp);
+                       sem_release($shmid);
+               }
+
+               function &hash($hash_string)
+               {
+                       $hash =& fmod(hexdec(md5($hash_string)), HASH_PRIME);
+                       //$this->log_this("Hashing " . $hash_string . " to " . 
$hash . "\n"); 
+                       return $hash;
+               }
+
+               function cache_end($contents)
+               {
+                       if(trim($contents))
+                       {
+                               $datasize = strlen($contents);
+                               $hash_string = 
"http://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"].serialize($_POST);
+                               $shmid = 
$this->store_value($hash_string,$contents);
+                               $this->update_keys($hash_string,$shmid);
+                       }
+                       return $contents; //display
+               }
+
+               function delete_key($key)
+               {
+                       $SHM_KEY = ftok(LOCK, 'R');
+                       $shmid = @sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
+
+                       sem_acquire($shmid);
+                       $data = $this->get_value($key);
+
+                       if(isset($data))
+                       {
+                               $v = $data[$key];
+                               $id =& $this->mem_exist($this->hash($hash_id));
+                               $this->delete_mem($id);
+                               $this->close_mem($id);
+                               unset($data);
+                               $this->store_value($key, $data);
+                       }
+                       sem_release($shmid);
+               }
+
+               function clear_cache()
+               {
+                       $SHM_KEY = ftok(LOCK, 'R');
+                       $shmid = @sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
+                       sem_acquire($shmid);
+                       $data = $this->get_value($this->hashid);
+                       _debug_array($data);
+                       foreach ($data as $k => $v)
+                       {
+                               $id = $this->mem_exist($v['shmid']);
+                               $this->delete_mem($id);
+                               $this->close_mem($id);
+                       }
+                       $data = array();
+                       $this->store_value($this->hashid, $data);
+                       sem_release($shmid);
+               }
+
+
+               function garbage_collection()
+               {
+                       $SHM_KEY = ftok(LOCK, 'R');
+                       $shmid = @sem_get($SHM_KEY, 1024, 0644 | IPC_CREAT);
+                       sem_acquire($shmid);
+                       $data = $this->get_value($this->hashid);
+                       foreach ($data as $k => $v)
+                       {
+                               if(time() - $v['time'] > CACHE_SECONDS)
+                               {
+                                       //$this->log_this("garbage collection 
found expired key $k, value $v[shmid] in hash table... deleting\n");
+                                       $id = $this->mem_exist($v['shmid']);
+                                       $this->delete_mem($id);
+                                       $this->close_mem($id);
+                                       unset($data[$k]);
+                               }
+                               $this->store_value($this->hashid, $data);
+                       }
+                       sem_release($shmid);
+               }
+
+               function do_cache()
+               {
+                       $key = 
"http://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"].serialize($_POST);
+                       $contents =& $this->get_value($key);
+                       if($contents)
+                       {
+                               //$this->log_this("Cache hit for " . $key . 
"\n");
+                               print $contents;
+                               exit;
+                       }
+                       $this->garbage_collection();
+                       ob_start("cache_end"); // callback
+               }
+       }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]