*/
public function getAllKeys($prefix = null)
{
- return $this->filterArrayKeysByPrefix($this->cachedData, $prefix);
+ return $this->filterArrayKeysByPrefix(array_keys($this->cachedData), $prefix);
}
/**
* Filters the keys of an array with a given prefix
* Returns the filtered keys as an new array
*
- * @param array $array The array, which should get filtered
+ * @param array $keys The keys, which should get filtered
* @param string|null $prefix The prefix (if null, all keys will get returned)
*
* @return array The filtered array with just the keys
*/
- protected function filterArrayKeysByPrefix($array, $prefix = null)
+ protected function filterArrayKeysByPrefix(array $keys, string $prefix = null)
{
if (empty($prefix)) {
- return array_keys($array);
+ return $keys;
} else {
$result = [];
- foreach (array_keys($array) as $key) {
+ foreach ($keys as $key) {
if (strpos($key, $prefix) === 0) {
array_push($result, $key);
}
*/
private $logger;
+ /**
+ * @var string First server address
+ */
+
+ private $firstServer;
+
+ /**
+ * @var int First server port
+ */
+ private $firstPort;
+
/**
* Due to limitations of the INI format, the expected configuration for Memcached servers is the following:
* array {
}
});
+ $this->firstServer = $memcached_hosts[0][0] ?? 'localhost';
+ $this->firstPort = $memcached_hosts[0][1] ?? 11211;
+
$this->memcached->addServers($memcached_hosts);
if (count($this->memcached->getServerList()) == 0) {
*/
public function getAllKeys($prefix = null)
{
- $keys = $this->getOriginalKeys($this->memcached->getAllKeys());
+ $keys = $this->getOriginalKeys($this->getMemcachedKeys());
- if ($this->memcached->getResultCode() == Memcached::RES_SUCCESS) {
- return $this->filterArrayKeysByPrefix($keys, $prefix);
- } else {
- $this->logger->debug('Memcached \'getAllKeys\' failed', ['result' => $this->memcached->getResultMessage()]);
- return [];
+ return $this->filterArrayKeysByPrefix($keys, $prefix);
+ }
+
+ /**
+ * Get all memcached keys.
+ * Special function because getAllKeys() is broken since memcached 1.4.23.
+ *
+ * cleaned up version of code found on Stackoverflow.com by Maduka Jayalath
+ *
+ * @return array|int - all retrieved keys (or negative number on error)
+ */
+ private function getMemcachedKeys()
+ {
+ $mem = @fsockopen($this->firstServer, $this->firstPort);
+ if ($mem === false) {
+ return -1;
+ }
+
+ // retrieve distinct slab
+ $r = @fwrite($mem, 'stats items' . chr(10));
+ if ($r === false) {
+ return -2;
}
+
+ $slab = [];
+ while (($l = @fgets($mem, 1024)) !== false) {
+ // finished?
+ $l = trim($l);
+ if ($l == 'END') {
+ break;
+ }
+
+ $m = [];
+ // <STAT items:22:evicted_nonzero 0>
+ $r = preg_match('/^STAT\sitems\:(\d+)\:/', $l, $m);
+ if ($r != 1) {
+ return -3;
+ }
+ $a_slab = $m[1];
+
+ if (!array_key_exists($a_slab, $slab)) {
+ $slab[$a_slab] = [];
+ }
+ }
+
+ reset($slab);
+ foreach ($slab as $a_slab_key => &$a_slab) {
+ $r = @fwrite($mem, 'stats cachedump ' . $a_slab_key . ' 100' . chr(10));
+ if ($r === false) {
+ return -4;
+ }
+
+ while (($l = @fgets($mem, 1024)) !== false) {
+ // finished?
+ $l = trim($l);
+ if ($l == 'END') {
+ break;
+ }
+
+ $m = [];
+ // ITEM 42 [118 b; 1354717302 s]
+ $r = preg_match('/^ITEM\s([^\s]+)\s/', $l, $m);
+ if ($r != 1) {
+ return -5;
+ }
+ $a_key = $m[1];
+
+ $a_slab[] = $a_key;
+ }
+ }
+
+ // close the connection
+ @fclose($mem);
+ unset($mem);
+
+ $keys = [];
+ reset($slab);
+ foreach ($slab AS &$a_slab) {
+ reset($a_slab);
+ foreach ($a_slab AS &$a_key) {
+ $keys[] = $a_key;
+ }
+ }
+ unset($slab);
+
+ return $keys;
}
/**
if (empty($prefix)) {
$where = ['`expires` >= ?', DateTimeFormat::utcNow()];
} else {
- $where = ['`expires` >= ? AND `k` LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix];
+ $where = ['`expires` >= ? AND `name` LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix];
}
$stmt = $this->dba->select('locks', ['name'], $where);
namespace Friendica\Test\src\Core\Cache;
-use Friendica\Core\Cache\MemcachedCache;
use Friendica\Test\MockedTest;
use Friendica\Util\PidFile;
*/
public function testGetAllKeys($value1, $value2, $value3)
{
- if ($this->cache instanceof MemcachedCache) {
- $this->markTestSkipped('Memcached doesn\'t support getAllKeys anymore');
- }
-
$this->assertTrue($this->instance->set('value1', $value1));
$this->assertTrue($this->instance->set('value2', $value2));
$this->assertTrue($this->instance->set('test_value3', $value3));
$list = $this->instance->getAllKeys('test');
$this->assertContains('test_value3', $list);
+ $this->assertNotContains('value1', $list);
+ $this->assertNotContains('value2', $list);
}
}