3 * @copyright Copyright (C) 2010-2021, the Friendica project
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\Type;
24 use Friendica\Core\Cache\Exception\CachePersistenceException;
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 MemcacheCommandTrait
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 CachePersistenceException
57 protected function getMemcacheKeys(): array
59 $string = $this->sendMemcacheCommand("stats items");
60 $lines = explode("\r\n", $string);
63 foreach ($lines as $line) {
64 if (preg_match("/STAT items:([\d]+):number ([\d]+)/", $line, $matches) &&
66 !in_array($matches[1], $keys)) {
67 $string = $this->sendMemcacheCommand("stats cachedump " . $matches[1] . " " . $matches[2]);
68 preg_match_all("/ITEM (.*?) /", $string, $matches);
69 $keys = array_merge($keys, $matches[1]);
77 * Taken directly from memcache PECL source
78 * Sends a command to the memcache instance and returns the result
81 * http://pecl.php.net/package/memcache
83 * @param string $command The command to send to the Memcache server
85 * @return string The returned buffer result
87 * @throws CachePersistenceException In case the memcache server isn't available (anymore)
89 protected function sendMemcacheCommand(string $command): string
91 $s = @fsockopen($this->server, $this->port);
93 throw new CachePersistenceException("Cant connect to:" . $this->server . ':' . $this->port);
96 fwrite($s, $command . "\r\n");
100 $buf .= fgets($s, 256);
102 if (strpos($buf, "END\r\n") !== false) { // stat says end
106 if (strpos($buf, "DELETED\r\n") !== false || strpos($buf, "NOT_FOUND\r\n") !== false) { // delete says these
110 if (strpos($buf, "OK\r\n") !== false) { // flush_all says ok