3 * @copyright Copyright (C) 2020, Friendica
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Core\Cache;
24 use Friendica\Network\HTTPException\InternalServerErrorException;
27 * Trait for Memcache to add a custom version of the
28 * method getAllKeys() since this isn't working anymore
30 * Adds the possibility to directly communicate with the memcache too
32 trait TraitMemcacheCommand
35 * @var string server address
40 * @var int server port
45 * Retrieves the stored keys of the memcache instance
46 * Uses custom commands, which aren't bound to the used instance of the class
48 * @todo Due the fact that we use a custom command, there are race conditions possible:
49 * - $this->memcache(d) adds a key
50 * - $this->getMemcacheKeys is called directly "after"
51 * - But $this->memcache(d) isn't finished adding the key, so getMemcacheKeys doesn't find it
53 * @return array All keys of the memcache instance
55 * @throws InternalServerErrorException
57 protected function getMemcacheKeys()
59 $string = $this->sendMemcacheCommand("stats items");
60 $lines = explode("\r\n", $string);
64 foreach ($lines as $line) {
66 if (preg_match("/STAT items:([\d]+):number ([\d]+)/", $line, $matches) &&
68 !in_array($matches[1], $keys)) {
70 $slabs[] = $matches[1];
71 $string = $this->sendMemcacheCommand("stats cachedump " . $matches[1] . " " . $matches[2]);
72 preg_match_all("/ITEM (.*?) /", $string, $matches);
73 $keys = array_merge($keys, $matches[1]);
81 * Taken directly from memcache PECL source
82 * Sends a command to the memcache instance and returns the result
85 * http://pecl.php.net/package/memcache
87 * @param string $command The command to send to the Memcache server
89 * @return string The returned buffer result
91 * @throws InternalServerErrorException In case the memcache server isn't available (anymore)
93 protected function sendMemcacheCommand(string $command)
95 $s = @fsockopen($this->server, $this->port);
97 throw new InternalServerErrorException("Cant connect to:" . $this->server . ':' . $this->port);
100 fwrite($s, $command . "\r\n");
105 $buf .= fgets($s, 256);
107 if (strpos($buf, "END\r\n") !== false) { // stat says end
111 if (strpos($buf, "DELETED\r\n") !== false || strpos($buf, "NOT_FOUND\r\n") !== false) { // delete says these
115 if (strpos($buf, "OK\r\n") !== false) { // flush_all says ok