Go to the documentation of this file.00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00017 final class SharedMemory extends SelectivePeer
00018 {
00019 const INDEX_SEGMENT = 12345678;
00020
00021 const DEFAULT_SEGMENT_SIZE = 4194304;
00022
00023 private $defaultSize = null;
00024 private $customSized = array();
00025
00026 private static $attached = array();
00027
00031 public static function create(
00032 $defaultSize = self::DEFAULT_SEGMENT_SIZE,
00033 $customSized = array()
00034 )
00035 {
00036 return new self($defaultSize, $customSized);
00037 }
00038
00042 public function __construct(
00043 $defaultSize = self::DEFAULT_SEGMENT_SIZE,
00044 $customSized = array()
00045 )
00046 {
00047 $this->defaultSize = $defaultSize;
00048 $this->customSized = $customSized;
00049 }
00050
00051 public function __destruct()
00052 {
00053 foreach (self::$attached as $segment)
00054 shm_detach($segment);
00055
00056
00057 $segment = shm_attach(
00058 self::INDEX_SEGMENT, self::DEFAULT_SEGMENT_SIZE, ONPHP_IPC_PERMS
00059 );
00060
00061 try {
00062 $index = shm_get_var($segment, 1);
00063 } catch (BaseException $e) {
00064 $index = array();
00065 }
00066
00067 try {
00068 shm_put_var(
00069 $segment,
00070 1,
00071 array_unique(
00072 array_merge(
00073 $index, array_keys(self::$attached)
00074 )
00075 )
00076 );
00077 } catch (BaseException $e) {}
00078
00079 try {
00080 shm_detach($segment);
00081 } catch (BaseException $e) {}
00082 }
00083
00084 public function increment($key, $value)
00085 {
00086 if (null !== ($current = $this->get($key))) {
00087 $this->set($key, $current += $value);
00088 return $current;
00089 }
00090
00091 return null;
00092 }
00093
00094 public function decrement($key, $value)
00095 {
00096 if (null !== ($current = $this->get($key))) {
00097 $this->set($key, $current -= $value);
00098 return $current;
00099 }
00100
00101 return null;
00102 }
00103
00104 public function get($key)
00105 {
00106 $segment = $this->getSegment();
00107
00108 $key = $this->stringToInt($key);
00109
00110 try {
00111 $stored = shm_get_var($segment, $key);
00112
00113 if ($stored['expires'] <= time()) {
00114 $this->delete($key);
00115 return null;
00116 }
00117
00118 return $this->restoreData($stored['value']);
00119
00120 } catch (BaseException $e) {
00121
00122 return null;
00123 }
00124
00125 Assert::isUnreachable();
00126 }
00127
00128 public function delete($key)
00129 {
00130 try {
00131 return shm_remove_var(
00132 $this->getSegment(), $this->stringToInt($key)
00133 );
00134 } catch (BaseException $e) {
00135 return false;
00136 }
00137
00138 Assert::isUnreachable();
00139 }
00140
00141 public function isAlive()
00142 {
00143
00144 return true;
00145 }
00146
00150 public function clean()
00151 {
00152 $segment = shm_attach(self::INDEX_SEGMENT);
00153
00154 try {
00155 $index = shm_get_var($segment, 1);
00156 } catch (BaseException $e) {
00157
00158 return null;
00159 }
00160
00161 foreach ($index as $key) {
00162 try {
00163 $sem = shm_attach($this->stringToInt($key));
00164 shm_remove($sem);
00165 } catch (BaseException $e) {
00166
00167 }
00168 }
00169
00170 shm_remove($segment);
00171
00172 return parent::clean();
00173 }
00174
00175 public function append($key, $data)
00176 {
00177 $segment = $this->getSegment();
00178
00179 $key = $this->stringToInt($key);
00180
00181 try {
00182 $stored = shm_get_var($segment, $key);
00183
00184 if ($stored['expires'] <= time()) {
00185 $this->delete($key);
00186 return false;
00187 }
00188
00189 return $this->store(
00190 'ignored',
00191 $key,
00192 $stored['value'].$data,
00193 $stored['expires']
00194 );
00195 } catch (BaseException $e) {
00196
00197 return false;
00198 }
00199 }
00200
00201 protected function store($action, $key, $value, $expires = 0)
00202 {
00203 $segment = $this->getSegment();
00204
00205 if ($expires < parent::TIME_SWITCH)
00206 $expires += time();
00207
00208 try {
00209 shm_put_var(
00210 $segment,
00211 $this->stringToInt($key),
00212 array(
00213 'value' => $this->prepareData($value),
00214 'expires' => $expires
00215 )
00216 );
00217
00218 return true;
00219
00220 } catch (BaseException $e) {
00221
00222 return false;
00223 }
00224
00225 Assert::isUnreachable();
00226 }
00227
00228 private function getSegment()
00229 {
00230 $class = $this->getClassName();
00231
00232 if (!isset(self::$attached[$class]))
00233 self::$attached[$class] = shm_attach(
00234 $this->stringToInt($class),
00235 isset($this->customSized[$class])
00236 ? $this->customSized[$class]
00237 : $this->defaultSize,
00238 ONPHP_IPC_PERMS
00239 );
00240
00241 return self::$attached[$class];
00242 }
00243
00244 private function stringToInt($string)
00245 {
00246 return hexdec(substr(md5($string), 0, 8));
00247 }
00248 }
00249 ?>