SharedMemory.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2005-2007 by Konstantin V. Arkhipov                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License as        *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  ***************************************************************************/
00011 /* $Id: SharedMemory.class.php 4687 2007-12-09 18:57:18Z voxus $ */
00012 
00018     final class SharedMemory extends SelectivePeer
00019     {
00020         const INDEX_SEGMENT         = 12345678;
00021         
00022         const DEFAULT_SEGMENT_SIZE  = 4194304; // 128^3 * 2
00023         
00024         private $defaultSize = null;
00025         private $customSized = array();
00026         
00027         private static $attached = array();
00028         
00032         public static function create(
00033             $defaultSize = self::DEFAULT_SEGMENT_SIZE,
00034             $customSized = array()
00035         )
00036         {
00037             return new self($defaultSize, $customSized);
00038         }
00039         
00043         public function __construct(
00044             $defaultSize = self::DEFAULT_SEGMENT_SIZE,
00045             $customSized = array() // 'className' => segmentSizeInBytes
00046         )
00047         {
00048             $this->defaultSize = $defaultSize;
00049             $this->customSized = $customSized;
00050         }
00051         
00052         public function __destruct()
00053         {
00054             foreach (self::$attached as $segment)
00055                 shm_detach($segment);
00056             
00057             // sync classes
00058             $segment = shm_attach(
00059                 self::INDEX_SEGMENT, self::DEFAULT_SEGMENT_SIZE, ONPHP_IPC_PERMS
00060             );
00061             
00062             try {
00063                 $index = shm_get_var($segment, 1);
00064             } catch (BaseException $e) {
00065                 $index = array();
00066             }
00067             
00068             try {
00069                 shm_put_var(
00070                     $segment,
00071                     1,
00072                     array_unique(
00073                         array_merge(
00074                             $index, array_keys(self::$attached)
00075                         )
00076                     )
00077                 );
00078             } catch (BaseException $e) {/*_*/}
00079             
00080             try {
00081                 shm_detach($segment);
00082             } catch (BaseException $e) {/*_*/}
00083         }
00084         
00085         public function get($key)
00086         {
00087             $segment = $this->getSegment();
00088             
00089             $key = $this->stringToInt($key);
00090             
00091             try {
00092                 $stored = shm_get_var($segment, $key);
00093                 
00094                 if ($stored['expires'] <= time()) {
00095                     $this->delete($key);
00096                     return null;
00097                 }
00098                 
00099                 return $this->restoreData($stored['value']);
00100                 
00101             } catch (BaseException $e) {
00102                 // not found there
00103                 return null;
00104             }
00105             
00106             Assert::isUnreachable();
00107         }
00108         
00109         public function delete($key)
00110         {
00111             try {
00112                 return shm_remove_var(
00113                     $this->getSegment(), $this->stringToInt($key)
00114                 );
00115             } catch (BaseException $e) {
00116                 return false;
00117             }
00118             
00119             Assert::isUnreachable();
00120         }
00121         
00122         public function isAlive()
00123         {
00124             // any better idea how to detect shm-availability?
00125             return true;
00126         }
00127         
00131         public function clean()
00132         {
00133             $segment = shm_attach(self::INDEX_SEGMENT);
00134             
00135             try {
00136                 $index = shm_get_var($segment, 1);
00137             } catch (BaseException $e) {
00138                 // nothing to clean
00139                 return null;
00140             }
00141             
00142             foreach ($index as $key) {
00143                 try {
00144                     $sem = shm_attach($this->stringToInt($key));
00145                     shm_remove($sem);
00146                 } catch (BaseException $e) {
00147                     // already removed, probably
00148                 }
00149             }
00150             
00151             shm_remove($segment);
00152             
00153             return parent::clean();
00154         }
00155         
00156         protected function store($action, $key, &$value, $expires = 0)
00157         {
00158             $segment = $this->getSegment();
00159             
00160             if ($expires < parent::TIME_SWITCH)
00161                 $expires += time();
00162             
00163             try {
00164                 shm_put_var(
00165                     $segment,
00166                     $this->stringToInt($key),
00167                     array(
00168                         'value' => $this->prepareData($value),
00169                         'expires' => $expires
00170                     )
00171                 );
00172                 
00173                 return true;
00174                 
00175             } catch (BaseException $e) {
00176                 // not enough memory
00177                 return false;
00178             }
00179             
00180             Assert::isUnreachable();
00181         }
00182         
00183         private function getSegment()
00184         {
00185             $class = $this->getClassName();
00186             
00187             if (!isset(self::$attached[$class]))
00188                 self::$attached[$class] = shm_attach(
00189                     $this->stringToInt($class),
00190                     isset($this->customSized[$class])
00191                         ? $this->customSized[$class]
00192                         : $this->defaultSize,
00193                     ONPHP_IPC_PERMS
00194                 );
00195             
00196             return self::$attached[$class];
00197         }
00198         
00199         private function stringToInt($string)
00200         {
00201             return hexdec(substr(md5($string), 0, 8));
00202         }
00203     }
00204 ?>

Generated on Sun Dec 9 21:56:23 2007 for onPHP by  doxygen 1.5.4