]> git.mxchange.org Git - friendica.git/blob - src/Core/Cache/TraitMemcacheCommand.php
2b136621e59aac084f59fb092f12766bd2bc1f29
[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
49                                 if (isset($matches[1])) {
50                                         if (!in_array($matches[1], $keys)) {
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                 }
59
60                 return $keys;
61         }
62
63         /**
64          * Taken directly from memcache PECL source
65          * Sends a command to the memcache instance and returns the result
66          * as a string
67          *
68          * http://pecl.php.net/package/memcache
69          *
70          * @param string $command The command to send to the Memcache server
71          *
72          * @return string The returned buffer result
73          *
74          * @throws InternalServerErrorException In case the memcache server isn't available (anymore)
75          */
76         protected function sendMemcacheCommand(string $command)
77         {
78                 $s = @fsockopen($this->server, $this->port);
79                 if (!$s) {
80                         throw new InternalServerErrorException("Cant connect to:" . $this->server . ':' . $this->port);
81                 }
82
83                 fwrite($s, $command . "\r\n");
84                 $buf = '';
85
86                 while ((!feof($s))) {
87
88                         $buf .= fgets($s, 256);
89
90                         if (strpos($buf, "END\r\n") !== false) { // stat says end
91                                 break;
92                         }
93
94                         if (strpos($buf, "DELETED\r\n") !== false || strpos($buf, "NOT_FOUND\r\n") !== false) { // delete says these
95                                 break;
96                         }
97
98                         if (strpos($buf, "OK\r\n") !== false) { // flush_all says ok
99                                 break;
100                         }
101                 }
102
103                 fclose($s);
104                 return ($buf);
105         }
106 }