Permalink
Browse files

feature(cache): allows specifying cache directory in settings.php

All file caches (system/simple cache, views) are stored in the directory
`$CONFIG->cacheroot`. If not given, this defaults to the data directory.

The system-wide file cache object is moved to a service.
  • Loading branch information...
mrclay committed Feb 19, 2016
1 parent ca9390f commit 4b2ed514e20c7da8c6a1e40a3886c6671c9b62ef
@@ -142,6 +142,16 @@
*/
//$CONFIG->boot_cache_ttl = 10;
+/**
+ * Set cache directory
+ *
+ * By default, Elgg uses the data directory to store cache files, but this may
+ * be undesirable for sites with the data directory on a distributed file system
+ * (e.g. multiple servers with load balancing). You can specify a separate location
+ * for the cache files here.
+ */
+//$CONFIG->cacheroot = "";
+
/**
* Cookie configuration
*
@@ -120,7 +120,7 @@ public function handleRequest($path) {
$this->handle304($etag);
// trust the client but check for an existing cache file
- $filename = $config->getVolatile('dataroot') . "views_simplecache/$ts/$viewtype/$view";
+ $filename = $config->getVolatile('cacheroot') . "views_simplecache/$ts/$viewtype/$view";
if (file_exists($filename)) {
$this->sendCacheHeaders($etag);
readfile($filename);
@@ -137,7 +137,7 @@ public function handleRequest($path) {
$lastcache = (int)$config->get('lastcache');
- $filename = $config->getVolatile('dataroot') . "views_simplecache/$lastcache/$viewtype/$view";
+ $filename = $config->getVolatile('cacheroot') . "views_simplecache/$lastcache/$viewtype/$view";
if ($lastcache == $ts) {
$this->sendCacheHeaders($etag);
@@ -213,7 +213,7 @@ protected function setupSimplecache() {
$config = $this->config;
$config->loadSettingsFile();
- if ($config->getVolatile('dataroot') && $config->getVolatile('simplecache_enabled') !== null) {
+ if ($config->getVolatile('cacheroot') && $config->getVolatile('simplecache_enabled') !== null) {
// we can work with these...
return;
}
@@ -242,8 +242,12 @@ protected function setupSimplecache() {
$config->set($row->name, $row->value);
}
- if (!$config->getVolatile('dataroot')) {
- $this->send403('Cache error: unable to get the data root');
+ if (!$config->getVolatile('cacheroot')) {
+ $dataroot = $config->getVolatile('dataroot');
+ if (!$dataroot) {
+ $this->send403('Cache error: unable to get the cache root');
+ }
+ $config->set('cacheroot', $dataroot);
}
}
@@ -164,7 +164,8 @@ function disable() {
* @return string
*/
private function getPath() {
- return realpath($this->config->getDataPath() . "/views_simplecache");
+ $realpath = realpath($this->config->getCachePath());
+ return rtrim($realpath, DIRECTORY_SEPARATOR) . "/views_simplecache";
}
/**
@@ -2,6 +2,9 @@
namespace Elgg\Cache;
use Elgg\Profilable;
+use Elgg\Config;
+use ElggFileCache;
+use Elgg\Database\Datalist;
/**
* WARNING: API IN FLUX. DO NOT USE DIRECTLY.
@@ -16,50 +19,40 @@ class SystemCache {
use Profilable;
/**
- * Global Elgg configuration
- *
- * @var \stdClass
+ * @var Config
*/
- private $CONFIG;
+ private $config;
/**
- * Constructor
+ * @var ElggFileCache
*/
- public function __construct() {
- global $CONFIG;
- $this->CONFIG = $CONFIG;
- }
+ private $cache;
/**
- * Returns an \ElggCache object suitable for caching system information
- *
- * @todo Can this be done in a cleaner way?
- * @todo Swap to memcache etc?
+ * @var Datalist
+ */
+ private $datalist;
+
+ /**
+ * Constructor
*
- * @return \ElggFileCache
+ * @param ElggFileCache $cache Elgg disk cache
+ * @param Config $config Elgg config
+ * @param Datalist $datalist Elgg datalist
*/
- function getFileCache() {
-
-
- /**
- * A default filestore cache using the dataroot.
- */
- static $FILE_PATH_CACHE;
-
- if (!$FILE_PATH_CACHE) {
- $FILE_PATH_CACHE = new \ElggFileCache($this->CONFIG->dataroot . 'system_cache/');
- }
-
- return $FILE_PATH_CACHE;
+ public function __construct(ElggFileCache $cache, Config $config, Datalist $datalist) {
+ $this->cache = $cache;
+ $this->config = $config;
+ $this->datalist = $datalist;
}
-
+
/**
* Reset the system cache by deleting the caches
*
* @return void
*/
function reset() {
- $this->getFileCache()->clear();
+ $this->cache->clear();
}
/**
@@ -70,9 +63,8 @@ function reset() {
* @return bool
*/
function save($type, $data) {
-
if ($this->isEnabled()) {
- return $this->getFileCache()->save($type, $data);
+ return $this->cache->save($type, $data);
}
return false;
@@ -85,10 +77,8 @@ function save($type, $data) {
* @return string
*/
function load($type) {
-
if ($this->isEnabled()) {
- $cached_data = $this->getFileCache()->load($type);
-
+ $cached_data = $this->cache->load($type);
if ($cached_data) {
return $cached_data;
}
@@ -103,7 +93,7 @@ function load($type) {
* @return bool
*/
function isEnabled() {
- return (bool) $this->CONFIG->system_cache_enabled;
+ return (bool)$this->config->getVolatile('system_cache_enabled');
}
/**
@@ -115,10 +105,8 @@ function isEnabled() {
* @return void
*/
function enable() {
-
-
- _elgg_services()->datalist->set('system_cache_enabled', 1);
- $this->CONFIG->system_cache_enabled = 1;
+ $this->datalist->set('system_cache_enabled', 1);
+ $this->config->set('system_cache_enabled', 1);
$this->reset();
}
@@ -131,10 +119,8 @@ function enable() {
* @return void
*/
function disable() {
-
-
- _elgg_services()->datalist->set('system_cache_enabled', 0);
- $this->CONFIG->system_cache_enabled = 0;
+ $this->datalist->set('system_cache_enabled', 0);
+ $this->config->set('system_cache_enabled', 0);
$this->reset();
}
@@ -149,7 +135,7 @@ function loadAll() {
$this->timer->begin([__METHOD__]);
}
- $this->CONFIG->system_cache_loaded = false;
+ $this->config->set('system_cache_loaded', false);
if (!_elgg_services()->views->configureFromCache($this)) {
return;
@@ -162,8 +148,8 @@ function loadAll() {
$GLOBALS['_ELGG']->view_types = unserialize($data);
// Note: We don't need view_overrides for operation. Inspector can pull this from the cache
-
- $this->CONFIG->system_cache_loaded = true;
+
+ $this->config->set('system_cache_loaded', true);
if ($this->timer) {
$this->timer->end([__METHOD__]);
@@ -182,7 +168,7 @@ function init() {
}
// cache system data if enabled and not loaded
- if (!$this->CONFIG->system_cache_loaded) {
+ if (!$this->config->getVolatile('system_cache_loaded')) {
$this->save('view_types', serialize($GLOBALS['_ELGG']->view_types));
_elgg_services()->views->cacheConfiguration($this);
@@ -132,6 +132,19 @@ public function getDataPath() {
return $this->config->dataroot;
}
+ /**
+ * {@inheritdoc}
+ */
+ public function getCachePath() {
+ $this->loadSettingsFile();
+
+ if (!isset($this->config->cacheroot)) {
+ $this->config->cacheroot = $this->getDataPath();
+ }
+
+ return $this->config->cacheroot;
+ }
+
/**
* {@inheritdoc}
*/
@@ -271,6 +284,10 @@ public function loadSettingsFile() {
$GLOBALS['_ELGG']->simplecache_enabled_in_settings = isset($CONFIG->simplecache_enabled);
+ if (!empty($CONFIG->cacheroot)) {
+ $CONFIG->cacheroot = rtrim($CONFIG->cacheroot, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
+ }
+
if (!$global_is_bound) {
// must manually copy settings into our storage
foreach ($CONFIG as $key => $value) {
@@ -35,6 +35,7 @@
* @property-read \Elgg\Database\EntityTable $entityTable
* @property-read \Elgg\EventsService $events
* @property-read \Elgg\Assets\ExternalFiles $externalFiles
+ * @property-read \ElggFileCache $fileCache
* @property-read \Elgg\PluginHooksService $hooks
* @property-read \Elgg\Http\Input $input
* @property-read \Elgg\Logger $logger
@@ -91,7 +92,7 @@ public function __construct(\Elgg\Config $config) {
$this->setFactory('autoloadManager', function(ServiceProvider $c) {
$manager = new \Elgg\AutoloadManager($c->classLoader);
if (!$c->config->get('AutoloaderManager_skip_storage')) {
- $manager->setStorage($c->systemCache->getFileCache());
+ $manager->setStorage($c->fileCache);
$manager->loadCache();
}
return $manager;
@@ -180,6 +181,10 @@ public function __construct(\Elgg\Config $config) {
return new \Elgg\Assets\ExternalFiles($c->config->getStorageObject());
});
+ $this->setFactory('fileCache', function(ServiceProvider $c) {
+ return new \ElggFileCache($c->config->getCachePath() . 'system_cache/');
+ });
+
$this->setFactory('hooks', function(ServiceProvider $c) {
return $this->resolveLoggerDependencies('hooks');
});
@@ -317,7 +322,7 @@ public function __construct(\Elgg\Config $config) {
});
$this->setFactory('systemCache', function (ServiceProvider $c) {
- $cache = new \Elgg\Cache\SystemCache();
+ $cache = new \Elgg\Cache\SystemCache($c->fileCache, $c->config, $c->datalist);
if ($c->config->getVolatile('enable_profiling')) {
$cache->setTimer($c->timer);
}
@@ -28,6 +28,15 @@ public function getPluginsPath();
*/
public function getDataPath();
+ /**
+ * Get the cache directory path for this installation
+ *
+ * If not set in settings.php, the data path will be returned.
+ *
+ * @return string
+ */
+ public function getCachePath();
+
/**
* Get an Elgg configuration value, possibly loading it from the DB's config table
*
View
@@ -18,7 +18,7 @@
* @return \ElggFileCache
*/
function elgg_get_system_cache() {
- return _elgg_services()->systemCache->getFileCache();
+ return _elgg_services()->fileCache;
}
/**
@@ -183,6 +183,11 @@ function elgg_disable_simplecache() {
* @access private
*/
function _elgg_rmdir($dir, $empty = false) {
+ if (!$dir) {
+ // realpath can return false
+ _elgg_services()->logger->warn(__FUNCTION__ . ' called with empty $dir');
+ return true;
+ }
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
@@ -48,6 +48,17 @@ function elgg_get_data_path() {
return _elgg_services()->config->getDataPath();
}
+/**
+ * Get the cache directory path for this installation.
+ *
+ * If not set in settings.php, the data path will be returned.
+ *
+ * @return string
+ */
+function elgg_get_cache_path() {
+ return _elgg_services()->config->getCachePath();
+}
+
/**
* Get the root directory path for this installation
*
@@ -35,6 +35,7 @@ function _elgg_testing_application(\Elgg\Application $app = null) {
'wwwroot' => 'http://localhost/',
'path' => __DIR__ . '/../../../',
'dataroot' => __DIR__ . '/test_files/dataroot/',
+ 'cacheroot' => __DIR__ . '/test_files/cacheroot/',
'site_guid' => 1,
'AutoloaderManager_skip_storage' => true,
'simplecache_enabled' => false,

0 comments on commit 4b2ed51

Please sign in to comment.