[ Index ] |
PHP Cross Reference of phpBB-3.1.12-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 * This file is part of the Symfony package. 5 * 6 * (c) Fabien Potencier <fabien@symfony.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12 namespace Symfony\Component\HttpKernel\Profiler; 13 14 /** 15 * RedisProfilerStorage stores profiling information in Redis. 16 * 17 * @author Andrej Hudec <pulzarraider@gmail.com> 18 * @author Stephane PY <py.stephane1@gmail.com> 19 */ 20 class RedisProfilerStorage implements ProfilerStorageInterface 21 { 22 const TOKEN_PREFIX = 'sf_profiler_'; 23 24 const REDIS_OPT_SERIALIZER = 1; 25 const REDIS_OPT_PREFIX = 2; 26 const REDIS_SERIALIZER_NONE = 0; 27 const REDIS_SERIALIZER_PHP = 1; 28 29 protected $dsn; 30 protected $lifetime; 31 32 /** 33 * @var \Redis 34 */ 35 private $redis; 36 37 /** 38 * Constructor. 39 * 40 * @param string $dsn A data source name 41 * @param string $username Not used 42 * @param string $password Not used 43 * @param int $lifetime The lifetime to use for the purge 44 */ 45 public function __construct($dsn, $username = '', $password = '', $lifetime = 86400) 46 { 47 $this->dsn = $dsn; 48 $this->lifetime = (int) $lifetime; 49 } 50 51 /** 52 * {@inheritdoc} 53 */ 54 public function find($ip, $url, $limit, $method, $start = null, $end = null) 55 { 56 $indexName = $this->getIndexName(); 57 58 if (!$indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE)) { 59 return array(); 60 } 61 62 $profileList = array_reverse(explode("\n", $indexContent)); 63 $result = array(); 64 65 foreach ($profileList as $item) { 66 if ($limit === 0) { 67 break; 68 } 69 70 if ($item == '') { 71 continue; 72 } 73 74 list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = explode("\t", $item, 6); 75 76 $itemTime = (int) $itemTime; 77 78 if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) { 79 continue; 80 } 81 82 if (!empty($start) && $itemTime < $start) { 83 continue; 84 } 85 86 if (!empty($end) && $itemTime > $end) { 87 continue; 88 } 89 90 $result[] = array( 91 'token' => $itemToken, 92 'ip' => $itemIp, 93 'method' => $itemMethod, 94 'url' => $itemUrl, 95 'time' => $itemTime, 96 'parent' => $itemParent, 97 ); 98 --$limit; 99 } 100 101 return $result; 102 } 103 104 /** 105 * {@inheritdoc} 106 */ 107 public function purge() 108 { 109 // delete only items from index 110 $indexName = $this->getIndexName(); 111 112 $indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE); 113 114 if (!$indexContent) { 115 return false; 116 } 117 118 $profileList = explode("\n", $indexContent); 119 120 $result = array(); 121 122 foreach ($profileList as $item) { 123 if ($item == '') { 124 continue; 125 } 126 127 if (false !== $pos = strpos($item, "\t")) { 128 $result[] = $this->getItemName(substr($item, 0, $pos)); 129 } 130 } 131 132 $result[] = $indexName; 133 134 return $this->delete($result); 135 } 136 137 /** 138 * {@inheritdoc} 139 */ 140 public function read($token) 141 { 142 if (empty($token)) { 143 return false; 144 } 145 146 $profile = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP); 147 148 if (false !== $profile) { 149 $profile = $this->createProfileFromData($token, $profile); 150 } 151 152 return $profile; 153 } 154 155 /** 156 * {@inheritdoc} 157 */ 158 public function write(Profile $profile) 159 { 160 $data = array( 161 'token' => $profile->getToken(), 162 'parent' => $profile->getParentToken(), 163 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()), 164 'data' => $profile->getCollectors(), 165 'ip' => $profile->getIp(), 166 'method' => $profile->getMethod(), 167 'url' => $profile->getUrl(), 168 'time' => $profile->getTime(), 169 ); 170 171 $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken())); 172 173 if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime, self::REDIS_SERIALIZER_PHP)) { 174 if (!$profileIndexed) { 175 // Add to index 176 $indexName = $this->getIndexName(); 177 178 $indexRow = implode("\t", array( 179 $profile->getToken(), 180 $profile->getIp(), 181 $profile->getMethod(), 182 $profile->getUrl(), 183 $profile->getTime(), 184 $profile->getParentToken(), 185 ))."\n"; 186 187 return $this->appendValue($indexName, $indexRow, $this->lifetime); 188 } 189 190 return true; 191 } 192 193 return false; 194 } 195 196 /** 197 * Internal convenience method that returns the instance of Redis. 198 * 199 * @return \Redis 200 * 201 * @throws \RuntimeException 202 */ 203 protected function getRedis() 204 { 205 if (null === $this->redis) { 206 $data = parse_url($this->dsn); 207 208 if (false === $data || !isset($data['scheme']) || $data['scheme'] !== 'redis' || !isset($data['host']) || !isset($data['port'])) { 209 throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Redis with an invalid dsn "%s". The minimal expected format is "redis://[host]:port".', $this->dsn)); 210 } 211 212 if (!extension_loaded('redis')) { 213 throw new \RuntimeException('RedisProfilerStorage requires that the redis extension is loaded.'); 214 } 215 216 $redis = new \Redis(); 217 $redis->connect($data['host'], $data['port']); 218 219 if (isset($data['path'])) { 220 $redis->select(substr($data['path'], 1)); 221 } 222 223 if (isset($data['pass'])) { 224 $redis->auth($data['pass']); 225 } 226 227 $redis->setOption(self::REDIS_OPT_PREFIX, self::TOKEN_PREFIX); 228 229 $this->redis = $redis; 230 } 231 232 return $this->redis; 233 } 234 235 /** 236 * Set instance of the Redis. 237 * 238 * @param \Redis $redis 239 */ 240 public function setRedis($redis) 241 { 242 $this->redis = $redis; 243 } 244 245 private function createProfileFromData($token, $data, $parent = null) 246 { 247 $profile = new Profile($token); 248 $profile->setIp($data['ip']); 249 $profile->setMethod($data['method']); 250 $profile->setUrl($data['url']); 251 $profile->setTime($data['time']); 252 $profile->setCollectors($data['data']); 253 254 if (!$parent && $data['parent']) { 255 $parent = $this->read($data['parent']); 256 } 257 258 if ($parent) { 259 $profile->setParent($parent); 260 } 261 262 foreach ($data['children'] as $token) { 263 if (!$token) { 264 continue; 265 } 266 267 if (!$childProfileData = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP)) { 268 continue; 269 } 270 271 $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile)); 272 } 273 274 return $profile; 275 } 276 277 /** 278 * Gets the item name. 279 * 280 * @param string $token 281 * 282 * @return string 283 */ 284 private function getItemName($token) 285 { 286 $name = $token; 287 288 if ($this->isItemNameValid($name)) { 289 return $name; 290 } 291 292 return false; 293 } 294 295 /** 296 * Gets the name of the index. 297 * 298 * @return string 299 */ 300 private function getIndexName() 301 { 302 $name = 'index'; 303 304 if ($this->isItemNameValid($name)) { 305 return $name; 306 } 307 308 return false; 309 } 310 311 private function isItemNameValid($name) 312 { 313 $length = strlen($name); 314 315 if ($length > 2147483648) { 316 throw new \RuntimeException(sprintf('The Redis item key "%s" is too long (%s bytes). Allowed maximum size is 2^31 bytes.', $name, $length)); 317 } 318 319 return true; 320 } 321 322 /** 323 * Retrieves an item from the Redis server. 324 * 325 * @param string $key 326 * @param int $serializer 327 * 328 * @return mixed 329 */ 330 private function getValue($key, $serializer = self::REDIS_SERIALIZER_NONE) 331 { 332 $redis = $this->getRedis(); 333 $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer); 334 335 return $redis->get($key); 336 } 337 338 /** 339 * Stores an item on the Redis server under the specified key. 340 * 341 * @param string $key 342 * @param mixed $value 343 * @param int $expiration 344 * @param int $serializer 345 * 346 * @return bool 347 */ 348 private function setValue($key, $value, $expiration = 0, $serializer = self::REDIS_SERIALIZER_NONE) 349 { 350 $redis = $this->getRedis(); 351 $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer); 352 353 return $redis->setex($key, $expiration, $value); 354 } 355 356 /** 357 * Appends data to an existing item on the Redis server. 358 * 359 * @param string $key 360 * @param string $value 361 * @param int $expiration 362 * 363 * @return bool 364 */ 365 private function appendValue($key, $value, $expiration = 0) 366 { 367 $redis = $this->getRedis(); 368 $redis->setOption(self::REDIS_OPT_SERIALIZER, self::REDIS_SERIALIZER_NONE); 369 370 if ($redis->exists($key)) { 371 $redis->append($key, $value); 372 373 return $redis->setTimeout($key, $expiration); 374 } 375 376 return $redis->setex($key, $expiration, $value); 377 } 378 379 /** 380 * Removes the specified keys. 381 * 382 * @param array $keys 383 * 384 * @return bool 385 */ 386 private function delete(array $keys) 387 { 388 return (bool) $this->getRedis()->delete($keys); 389 } 390 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Jan 11 00:25:41 2018 | Cross-referenced by PHPXref 0.7.1 |