00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00018 final class SharedMemory extends SelectivePeer
00019 {
00020 const INDEX_SEGMENT = 12345678;
00021
00022 const DEFAULT_SEGMENT_SIZE = 4194304;
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()
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
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
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
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
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
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
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 ?>