]> git.mxchange.org Git - friendica.git/blob - src/Core/Cache/TraitMemcacheCommand.php
Merge pull request #7945 from MrPetovan/bug/fatal-errors
[friendica.git] / src / Core / Cache / TraitMemcacheCommand.php
1 <?php
2
3 namespace Friendica\Core\Cache;
4
5 use Friendica\Network\HTTPException\InternalServerErrorException;
6
7 /**
8  * Trait for Memcache to add a custom version of the
9  * method getAllKeys() since this isn't working anymore
10  *
11  * Adds the possibility to directly communicate with the memcache too
12  */
13 trait TraitMemcacheCommand
14 {
15         /**
16          * @var string server address
17          */
18         protected $server;
19
20         /**
21          * @var int server port
22          */
23         protected $port;
24
25         /**
26          * Retrieves the stored keys of the memcache instance
27          * Uses custom commands, which aren't bound to the used instance of the class
28          *
29          * @todo Due the fact that we use a custom command, there are race conditions possible:
30          *       - $this->memcache(d) adds a key
31          *       - $this->getMemcacheKeys is called directly "after"
32          *       - But $this->memcache(d) isn't finished adding the key, so getMemcacheKeys doesn't find it
33          *
34          * @return array All keys of the memcache instance
35          *
36          * @throws InternalServerErrorException
37          */
38         protected function getMemcacheKeys()
39         {
40                 $string = $this->sendMemcacheCommand("stats items");
41                 $lines  = explode("\r\n", $string);
42                 $slabs  = [];
43                 $keys   = [];
44
45                 foreach ($lines as $line) {
46
47                         if (preg_match("/STAT items:([\d]+):number ([\d]+)/", $line, $matches) &&
48                             isset($matches[1]) &&
49                             !in_array($matches[1], $keys)) {
50
51                                 $slabs[] = $matches[1];
52                                 $string  = $this->sendMemcacheCommand("stats cachedump " . $matches[1] . " " . $matches[2]);
53                                 preg_match_all("/ITEM (.*?) /", $string, $matches);
54                                 $keys = array_merge($keys, $matches[1]);
55                         }
56                 }
57
58                 return $keys;
59         }
60
61         /**
62          * Taken directly from memcache PECL source
63          * Sends a command to the memcache instance and returns the result
64          * as a string
65          *
66          * http://pecl.php.net/package/memcache
67          *
68          * @param string $command The command to send to the Memcache server
69          *
70          * @return string The returned buffer result
71          *
72          * @throws InternalServerErrorException In case the memcache server isn't available (anymore)
73          */
74         protected function sendMemcacheCommand(string $command)
75         {
76                 $s = @fsockopen($this->server, $this->port);
77                 if (!$s) {
78                         throw new InternalServerErrorException("Cant connect to:" . $this->server . ':' . $this->port);
79                 }
80
81                 fwrite($s, $command . "\r\n");
82                 $buf = '';
83
84                 while (!feof($s)) {
85
86                         $buf .= fgets($s, 256);
87
88                         if (strpos($buf, "END\r\n") !== false) { // stat says end
89                                 break;
90                         }
91
92                         if (strpos($buf, "DELETED\r\n") !== false || strpos($buf, "NOT_FOUND\r\n") !== false) { // delete says these
93                                 break;
94                         }
95
96                         if (strpos($buf, "OK\r\n") !== false) { // flush_all says ok
97                                 break;
98                         }
99                 }
100
101                 fclose($s);
102                 return ($buf);
103         }
104 }