/**
* @brief Returns all the cache keys sorted alphabetically
*
- * @return array|null Null if the driver doesn't support this feature
+ * @param string $prefix Prefix of the keys (optional)
+ *
+ * @return array Empty if the driver doesn't support this feature
*/
- public static function getAllKeys()
+ public static function getAllKeys($prefix = null)
{
$time = microtime(true);
- $return = self::getDriver()->getAllKeys();
-
- // Keys are prefixed with the node hostname, let's remove it
- array_walk($return, function (&$value) {
- $value = preg_replace('/^' . self::getApp()->get_hostname() . ':/', '', $value);
- });
-
- sort($return);
+ $return = self::getDriver()->getAllKeys($prefix);
self::getApp()->save_timestamp($time, 'cache');
* @param string $key The original key
* @return string The cache key used for the cache
*/
- protected function getCacheKey($key) {
+ protected function getCacheKey($key)
+ {
// We fetch with the hostname as key to avoid problems with other applications
return self::getApp()->get_hostname() . ":" . $key;
}
+
+ /**
+ * @param array $keys A list of cached keys
+ * @return array A list of original keys
+ */
+ protected function getOriginalKeys($keys)
+ {
+ if (empty($keys)) {
+ return [];
+ } else {
+ // Keys are prefixed with the node hostname, let's remove it
+ array_walk($keys, function (&$value) {
+ $value = preg_replace('/^' . self::getApp()->get_hostname() . ':/', '', $value);
+ });
+
+ sort($keys);
+
+ return $keys;
+ }
+ }
+
+ /**
+ * 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 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)
+ {
+ if (empty($prefix)) {
+ return array_keys($array);
+ } else {
+ $result = [];
+
+ foreach (array_keys($array) as $key) {
+ if (strpos($key, $prefix) === 0) {
+ array_push($result, $key);
+ }
+ }
+
+ return $result;
+ }
+
+ }
}
/**
* (@inheritdoc)
*/
- public function getAllKeys()
+ public function getAllKeys($prefix = null)
{
- return array_keys($this->cachedData);
+ return $this->filterArrayKeysByPrefix($this->cachedData, $prefix);
}
/**
/**
* (@inheritdoc)
*/
- public function getAllKeys()
+ public function getAllKeys($prefix = null)
{
- $stmt = DBA::select('cache', ['k'], ['`expires` >= ?', DateTimeFormat::utcNow()]);
+ if (empty($prefix)) {
+ $where = ['`expires` >= ?', DateTimeFormat::utcNow()];
+ } else {
+ $where = ['`expires` >= ? AND `k` LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix];
+ }
+
+ $stmt = DBA::select('cache', ['k'], $where);
+
+ $keys = [];
+ while ($key = DBA::fetch($stmt)) {
+ array_push($keys, $key['k']);
+ }
+ DBA::close($stmt);
- return DBA::toArray($stmt);
+ return $keys;
}
/**
/**
* Lists all cache keys
*
- * @return array|null Null if it isn't supported by the cache driver
+ * @param string prefix optional a prefix to search
+ *
+ * @return array Empty if it isn't supported by the cache driver
*/
- public function getAllKeys();
+ public function getAllKeys($prefix = null);
/**
* Fetches cached data according to the key
/**
* (@inheritdoc)
*/
- public function getAllKeys()
+ public function getAllKeys($prefix = null)
{
- $list = [];
+ $keys = [];
$allSlabs = $this->memcache->getExtendedStats('slabs');
foreach ($allSlabs as $slabs) {
foreach (array_keys($slabs) as $slabId) {
$cachedump = $this->memcache->getExtendedStats('cachedump', (int)$slabId);
- foreach ($cachedump as $keys => $arrVal) {
+ foreach ($cachedump as $key => $arrVal) {
if (!is_array($arrVal)) {
continue;
}
- $list = array_merge($list, array_keys($arrVal));
+ $keys = array_merge($keys, array_keys($arrVal));
}
}
}
- return $list;
+ $keys = $this->getOriginalKeys($keys);
+
+ return $this->filterArrayKeysByPrefix($keys, $prefix);
}
/**
use Friendica\Core\Cache;
use Exception;
+use Friendica\Network\HTTPException\InternalServerErrorException;
use Memcached;
/**
/**
* (@inheritdoc)
*/
- public function getAllKeys()
+ public function getAllKeys($prefix = null)
{
- return $this->memcached->getAllKeys();
+ $keys = $this->getOriginalKeys($this->memcached->getAllKeys());
+
+ if ($this->memcached->getResultCode() == Memcached::RES_SUCCESS) {
+ return $this->filterArrayKeysByPrefix($keys, $prefix);
+ } else {
+ logger('Memcached \'getAllKeys\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL);
+ return [];
+ }
}
/**
if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) {
$return = $value;
+ } else {
+ logger('Memcached \'get\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL);
}
return $return;
$value
);
}
-
}
/**
/**
* (@inheritdoc)
*/
- public function getAllKeys()
+ public function getAllKeys($prefix = null)
{
- return null;
+ if (empty($prefix)) {
+ $search = '*';
+ } else {
+ $search = $prefix . '*';
+ }
+
+ $list = $this->redis->keys($this->getCacheKey($search));
+
+ return $this->getOriginalKeys($list);
}
/**
private function executeList()
{
$prefix = $this->getArgument(1);
- $keys = Core\Cache::getAllKeys();
+ $keys = Core\Cache::getAllKeys($prefix);
if (empty($prefix)) {
$this->out('Listing all cache keys:');
$count = 0;
foreach ($keys as $key) {
- if (empty($prefix) || strpos($key, $prefix) === 0) {
- $this->out($key);
- $count++;
- }
+ $this->out($key);
+ $count++;
}
$this->out($count . ' keys found');
class ArrayCacheDriverTest extends MemoryCacheTest
{
- /**
- * @var \Friendica\Core\Cache\IMemoryCacheDriver
- */
- private $cache;
-
protected function getInstance()
{
$this->cache = new ArrayCache();
namespace Friendica\Test\src\Core\Cache;
+use Friendica\Core\Cache\MemcachedCacheDriver;
use Friendica\Core\Config;
use Friendica\Test\DatabaseTest;
use Friendica\Util\DateTimeFormat;
*/
protected $instance;
+ /**
+ * @var \Friendica\Core\Cache\IMemoryCacheDriver
+ */
+ protected $cache;
+
+
abstract protected function getInstance();
protected function setUp()
Config::set('system', 'throttle_limit_week', 100);
Config::set('system', 'throttle_limit_month', 100);
Config::set('system', 'theme', 'system_theme');
+
+ $this->instance->clear(false);
}
/**
$received = $this->instance->get('objVal');
$this->assertEquals($value, $received, 'Value type changed from ' . gettype($value) . ' to ' . gettype($received));
}
+
+ /**
+ * @small
+ */
+ public function testGetAllKeys() {
+ if ($this->cache instanceof MemcachedCacheDriver) {
+ $this->markTestSkipped('Memcached doesn\'t support getAllKeys anymore');
+ }
+
+ $this->assertTrue($this->instance->set('value1', 'test'));
+ $this->assertTrue($this->instance->set('value2', 'test'));
+ $this->assertTrue($this->instance->set('test_value3', 'test'));
+
+ $list = $this->instance->getAllKeys();
+
+ $this->assertContains('value1', $list);
+ $this->assertContains('value2', $list);
+ $this->assertContains('test_value3', $list);
+
+ $list = $this->instance->getAllKeys('test');
+
+ $this->assertContains('test_value3', $list);
+ }
}
class DatabaseCacheDriverTest extends CacheTest
{
- /**
- * @var \Friendica\Core\Cache\IMemoryCacheDriver
- */
- private $cache;
-
protected function getInstance()
{
$this->cache = CacheDriverFactory::create('database');
*/
class MemcacheCacheDriverTest extends MemoryCacheTest
{
- /**
- * @var \Friendica\Core\Cache\IMemoryCacheDriver
- */
- private $cache;
-
protected function getInstance()
{
$this->cache = CacheDriverFactory::create('memcache');
*/
class MemcachedCacheDriverTest extends MemoryCacheTest
{
- /**
- * @var \Friendica\Core\Cache\IMemoryCacheDriver
- */
- private $cache;
-
protected function getInstance()
{
$this->cache = CacheDriverFactory::create('memcached');
*/
class RedisCacheDriverTest extends MemoryCacheTest
{
- /**
- * @var \Friendica\Core\Cache\IMemoryCacheDriver
- */
- private $cache;
-
protected function getInstance()
{
$this->cache = CacheDriverFactory::create('redis');