Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
RedisProfilerStorage.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Component\HttpKernel\Profiler;
013
014 @trigger_error('The '.__NAMESPACE__.'\RedisProfilerStorage class is deprecated since Symfony 2.8 and will be removed in 3.0. Use FileProfilerStorage instead.', E_USER_DEPRECATED);
015
016 /**
017 * RedisProfilerStorage stores profiling information in Redis.
018 *
019 * @author Andrej Hudec <pulzarraider@gmail.com>
020 * @author Stephane PY <py.stephane1@gmail.com>
021 *
022 * @deprecated Deprecated since Symfony 2.8, to be removed in Symfony 3.0.
023 * Use {@link FileProfilerStorage} instead.
024 */
025 class RedisProfilerStorage implements ProfilerStorageInterface
026 {
027 const TOKEN_PREFIX = 'sf_profiler_';
028
029 const REDIS_OPT_SERIALIZER = 1;
030 const REDIS_OPT_PREFIX = 2;
031 const REDIS_SERIALIZER_NONE = 0;
032 const REDIS_SERIALIZER_PHP = 1;
033
034 protected $dsn;
035 protected $lifetime;
036
037 /**
038 * @var \Redis
039 */
040 private $redis;
041
042 /**
043 * Constructor.
044 *
045 * @param string $dsn A data source name
046 * @param string $username Not used
047 * @param string $password Not used
048 * @param int $lifetime The lifetime to use for the purge
049 */
050 public function __construct($dsn, $username = '', $password = '', $lifetime = 86400)
051 {
052 $this->dsn = $dsn;
053 $this->lifetime = (int) $lifetime;
054 }
055
056 /**
057 * {@inheritdoc}
058 */
059 public function find($ip, $url, $limit, $method, $start = null, $end = null)
060 {
061 $indexName = $this->getIndexName();
062
063 if (!$indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE)) {
064 return array();
065 }
066
067 $profileList = array_reverse(explode("\n", $indexContent));
068 $result = array();
069
070 foreach ($profileList as $item) {
071 if ($limit === 0) {
072 break;
073 }
074
075 if ($item == '') {
076 continue;
077 }
078
079 $values = explode("\t", $item, 7);
080 list($itemToken, $itemIp, $itemMethod, $itemUrl, $itemTime, $itemParent) = $values;
081 $statusCode = isset($values[6]) ? $values[6] : null;
082
083 $itemTime = (int) $itemTime;
084
085 if ($ip && false === strpos($itemIp, $ip) || $url && false === strpos($itemUrl, $url) || $method && false === strpos($itemMethod, $method)) {
086 continue;
087 }
088
089 if (!empty($start) && $itemTime < $start) {
090 continue;
091 }
092
093 if (!empty($end) && $itemTime > $end) {
094 continue;
095 }
096
097 $result[] = array(
098 'token' => $itemToken,
099 'ip' => $itemIp,
100 'method' => $itemMethod,
101 'url' => $itemUrl,
102 'time' => $itemTime,
103 'parent' => $itemParent,
104 'status_code' => $statusCode,
105 );
106 --$limit;
107 }
108
109 return $result;
110 }
111
112 /**
113 * {@inheritdoc}
114 */
115 public function purge()
116 {
117 // delete only items from index
118 $indexName = $this->getIndexName();
119
120 $indexContent = $this->getValue($indexName, self::REDIS_SERIALIZER_NONE);
121
122 if (!$indexContent) {
123 return false;
124 }
125
126 $profileList = explode("\n", $indexContent);
127
128 $result = array();
129
130 foreach ($profileList as $item) {
131 if ($item == '') {
132 continue;
133 }
134
135 if (false !== $pos = strpos($item, "\t")) {
136 $result[] = $this->getItemName(substr($item, 0, $pos));
137 }
138 }
139
140 $result[] = $indexName;
141
142 return $this->delete($result);
143 }
144
145 /**
146 * {@inheritdoc}
147 */
148 public function read($token)
149 {
150 if (empty($token)) {
151 return false;
152 }
153
154 $profile = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP);
155
156 if (false !== $profile) {
157 $profile = $this->createProfileFromData($token, $profile);
158 }
159
160 return $profile;
161 }
162
163 /**
164 * {@inheritdoc}
165 */
166 public function write(Profile $profile)
167 {
168 $data = array(
169 'token' => $profile->getToken(),
170 'parent' => $profile->getParentToken(),
171 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()),
172 'data' => $profile->getCollectors(),
173 'ip' => $profile->getIp(),
174 'method' => $profile->getMethod(),
175 'url' => $profile->getUrl(),
176 'time' => $profile->getTime(),
177 );
178
179 $profileIndexed = false !== $this->getValue($this->getItemName($profile->getToken()));
180
181 if ($this->setValue($this->getItemName($profile->getToken()), $data, $this->lifetime, self::REDIS_SERIALIZER_PHP)) {
182 if (!$profileIndexed) {
183 // Add to index
184 $indexName = $this->getIndexName();
185
186 $indexRow = implode("\t", array(
187 $profile->getToken(),
188 $profile->getIp(),
189 $profile->getMethod(),
190 $profile->getUrl(),
191 $profile->getTime(),
192 $profile->getParentToken(),
193 $profile->getStatusCode(),
194 ))."\n";
195
196 return $this->appendValue($indexName, $indexRow, $this->lifetime);
197 }
198
199 return true;
200 }
201
202 return false;
203 }
204
205 /**
206 * Internal convenience method that returns the instance of Redis.
207 *
208 * @return \Redis
209 *
210 * @throws \RuntimeException
211 */
212 protected function getRedis()
213 {
214 if (null === $this->redis) {
215 $data = parse_url($this->dsn);
216
217 if (false === $data || !isset($data['scheme']) || $data['scheme'] !== 'redis' || !isset($data['host']) || !isset($data['port'])) {
218 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));
219 }
220
221 if (!extension_loaded('redis')) {
222 throw new \RuntimeException('RedisProfilerStorage requires that the redis extension is loaded.');
223 }
224
225 $redis = new \Redis();
226 $redis->connect($data['host'], $data['port']);
227
228 if (isset($data['path'])) {
229 $redis->select(substr($data['path'], 1));
230 }
231
232 if (isset($data['pass'])) {
233 $redis->auth($data['pass']);
234 }
235
236 $redis->setOption(self::REDIS_OPT_PREFIX, self::TOKEN_PREFIX);
237
238 $this->redis = $redis;
239 }
240
241 return $this->redis;
242 }
243
244 /**
245 * Set instance of the Redis.
246 *
247 * @param \Redis $redis
248 */
249 public function setRedis($redis)
250 {
251 $this->redis = $redis;
252 }
253
254 private function createProfileFromData($token, $data, $parent = null)
255 {
256 $profile = new Profile($token);
257 $profile->setIp($data['ip']);
258 $profile->setMethod($data['method']);
259 $profile->setUrl($data['url']);
260 $profile->setTime($data['time']);
261 $profile->setCollectors($data['data']);
262
263 if (!$parent && $data['parent']) {
264 $parent = $this->read($data['parent']);
265 }
266
267 if ($parent) {
268 $profile->setParent($parent);
269 }
270
271 foreach ($data['children'] as $token) {
272 if (!$token) {
273 continue;
274 }
275
276 if (!$childProfileData = $this->getValue($this->getItemName($token), self::REDIS_SERIALIZER_PHP)) {
277 continue;
278 }
279
280 $profile->addChild($this->createProfileFromData($token, $childProfileData, $profile));
281 }
282
283 return $profile;
284 }
285
286 /**
287 * Gets the item name.
288 *
289 * @param string $token
290 *
291 * @return string
292 */
293 private function getItemName($token)
294 {
295 $name = $token;
296
297 if ($this->isItemNameValid($name)) {
298 return $name;
299 }
300
301 return false;
302 }
303
304 /**
305 * Gets the name of the index.
306 *
307 * @return string
308 */
309 private function getIndexName()
310 {
311 $name = 'index';
312
313 if ($this->isItemNameValid($name)) {
314 return $name;
315 }
316
317 return false;
318 }
319
320 private function isItemNameValid($name)
321 {
322 $length = strlen($name);
323
324 if ($length > 2147483648) {
325 throw new \RuntimeException(sprintf('The Redis item key "%s" is too long (%s bytes). Allowed maximum size is 2^31 bytes.', $name, $length));
326 }
327
328 return true;
329 }
330
331 /**
332 * Retrieves an item from the Redis server.
333 *
334 * @param string $key
335 * @param int $serializer
336 *
337 * @return mixed
338 */
339 private function getValue($key, $serializer = self::REDIS_SERIALIZER_NONE)
340 {
341 $redis = $this->getRedis();
342 $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer);
343
344 return $redis->get($key);
345 }
346
347 /**
348 * Stores an item on the Redis server under the specified key.
349 *
350 * @param string $key
351 * @param mixed $value
352 * @param int $expiration
353 * @param int $serializer
354 *
355 * @return bool
356 */
357 private function setValue($key, $value, $expiration = 0, $serializer = self::REDIS_SERIALIZER_NONE)
358 {
359 $redis = $this->getRedis();
360 $redis->setOption(self::REDIS_OPT_SERIALIZER, $serializer);
361
362 return $redis->setex($key, $expiration, $value);
363 }
364
365 /**
366 * Appends data to an existing item on the Redis server.
367 *
368 * @param string $key
369 * @param string $value
370 * @param int $expiration
371 *
372 * @return bool
373 */
374 private function appendValue($key, $value, $expiration = 0)
375 {
376 $redis = $this->getRedis();
377 $redis->setOption(self::REDIS_OPT_SERIALIZER, self::REDIS_SERIALIZER_NONE);
378
379 if ($redis->exists($key)) {
380 $redis->append($key, $value);
381
382 return $redis->setTimeout($key, $expiration);
383 }
384
385 return $redis->setex($key, $expiration, $value);
386 }
387
388 /**
389 * Removes the specified keys.
390 *
391 * @param array $keys
392 *
393 * @return bool
394 */
395 private function delete(array $keys)
396 {
397 return (bool) $this->getRedis()->delete($keys);
398 }
399 }
400