Commit 28e67ceb by Scott

Ensure unique prefix for cache keys

parent 618372e6
......@@ -76,6 +76,13 @@ interface Q2A_Storage_CacheDriver
public function getError();
/**
* Get the prefix used for all cache keys.
*
* @return string
*/
public function getKeyPrefix();
/**
* Get current statistics for the cache.
*
* @return array Array of stats: 'files' => number of files, 'size' => total file size in bytes.
......
......@@ -36,6 +36,7 @@ class Q2A_Storage_CacheFactory
if (self::$cacheDriver === null) {
$config = array(
'enabled' => (int) qa_opt('caching_enabled') === 1,
'keyprefix' => QA_FINAL_MYSQL_DATABASE . '.' . QA_MYSQL_TABLE_PREFIX . '.',
'dir' => defined('QA_CACHE_DIRECTORY') ? QA_CACHE_DIRECTORY : null,
);
......
......@@ -26,6 +26,7 @@
class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
{
private $enabled = false;
private $keyPrefix = '';
private $error;
private $cacheDir;
......@@ -39,6 +40,10 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
return;
}
if (isset($config['keyprefix'])) {
$this->keyPrefix = $config['keyprefix'];
}
if (isset($config['dir'])) {
$this->cacheDir = realpath($config['dir']);
......@@ -67,14 +72,15 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
return null;
}
$file = $this->getFilename($key);
$fullKey = $this->keyPrefix . $key;
$file = $this->getFilename($fullKey);
if (is_readable($file)) {
$lines = file($file, FILE_IGNORE_NEW_LINES);
$actualKey = array_shift($lines);
// double check this is the correct data
if ($key === $actualKey) {
if ($fullKey === $actualKey) {
$expiry = array_shift($lines);
if (is_numeric($expiry) && time() < $expiry) {
......@@ -103,13 +109,14 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
{
$success = false;
$ttl = (int) $ttl;
$fullKey = $this->keyPrefix . $key;
if ($this->enabled && $ttl > 0) {
$encData = serialize($data);
$expiry = time() + ($ttl * 60);
$cache = $key . "\n" . $expiry . "\n" . $encData;
$cache = $fullKey . "\n" . $expiry . "\n" . $encData;
$file = $this->getFilename($key);
$file = $this->getFilename($fullKey);
$dir = dirname($file);
if (is_dir($dir) || mkdir($dir, 0777, true)) {
$success = @file_put_contents($file, $cache) !== false;
......@@ -127,10 +134,10 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
*/
public function delete($key)
{
if ($this->enabled) {
$file = $this->getFilename($key);
$dir = dirname($key);
$fullKey = $this->keyPrefix . $key;
if ($this->enabled) {
$file = $this->getFilename($fullKey);
return $this->deleteFile($file);
}
......@@ -209,6 +216,16 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
}
/**
* Get the prefix used for all cache keys.
*
* @return string
*/
public function getKeyPrefix()
{
return $this->keyPrefix;
}
/**
* Get current statistics for the cache.
*
* @return array Array of stats: 'files' => number of files, 'size' => total file size in bytes.
......@@ -255,13 +272,13 @@ class Q2A_Storage_FileCacheDriver implements Q2A_Storage_CacheDriver
/**
* Generates filename for cache key, of the form `1/23/123abc`
* @param string $key The unique cache key.
* @param string $key The unique cache key (including prefix).
*
* @return string
*/
private function getFilename($key)
private function getFilename($fullKey)
{
$filename = sha1($key);
$filename = sha1($fullKey);
return $this->cacheDir . '/' . substr($filename, 0, 1) . '/' . substr($filename, 1, 2) . '/' . $filename;
}
}
......@@ -27,6 +27,7 @@ class Q2A_Storage_MemcachedDriver implements Q2A_Storage_CacheDriver
{
private $memcached;
private $enabled = false;
private $keyPrefix = '';
private $error;
private $flushed = false;
......@@ -45,10 +46,14 @@ class Q2A_Storage_MemcachedDriver implements Q2A_Storage_CacheDriver
return;
}
if (isset($config['keyprefix'])) {
$this->keyPrefix = $config['keyprefix'];
}
if (extension_loaded('memcached')) {
$this->memcached = new Memcached;
$this->memcached->addServer(self::HOST, self::PORT);
if ($this->memcached->set('q2a.test', 'TEST')) {
if ($this->memcached->set($this->keyPrefix . 'test', 'TEST')) {
$this->enabled = true;
} else {
$this->setMemcachedError();
......@@ -70,7 +75,7 @@ class Q2A_Storage_MemcachedDriver implements Q2A_Storage_CacheDriver
return null;
}
$result = $this->memcached->get($key);
$result = $this->memcached->get($this->keyPrefix . $key);
if ($result === false) {
$this->setMemcachedError();
......@@ -96,7 +101,7 @@ class Q2A_Storage_MemcachedDriver implements Q2A_Storage_CacheDriver
$ttl = (int) $ttl;
$expiry = time() + ($ttl * 60);
$success = $this->memcached->set($key, $data, $expiry);
$success = $this->memcached->set($this->keyPrefix . $key, $data, $expiry);
if (!$success) {
$this->setMemcachedError();
......@@ -117,7 +122,7 @@ class Q2A_Storage_MemcachedDriver implements Q2A_Storage_CacheDriver
return false;
}
$success = $this->memcached->delete($key);
$success = $this->memcached->delete($this->keyPrefix . $key);
if (!$success) {
$this->setMemcachedError();
......@@ -170,6 +175,16 @@ class Q2A_Storage_MemcachedDriver implements Q2A_Storage_CacheDriver
}
/**
* Get the prefix used for all cache keys.
*
* @return string
*/
public function getKeyPrefix()
{
return $this->keyPrefix;
}
/**
* Get current statistics for the cache.
*
* @return array Array of stats: 'files' => number of files, 'size' => total file size in bytes.
......
......@@ -42,7 +42,7 @@ $pagestate = qa_get_state();
// Get information about this question
$cacheDriver = Q2A_Storage_CacheFactory::getCacheDriver();
$cacheKey = "q2a.question:$questionid";
$cacheKey = "question:$questionid";
$useCache = $userid === null && $cacheDriver->isEnabled() && !qa_is_http_post() && empty($pagestate);
$saveCache = false;
......
......@@ -524,7 +524,7 @@ function qa_db_single_select($selectspec)
// check for cached results
if (isset($selectspec['caching'])) {
$cacheDriver = Q2A_Storage_CacheFactory::getCacheDriver();
$cacheKey = 'q2a.query:' . $selectspec['caching']['key'];
$cacheKey = 'query:' . $selectspec['caching']['key'];
if ($cacheDriver->isEnabled()) {
$queryData = $cacheDriver->get($cacheKey);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment