diff options
author | Thomas Steur <thomas.steur@googlemail.com> | 2014-12-17 00:25:51 +0300 |
---|---|---|
committer | Thomas Steur <thomas.steur@googlemail.com> | 2014-12-17 00:25:51 +0300 |
commit | 1634607051341f6d348404cd4bc478cf2474a259 (patch) | |
tree | 8893897d8cdb2b5313a3a2f3f6fac39ce1b56755 /core | |
parent | c0f24c160ab2f573a06146c66fa7fc7bab97a3a7 (diff) |
added support for different caching backends such as redis
Diffstat (limited to 'core')
-rw-r--r-- | core/Cache.php | 117 | ||||
-rw-r--r-- | core/Cache/CacheDecorator.php | 54 | ||||
-rw-r--r-- | core/Cache/CacheInterface.php | 29 | ||||
-rw-r--r-- | core/Cache/LanguageAwareStaticCache.php | 26 | ||||
-rw-r--r-- | core/Cache/PersistentCache.php | 159 | ||||
-rw-r--r-- | core/Cache/PluginAwareStaticCache.php | 31 | ||||
-rw-r--r-- | core/Cache/StaticCache.php | 94 | ||||
-rw-r--r-- | core/CacheFile.php | 237 | ||||
-rw-r--r-- | core/CacheId.php | 30 | ||||
-rw-r--r-- | core/Columns/Updater.php | 21 | ||||
-rw-r--r-- | core/Container/StaticContainer.php | 5 | ||||
-rw-r--r-- | core/DeviceDetectorCache.php | 21 | ||||
-rw-r--r-- | core/DeviceDetectorFactory.php | 2 | ||||
-rw-r--r-- | core/Filesystem.php | 2 | ||||
-rw-r--r-- | core/Metrics.php | 39 | ||||
-rw-r--r-- | core/Plugin.php | 35 | ||||
-rw-r--r-- | core/Plugin/Dimension/ActionDimension.php | 12 | ||||
-rw-r--r-- | core/Plugin/Dimension/ConversionDimension.php | 12 | ||||
-rw-r--r-- | core/Plugin/Dimension/VisitDimension.php | 12 | ||||
-rw-r--r-- | core/Plugin/Manager.php | 20 | ||||
-rw-r--r-- | core/Plugin/Report.php | 16 | ||||
-rw-r--r-- | core/Tracker/Cache.php | 52 | ||||
-rw-r--r-- | core/Tracker/SettingsStorage.php | 18 | ||||
-rw-r--r-- | core/WidgetsList.php | 21 |
24 files changed, 317 insertions, 748 deletions
diff --git a/core/Cache.php b/core/Cache.php new file mode 100644 index 0000000000..b90be8d27b --- /dev/null +++ b/core/Cache.php @@ -0,0 +1,117 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik; + +use Piwik\Cache\Backend; +use Piwik\Container\StaticContainer; + +class Cache +{ + + /** + * This can be considered as the default cache to use in case you don't know which one to pick. It does not support + * the caching of any objects though. Only boolean, numbers, strings and arrays are supported. Whenever you request + * an entry from the cache it will fetch the entry. Cache entries might be persisted but not necessarily. It + * depends on the configured backend. + * + * @return Cache\Lazy + */ + public static function getLazyCache() + { + return StaticContainer::getContainer()->get('Piwik\Cache\Lazy'); + } + + /** + * This class is used to cache any data during one request. It won't be persisted between requests and it can + * cache all kind of data, even objects or resources. This cache is very fast. + * + * @return Cache\Transient + */ + public static function getTransientCache() + { + return StaticContainer::getContainer()->get('Piwik\Cache\Transient'); + } + + /** + * This cache stores all its cache entries under one "cache" entry in a configurable backend. + * + * This comes handy for things that you need very often, nearly in every request. For example plugin metadata, the + * list of tracker plugins, the list of available languages, ... + * Instead of having to read eg. a hundred cache entries from files (or any other backend) it only loads one cache + * entry which contains the hundred keys. Should be used only for things that you need very often and only for + * cache entries that are not too large to keep loading and parsing the single cache entry fast. + * All cache entries it contains have the same life time. For fast performance it won't validate any cache ids. + * It is not possible to cache any objects using this cache. + * + * @return Cache\Eager + */ + public static function getEagerCache() + { + return StaticContainer::getContainer()->get('Piwik\Cache\Eager'); + } + + public static function flushAll() + { + self::getLazyCache()->flushAll(); + self::getTransientCache()->flushAll(); + self::getEagerCache()->flushAll(); + } + + /** + * @param $type + * @return Cache\Backend + */ + public static function buildBackend($type) + { + $factory = new Cache\Backend\Factory(); + $options = self::getOptions($type); + + $backend = $factory->buildBackend($type, $options); + + return $backend; + } + + private static function getOptions($type) + { + $options = self::getBackendOptions($type); + + switch ($type) { + case 'file': + + $options = array('directory' => StaticContainer::getContainer()->get('path.cache')); + break; + + case 'chained': + + foreach ($options['backends'] as $backend) { + $options[$backend] = self::getOptions($backend); + } + + break; + + case 'redis': + + if (!empty($options['timeout'])) { + $options['timeout'] = (float)Common::forceDotAsSeparatorForDecimalPoint($options['timeout']); + } + + break; + } + + return $options; + } + + private static function getBackendOptions($backend) + { + $key = ucfirst($backend) . 'Cache'; + $options = Config::getInstance()->$key; + + return $options; + } +} diff --git a/core/Cache/CacheDecorator.php b/core/Cache/CacheDecorator.php deleted file mode 100644 index f35154ba72..0000000000 --- a/core/Cache/CacheDecorator.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** - * Piwik - free/libre analytics platform - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ -namespace Piwik\Cache; - -use Piwik\Tracker; -use Piwik\Translate; - -/** - * Caching class used for static caching. - */ -class CacheDecorator implements CacheInterface -{ - /** - * @var StaticCache - */ - protected $staticCache; - - public function __construct(CacheInterface $cache) - { - $this->staticCache = $cache; - } - - public function get() - { - return $this->staticCache->get(); - } - - public function has() - { - return $this->staticCache->has(); - } - - public function setCacheKey($cacheKey) - { - $this->staticCache->setCacheKey($cacheKey); - } - - public function getCacheKey() - { - return $this->staticCache->getCacheKey(); - } - - public function set($content) - { - $this->staticCache->set($content); - } - -} diff --git a/core/Cache/CacheInterface.php b/core/Cache/CacheInterface.php deleted file mode 100644 index 65039e5436..0000000000 --- a/core/Cache/CacheInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php -/** - * Piwik - free/libre analytics platform - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ -namespace Piwik\Cache; - -use Piwik\Tracker; -use Piwik\Translate; - -/** - * Caching class used for static caching. - */ -interface CacheInterface -{ - public function get(); - - public function has(); - - public function setCacheKey($cacheKey); - - public function getCacheKey(); - - public function set($content); - -} diff --git a/core/Cache/LanguageAwareStaticCache.php b/core/Cache/LanguageAwareStaticCache.php deleted file mode 100644 index 62b4773282..0000000000 --- a/core/Cache/LanguageAwareStaticCache.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php -/** - * Piwik - free/libre analytics platform - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ -namespace Piwik\Cache; - -use Piwik\Translate; - -/** - * Caching class used for static caching which is language aware. It'll cache the given content depending on the - * current loaded language. This prevents you from having to invalidate the cache during tests in case the loaded - * language changes etc. - * - * TODO convert this to a decorator... see {@link StaticCache} - */ -class LanguageAwareStaticCache extends StaticCache -{ - protected function completeKey($cacheKey) - { - return $cacheKey . Translate::getLanguageLoaded(); - } -} diff --git a/core/Cache/PersistentCache.php b/core/Cache/PersistentCache.php deleted file mode 100644 index 5a98621a4c..0000000000 --- a/core/Cache/PersistentCache.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php -/** - * Piwik - free/libre analytics platform - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ -namespace Piwik\Cache; - -use Piwik\CacheFile; -use Piwik\Development; -use Piwik\Piwik; -use Piwik\SettingsServer; -use Piwik\Version; - -/** - * Caching class that persists all cached values between requests. Meaning whatever you cache will be stored on the - * file system. It differs from other caches such as {@link CacheFile} that it does not create a file for each cacheKey. - * Reading and writing new values does not cause multiple reads / writes on the file system and is therefore faster. - * The cache won't be invalidated after any time by default but when the tracker cache is cleared. This is usually the - * case when a new plugin is installed or an existing plugin or the core is updated. - * You should be careful when caching any data since we won't modify the cache key. So if your data depends on which - * plugins are activated or should not be available to each user than make sure to include unique names in the cache - * key such as the names of all loaded plugin names. - * If development mode is enabled in the config this cache acts as a {@link StaticCache}. Meaning it won't persist any - * data between requests. - */ -class PersistentCache -{ - /** - * @var CacheFile - */ - private static $storage = null; - private static $content = null; - private static $isDirty = false; - - private $cacheKey; - - /** - * Initializes the cache. - * @param string $cacheKey - */ - public function __construct($cacheKey) - { - $this->cacheKey = $cacheKey; - - if (is_null(self::$content)) { - self::$content = array(); - self::populateCache(); - } - } - - /** - * Overwrites a previously set cache key. Useful if you want to reuse the same instance for different cache keys - * for performance reasons. - * @param string $cacheKey - */ - public function setCacheKey($cacheKey) - { - $this->cacheKey = $cacheKey; - } - - /** - * Get the content related to the current cache key. Make sure to call the method {@link has()} to verify whether - * there is actually any content set under this cache key. - * @return mixed - */ - public function get() - { - return self::$content[$this->cacheKey]; - } - - /** - * Check whether any content was actually stored for the current cache key. - * @return bool - */ - public function has() - { - return array_key_exists($this->cacheKey, self::$content); - } - - /** - * Set (overwrite) any content related to the current set cache key. - * @param $content - */ - public function set($content) - { - self::$content[$this->cacheKey] = $content; - self::$isDirty = true; - } - - private static function populateCache() - { - if (Development::isEnabled()) { - return; - } - - if (SettingsServer::isTrackerApiRequest()) { - $eventToPersist = 'Tracker.end'; - $mode = '-tracker'; - } else { - $eventToPersist = 'Request.dispatch.end'; - $mode = '-ui'; - } - - $cache = self::getStorage()->get(self::getCacheFilename() . $mode); - - if (is_array($cache)) { - self::$content = $cache; - } - - Piwik::addAction($eventToPersist, array(__CLASS__, 'persistCache')); - } - - private static function getCacheFilename() - { - return 'StaticCache-' . str_replace(array('.', '-'), '', Version::VERSION); - } - - /** - * @ignore - */ - public static function persistCache() - { - if (self::$isDirty) { - if (SettingsServer::isTrackerApiRequest()) { - $mode = '-tracker'; - } else { - $mode = '-ui'; - } - - self::getStorage()->set(self::getCacheFilename() . $mode, self::$content); - } - } - - /** - * @ignore - */ - public static function _reset() - { - self::$content = array(); - } - - /** - * @return CacheFile - */ - private static function getStorage() - { - if (is_null(self::$storage)) { - self::$storage = new CacheFile('tracker', 43200); - self::$storage->addOnDeleteCallback(function () { - PersistentCache::_reset(); - }); - } - - return self::$storage; - } -} diff --git a/core/Cache/PluginAwareStaticCache.php b/core/Cache/PluginAwareStaticCache.php deleted file mode 100644 index 1bc3a25bd5..0000000000 --- a/core/Cache/PluginAwareStaticCache.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php -/** - * Piwik - free/libre analytics platform - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ -namespace Piwik\Cache; - -use Piwik\Plugin\Manager as PluginManager; -use Piwik\Translate; - -/** - * Caching class used for static caching which is plugin aware. It'll cache the given content depending on the plugins - * that are installed. This prevents you from having to invalidate the cache during tests in case the loaded plugins - * changes etc. The key is language aware as well. - * - * TODO convert this to a decorator... see {@link StaticCache} - */ -class PluginAwareStaticCache extends StaticCache -{ - protected function completeKey($cacheKey) - { - $pluginManager = PluginManager::getInstance(); - $pluginNames = $pluginManager->getLoadedPluginsName(); - $cacheKey = $cacheKey . md5(implode('', $pluginNames)) . Translate::getLanguageLoaded(); - - return $cacheKey; - } -} diff --git a/core/Cache/StaticCache.php b/core/Cache/StaticCache.php deleted file mode 100644 index 0c102e18d3..0000000000 --- a/core/Cache/StaticCache.php +++ /dev/null @@ -1,94 +0,0 @@ -<?php -/** - * Piwik - free/libre analytics platform - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ -namespace Piwik\Cache; - -/** - * Caching class used for static caching. Any content that is set here won't be cached between requests. If you do want - * to persist any content between requests have a look at {@link PersistentCache} - * - * TODO the default static cache should actually not be language aware. Especially since we would end up in classes like - * LanguageAwareStaticCache, PluginAwareStaticCache, PluginAwareLanguageAwareStaticCache, PluginAwareXYZStaticCache,... - * once we have dependency injection we should "build" all the caches we need removing duplicated code and extend the - * static cache by using decorators which "enrich" the cache key depending on their awareness. - */ -class StaticCache -{ - protected static $staticCache = array(); - - private $cacheKey; - - /** - * Initializes the cache. - * @param string $cacheKey - */ - public function __construct($cacheKey) - { - $this->setCacheKey($cacheKey); - } - - /** - * Overwrites a previously set cache key. Useful if you want to reuse the same instance for different cache keys - * for performance reasons. - * @param string $cacheKey - */ - public function setCacheKey($cacheKey) - { - $this->cacheKey = $this->completeKey($cacheKey); - } - - /** - * Get the content related to the current cache key. Make sure to call the method {@link has()} to verify whether - * there is actually any content set under this cache key. - * @return mixed - */ - public function get() - { - return self::$staticCache[$this->cacheKey]; - } - - /** - * Check whether any content was actually stored for the current cache key. - * @return bool - */ - public function has() - { - return array_key_exists($this->cacheKey, self::$staticCache); - } - - /** - * Reset the stored content of the current cache key. - */ - public function clear() - { - unset(self::$staticCache[$this->cacheKey]); - } - - /** - * Reset the stored content of the current cache key. - * @ignore - */ - public static function clearAll() - { - self::$staticCache = array(); - } - - /** - * Set (overwrite) any content related to the current set cache key. - * @param $content - */ - public function set($content) - { - self::$staticCache[$this->cacheKey] = $content; - } - - protected function completeKey($cacheKey) - { - return $cacheKey; - } -}
\ No newline at end of file diff --git a/core/CacheFile.php b/core/CacheFile.php deleted file mode 100644 index b8ec14c575..0000000000 --- a/core/CacheFile.php +++ /dev/null @@ -1,237 +0,0 @@ -<?php -/** - * Piwik - free/libre analytics platform - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - * - */ -namespace Piwik; - -use Exception; -use Piwik\Container\StaticContainer; - -/** - * This class is used to cache data on the filesystem. - * - * It is for example used by the Tracker process to cache various settings and websites attributes in tmp/cache/tracker/* - * - */ -class CacheFile -{ - // for testing purposes since tests run on both CLI/FPM (changes in CLI can't invalidate - // opcache in FPM, so we have to invalidate before reading) - public static $invalidateOpCacheBeforeRead = false; - - /** - * @var string - */ - private $cachePath; - - /** - * Minimum enforced TTL in seconds - */ - const MINIMUM_TTL = 60; - - /** - * @var \Callable[] - */ - private static $onDeleteCallback = array(); - - /** - * @param string $directory directory to use - * @param int $timeToLiveInSeconds TTL - */ - public function __construct($directory, $timeToLiveInSeconds = 300) - { - $this->cachePath = StaticContainer::getContainer()->get('path.tmp') . '/cache/' . $directory . '/'; - - if ($timeToLiveInSeconds < self::MINIMUM_TTL) { - $timeToLiveInSeconds = self::MINIMUM_TTL; - } - $this->ttl = $timeToLiveInSeconds; - } - - /** - * Function to fetch a cache entry - * - * @param string $id The cache entry ID - * @return array|bool False on error, or array the cache content - */ - public function get($id) - { - if (empty($id)) { - return false; - } - - $id = $this->cleanupId($id); - - $cache_complete = false; - $content = ''; - $expires_on = false; - - // We are assuming that most of the time cache will exists - $cacheFilePath = $this->cachePath . $id . '.php'; - if (self::$invalidateOpCacheBeforeRead) { - $this->opCacheInvalidate($cacheFilePath); - } - - $ok = @include($cacheFilePath); - - if ($ok && $cache_complete == true) { - - if (empty($expires_on) - || $expires_on < time() - ) { - return false; - } - - return $content; - } - - return false; - } - - private function getExpiresTime() - { - return time() + $this->ttl; - } - - protected function cleanupId($id) - { - if (!Filesystem::isValidFilename($id)) { - throw new Exception("Invalid cache ID request $id"); - } - - return $id; - } - - /** - * A function to store content a cache entry. - * - * @param string $id The cache entry ID - * @param array $content The cache content - * @throws \Exception - * @return bool True if the entry was succesfully stored - */ - public function set($id, $content) - { - if (empty($id)) { - return false; - } - - if (!is_dir($this->cachePath)) { - Filesystem::mkdir($this->cachePath); - } - - if (!is_writable($this->cachePath)) { - return false; - } - - $id = $this->cleanupId($id); - $id = $this->cachePath . $id . '.php'; - - if (is_object($content)) { - throw new \Exception('You cannot use the CacheFile to cache an object, only arrays, strings and numbers.'); - } - - $cache_literal = $this->buildCacheLiteral($content); - - // Write cache to a temp file, then rename it, overwriting the old cache - // On *nix systems this should guarantee atomicity - $tmp_filename = tempnam($this->cachePath, 'tmp_'); - @chmod($tmp_filename, 0640); - if ($fp = @fopen($tmp_filename, 'wb')) { - @fwrite($fp, $cache_literal, strlen($cache_literal)); - @fclose($fp); - - if (!@rename($tmp_filename, $id)) { - // On some systems rename() doesn't overwrite destination - @unlink($id); - if (!@rename($tmp_filename, $id)) { - // Make sure that no temporary file is left over - // if the destination is not writable - @unlink($tmp_filename); - } - } - - $this->opCacheInvalidate($id); - - return true; - } - - return false; - } - - /** - * A function to delete a single cache entry - * - * @param string $id The cache entry ID - * @return bool True if the entry was succesfully deleted - */ - public function delete($id) - { - if (empty($id)) { - return false; - } - - $id = $this->cleanupId($id); - - $filename = $this->cachePath . $id . '.php'; - - if (file_exists($filename)) { - $this->opCacheInvalidate($filename); - @unlink($filename); - return true; - } - - return false; - } - - public function addOnDeleteCallback($onDeleteCallback) - { - self::$onDeleteCallback[] = $onDeleteCallback; - } - - /** - * A function to delete all cache entries in the directory - */ - public function deleteAll() - { - $self = $this; - $beforeUnlink = function ($path) use ($self) { - $self->opCacheInvalidate($path); - }; - - Filesystem::unlinkRecursive($this->cachePath, $deleteRootToo = false, $beforeUnlink); - - if (!empty(self::$onDeleteCallback)) { - foreach (self::$onDeleteCallback as $callback) { - $callback(); - } - } - } - - public function opCacheInvalidate($filepath) - { - if (is_file($filepath)) { - if (function_exists('opcache_invalidate')) { - @opcache_invalidate($filepath, $force = true); - } - if (function_exists('apc_delete_file')) { - @apc_delete_file($filepath); - } - } - } - - private function buildCacheLiteral($content) - { - $cache_literal = "<" . "?php\n"; - $cache_literal .= "$" . "content = " . var_export($content, true) . ";\n"; - $cache_literal .= "$" . "expires_on = " . $this->getExpiresTime() . ";\n"; - $cache_literal .= "$" . "cache_complete = true;\n"; - $cache_literal .= "?" . ">"; - - return $cache_literal; - } -} diff --git a/core/CacheId.php b/core/CacheId.php new file mode 100644 index 0000000000..e445424009 --- /dev/null +++ b/core/CacheId.php @@ -0,0 +1,30 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ +namespace Piwik; + +use Piwik\Translate; +use Piwik\Plugin\Manager; + +class CacheId +{ + public static function languageAware($cacheId) + { + return $cacheId . '-' . Translate::getLanguageLoaded(); + } + + public static function pluginAware($cacheId) + { + $pluginManager = Manager::getInstance(); + $pluginNames = $pluginManager->getLoadedPluginsName(); + $cacheId = $cacheId . '-' . md5(implode('', $pluginNames)); + $cacheId = self::languageAware($cacheId); + + return $cacheId; + } +} diff --git a/core/Columns/Updater.php b/core/Columns/Updater.php index 6c42ba0dff..4272f46f56 100644 --- a/core/Columns/Updater.php +++ b/core/Columns/Updater.php @@ -14,14 +14,16 @@ use Piwik\Plugin\Dimension\VisitDimension; use Piwik\Plugin\Dimension\ConversionDimension; use Piwik\Db; use Piwik\Updater as PiwikUpdater; -use Piwik\Cache\PersistentCache; use Piwik\Filesystem; +use Piwik\Cache as PiwikCache; /** * Class that handles dimension updates */ class Updater extends \Piwik\Updates { + private static $cacheId = 'AllDimensionModifyTime'; + /** * @var Updater */ @@ -315,15 +317,22 @@ class Updater extends \Piwik\Updates private static function cacheCurrentDimensionFileChanges() { $changes = self::getCurrentDimensionFileChanges(); - $persistentCache = new PersistentCache('AllDimensionModifyTime'); - $persistentCache->set($changes); + + $cache = self::buildCache(); + $cache->save(self::$cacheId, $changes); + } + + private static function buildCache() + { + return PiwikCache::getEagerCache(); } private static function getCachedDimensionFileChanges() { - $persistentCache = new PersistentCache('AllDimensionModifyTime'); - if ($persistentCache->has()) { - return $persistentCache->get(); + $cache = self::buildCache(); + + if ($cache->contains(self::$cacheId)) { + return $cache->fetch(self::$cacheId); } return array(); diff --git a/core/Container/StaticContainer.php b/core/Container/StaticContainer.php index b46f01e1ca..4e09d2bdb7 100644 --- a/core/Container/StaticContainer.php +++ b/core/Container/StaticContainer.php @@ -39,6 +39,11 @@ class StaticContainer return self::$container; } + public static function clearContainer() + { + self::$container = null; + } + /** * @link http://php-di.org/doc/container-configuration.html */ diff --git a/core/DeviceDetectorCache.php b/core/DeviceDetectorCache.php index ba65b82c9f..c337b1b0a4 100644 --- a/core/DeviceDetectorCache.php +++ b/core/DeviceDetectorCache.php @@ -8,6 +8,7 @@ */ namespace Piwik; +use Piwik\Cache as PiwikCache; use Exception; /** @@ -17,10 +18,19 @@ use Exception; * * Static caching speeds up multiple detections in one request, which is the case when sending bulk requests */ -class DeviceDetectorCache extends CacheFile implements \DeviceDetector\Cache\CacheInterface +class DeviceDetectorCache implements \DeviceDetector\Cache\CacheInterface { protected static $staticCache = array(); + private $cache; + private $ttl; + + public function __construct($ttl = 300) + { + $this->ttl = (int) $ttl; + $this->cache = PiwikCache::getLazyCache(); + } + /** * Function to fetch a cache entry * @@ -33,13 +43,11 @@ class DeviceDetectorCache extends CacheFile implements \DeviceDetector\Cache\Cac return false; } - $id = $this->cleanupId($id); - if (array_key_exists($id, self::$staticCache)) { return self::$staticCache[$id]; } - return parent::get($id); + return $this->cache->fetch($id); } /** @@ -56,10 +64,9 @@ class DeviceDetectorCache extends CacheFile implements \DeviceDetector\Cache\Cac return false; } - $id = $this->cleanupId($id); - self::$staticCache[$id] = $content; - return parent::set($id, $content); + return $this->cache->save($id, $content, $this->ttl); } + } diff --git a/core/DeviceDetectorFactory.php b/core/DeviceDetectorFactory.php index c61da87a14..c7962a96f0 100644 --- a/core/DeviceDetectorFactory.php +++ b/core/DeviceDetectorFactory.php @@ -28,7 +28,7 @@ class DeviceDetectorFactory $deviceDetector = new DeviceDetector($userAgent); $deviceDetector->discardBotInformation(); - $deviceDetector->setCache(new DeviceDetectorCache('tracker', 86400)); + $deviceDetector->setCache(new DeviceDetectorCache(86400)); $deviceDetector->parse(); self::$deviceDetectorInstances[$userAgent] = $deviceDetector; diff --git a/core/Filesystem.php b/core/Filesystem.php index 125c47bfda..05e659a4bb 100644 --- a/core/Filesystem.php +++ b/core/Filesystem.php @@ -11,6 +11,7 @@ namespace Piwik; use Exception; use Piwik\Container\StaticContainer; use Piwik\Tracker\Cache; +use Piwik\Cache as PiwikCache; /** * Contains helper functions that deal with the filesystem. @@ -27,6 +28,7 @@ class Filesystem AssetManager::getInstance()->removeMergedAssets($pluginName); View::clearCompiledTemplates(); Cache::deleteTrackerCache(); + PiwikCache::flushAll(); self::clearPhpCaches(); } diff --git a/core/Metrics.php b/core/Metrics.php index 009fa36151..e76e8dd5e9 100644 --- a/core/Metrics.php +++ b/core/Metrics.php @@ -8,8 +8,7 @@ */ namespace Piwik; -use Piwik\Cache\LanguageAwareStaticCache; -use Piwik\Cache\PluginAwareStaticCache; +use Piwik\Cache as PiwikCache; use Piwik\Metrics\Formatter; require_once PIWIK_INCLUDE_PATH . "/core/Piwik.php"; @@ -250,10 +249,11 @@ class Metrics public static function getDefaultMetricTranslations() { - $cache = new PluginAwareStaticCache('DefaultMetricTranslations'); + $cacheId = CacheId::pluginAware('DefaultMetricTranslations'); + $cache = PiwikCache::getTransientCache(); - if ($cache->has()) { - return $cache->get(); + if ($cache->contains($cacheId)) { + return $cache->fetch($cacheId); } $translations = array( @@ -302,17 +302,18 @@ class Metrics $translations = array_map(array('\\Piwik\\Piwik','translate'), $translations); - $cache->set($translations); + $cache->save($cacheId, $translations); return $translations; } public static function getDefaultMetrics() { - $cache = new LanguageAwareStaticCache('DefaultMetrics'); + $cacheId = CacheId::languageAware('DefaultMetrics'); + $cache = PiwikCache::getTransientCache(); - if ($cache->has()) { - return $cache->get(); + if ($cache->contains($cacheId)) { + return $cache->fetch($cacheId); } $translations = array( @@ -323,17 +324,18 @@ class Metrics ); $translations = array_map(array('\\Piwik\\Piwik','translate'), $translations); - $cache->set($translations); + $cache->save($cacheId, $translations); return $translations; } public static function getDefaultProcessedMetrics() { - $cache = new LanguageAwareStaticCache('DefaultProcessedMetrics'); + $cacheId = CacheId::languageAware('DefaultProcessedMetrics'); + $cache = PiwikCache::getTransientCache(); - if ($cache->has()) { - return $cache->get(); + if ($cache->contains($cacheId)) { + return $cache->fetch($cacheId); } $translations = array( @@ -345,7 +347,7 @@ class Metrics ); $translations = array_map(array('\\Piwik\\Piwik','translate'), $translations); - $cache->set($translations); + $cache->save($cacheId, $translations); return $translations; } @@ -383,10 +385,11 @@ class Metrics public static function getDefaultMetricsDocumentation() { - $cache = new PluginAwareStaticCache('DefaultMetricsDocumentation'); + $cacheId = CacheId::pluginAware('DefaultMetricsDocumentation'); + $cache = PiwikCache::getTransientCache(); - if ($cache->has()) { - return $cache->get(); + if ($cache->contains($cacheId)) { + return $cache->fetch($cacheId); } $translations = array( @@ -412,7 +415,7 @@ class Metrics $translations = array_map(array('\\Piwik\\Piwik','translate'), $translations); - $cache->set($translations); + $cache->save($cacheId, $translations); return $translations; } diff --git a/core/Plugin.php b/core/Plugin.php index f30c3ed23a..75ebb5a021 100644 --- a/core/Plugin.php +++ b/core/Plugin.php @@ -8,7 +8,6 @@ */ namespace Piwik; -use Piwik\Cache\PersistentCache; use Piwik\Plugin\Dependency; use Piwik\Plugin\MetadataLoader; @@ -108,10 +107,10 @@ class Plugin /** * As the cache is used quite often we avoid having to create instances all the time. We reuse it which is not - * perfect but efficient. If the cache is used we need to make sure to call setCacheKey() before usage as there + * perfect but efficient. If the cache is used we need to make sure to call setId() before usage as there * is maybe a different key set since last usage. * - * @var PersistentCache + * @var \Piwik\Cache\Eager */ private $cache; @@ -131,12 +130,12 @@ class Plugin } $this->pluginName = $pluginName; - $cache = new PersistentCache('Plugin' . $pluginName . 'Metadata'); + $cacheId = 'Plugin' . $pluginName . 'Metadata'; + $cache = Cache::getEagerCache($cacheId); - if ($cache->has()) { - $this->pluginInformation = $cache->get(); + if ($cache->contains($cacheId)) { + $this->pluginInformation = $cache->fetch($cacheId); } else { - $metadataLoader = new MetadataLoader($pluginName); $this->pluginInformation = $metadataLoader->load(); @@ -144,14 +143,14 @@ class Plugin throw new \Exception('Plugin ' . $pluginName . ' has defined the method getInformation() and as well as having a plugin.json file. Please delete the getInformation() method from the plugin class. Alternatively, you may delete the plugin directory from plugins/' . $pluginName); } - $cache->set($this->pluginInformation); + $cache->save($cacheId, $this->pluginInformation); } } private function createCacheIfNeeded() { if (is_null($this->cache)) { - $this->cache = new PersistentCache('Plugin' . $this->pluginName); + $this->cache = Cache::getEagerCache(); } } @@ -321,12 +320,12 @@ class Plugin { $this->createCacheIfNeeded(); - $this->cache->setCacheKey('Plugin' . $this->pluginName . $componentName . $expectedSubclass); + $cacheId = 'Plugin' . $this->pluginName . $componentName . $expectedSubclass; $componentFile = sprintf('%s/plugins/%s/%s.php', PIWIK_INCLUDE_PATH, $this->pluginName, $componentName); - if ($this->cache->has()) { - $klassName = $this->cache->get(); + if ($this->cache->contains($cacheId)) { + $klassName = $this->cache->fetch($cacheId); if (empty($klassName)) { return; // might by "false" in case has no menu, widget, ... @@ -337,7 +336,7 @@ class Plugin } } else { - $this->cache->set(false); // prevent from trying to load over and over again for instance if there is no Menu for a plugin + $this->cache->save($cacheId, false); // prevent from trying to load over and over again for instance if there is no Menu for a plugin if (!file_exists($componentFile)) { return; @@ -357,7 +356,7 @@ class Plugin return; } - $this->cache->set($klassName); + $this->cache->save($cacheId, $klassName); } return new $klassName; @@ -367,10 +366,10 @@ class Plugin { $this->createCacheIfNeeded(); - $this->cache->setCacheKey('Plugin' . $this->pluginName . $directoryWithinPlugin . $expectedSubclass); + $cacheId = 'Plugin' . $this->pluginName . $directoryWithinPlugin . $expectedSubclass; - if ($this->cache->has()) { - $components = $this->cache->get(); + if ($this->cache->contains($cacheId)) { + $components = $this->cache->fetch($cacheId); if ($this->includeComponents($components)) { return $components; @@ -381,7 +380,7 @@ class Plugin $components = $this->doFindMultipleComponents($directoryWithinPlugin, $expectedSubclass); - $this->cache->set($components); + $this->cache->save($cacheId, $components); return $components; } diff --git a/core/Plugin/Dimension/ActionDimension.php b/core/Plugin/Dimension/ActionDimension.php index bc09b01fc3..f0daaf547c 100644 --- a/core/Plugin/Dimension/ActionDimension.php +++ b/core/Plugin/Dimension/ActionDimension.php @@ -8,7 +8,8 @@ */ namespace Piwik\Plugin\Dimension; -use Piwik\Cache\PluginAwareStaticCache; +use Piwik\CacheId; +use Piwik\Cache as PiwikCache; use Piwik\Columns\Dimension; use Piwik\Plugin\Manager as PluginManager; use Piwik\Plugin\Segment; @@ -212,9 +213,10 @@ abstract class ActionDimension extends Dimension */ public static function getAllDimensions() { - $cache = new PluginAwareStaticCache('ActionDimensions'); + $cacheId = CacheId::pluginAware('ActionDimensions'); + $cache = PiwikCache::getTransientCache(); - if (!$cache->has()) { + if (!$cache->contains($cacheId)) { $plugins = PluginManager::getInstance()->getPluginsLoadedAndActivated(); $instances = array(); @@ -225,10 +227,10 @@ abstract class ActionDimension extends Dimension } } - $cache->set($instances); + $cache->save($cacheId, $instances); } - return $cache->get(); + return $cache->fetch($cacheId); } /** diff --git a/core/Plugin/Dimension/ConversionDimension.php b/core/Plugin/Dimension/ConversionDimension.php index 7cf2a813c0..34a8006111 100644 --- a/core/Plugin/Dimension/ConversionDimension.php +++ b/core/Plugin/Dimension/ConversionDimension.php @@ -8,7 +8,8 @@ */ namespace Piwik\Plugin\Dimension; -use Piwik\Cache\PluginAwareStaticCache; +use Piwik\CacheId; +use Piwik\Cache as PiwikCache; use Piwik\Columns\Dimension; use Piwik\Plugin\Manager as PluginManager; use Piwik\Common; @@ -155,9 +156,10 @@ abstract class ConversionDimension extends Dimension */ public static function getAllDimensions() { - $cache = new PluginAwareStaticCache('ConversionDimensions'); + $cacheId = CacheId::pluginAware('ConversionDimensions'); + $cache = PiwikCache::getTransientCache(); - if (!$cache->has()) { + if (!$cache->contains($cacheId)) { $plugins = PluginManager::getInstance()->getPluginsLoadedAndActivated(); $instances = array(); @@ -168,10 +170,10 @@ abstract class ConversionDimension extends Dimension } } - $cache->set($instances); + $cache->save($cacheId, $instances); } - return $cache->get(); + return $cache->fetch($cacheId); } /** diff --git a/core/Plugin/Dimension/VisitDimension.php b/core/Plugin/Dimension/VisitDimension.php index b9aa3a9b2a..97dfd6f57b 100644 --- a/core/Plugin/Dimension/VisitDimension.php +++ b/core/Plugin/Dimension/VisitDimension.php @@ -8,7 +8,8 @@ */ namespace Piwik\Plugin\Dimension; -use Piwik\Cache\PluginAwareStaticCache; +use Piwik\CacheId; +use Piwik\Cache as PiwikCache; use Piwik\Columns\Dimension; use Piwik\Common; use Piwik\Db; @@ -294,9 +295,10 @@ abstract class VisitDimension extends Dimension */ public static function getAllDimensions() { - $cache = new PluginAwareStaticCache('VisitDimensions'); + $cacheId = CacheId::pluginAware('VisitDimensions'); + $cache = PiwikCache::getTransientCache(); - if (!$cache->has()) { + if (!$cache->contains($cacheId)) { $plugins = PluginManager::getInstance()->getPluginsLoadedAndActivated(); $instances = array(); @@ -309,10 +311,10 @@ abstract class VisitDimension extends Dimension usort($instances, array('self', 'sortByRequiredFields')); - $cache->set($instances); + $cache->save($cacheId, $instances); } - return $cache->get(); + return $cache->fetch($cacheId); } /** diff --git a/core/Plugin/Manager.php b/core/Plugin/Manager.php index a85784f6d4..bca24d8b5a 100644 --- a/core/Plugin/Manager.php +++ b/core/Plugin/Manager.php @@ -9,8 +9,7 @@ namespace Piwik\Plugin; -use Piwik\Cache\PersistentCache; -use Piwik\CacheFile; +use Piwik\Cache; use Piwik\Columns\Dimension; use Piwik\Common; use Piwik\Config as PiwikConfig; @@ -119,10 +118,11 @@ class Manager extends Singleton */ public function loadTrackerPlugins() { - $cache = new PersistentCache('PluginsTracker'); + $cacheId = 'PluginsTracker'; + $cache = Cache::getEagerCache(); - if ($cache->has()) { - $pluginsTracker = $cache->get(); + if ($cache->contains($cacheId)) { + $pluginsTracker = $cache->fetch($cacheId); } else { $this->unloadPlugins(); @@ -137,7 +137,7 @@ class Manager extends Singleton } if (!empty($pluginsTracker)) { - $cache->set($pluginsTracker); + $cache->save($cacheId, $pluginsTracker); } } @@ -697,7 +697,6 @@ class Manager extends Singleton $language = Translate::getLanguageToLoad(); } - $cache = new CacheFile('tracker', 43200); // ttl=12hours $cacheKey = 'PluginTranslations'; if (!empty($language)) { @@ -709,11 +708,12 @@ class Manager extends Singleton $cacheKey .= '-' . md5(implode('', $this->getLoadedPluginsName())); } - $translations = $cache->get($cacheKey); + $cache = Cache::getLazyCache(); + $translations = $cache->fetch($cacheKey); if (!empty($translations) && is_array($translations) && - !Development::isEnabled()) { + !Development::isEnabled()) { // TODO remove this one here once we have environments in DI Translate::mergeTranslationArray($translations); return; @@ -734,7 +734,7 @@ class Manager extends Singleton } } - $cache->set($cacheKey, $translations); + $cache->save($cacheKey, $translations, 43200); // ttl=12hours } /** diff --git a/core/Plugin/Report.php b/core/Plugin/Report.php index 1824b6774f..af61a33a0a 100644 --- a/core/Plugin/Report.php +++ b/core/Plugin/Report.php @@ -10,11 +10,12 @@ namespace Piwik\Plugin; use Piwik\API\Proxy; use Piwik\API\Request; -use Piwik\Cache\LanguageAwareStaticCache; +use Piwik\CacheId; use Piwik\Columns\Dimension; use Piwik\DataTable; use Piwik\Menu\MenuReporting; use Piwik\Metrics; +use Piwik\Cache as PiwikCache; use Piwik\Piwik; use Piwik\Plugin\Manager as PluginManager; use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable; @@ -735,9 +736,10 @@ class Report public static function getAllReports() { $reports = self::getAllReportClasses(); - $cache = new LanguageAwareStaticCache('Reports' . implode('', $reports)); + $cacheId = CacheId::languageAware('Reports' . md5(implode('', $reports))); + $cache = PiwikCache::getTransientCache(); - if (!$cache->has()) { + if (!$cache->contains($cacheId)) { $instances = array(); foreach ($reports as $report) { @@ -746,10 +748,10 @@ class Report usort($instances, array('self', 'sort')); - $cache->set($instances); + $cache->save($cacheId, $instances); } - return $cache->get(); + return $cache->fetch($cacheId); } /** @@ -785,10 +787,10 @@ class Report foreach ($metricsToTranslate as $metric) { if ($metric instanceof Metric) { - $metricName = $metric->getName(); + $metricName = $metric->getName(); $translation = $metric->getTranslatedName(); } else { - $metricName = $metric; + $metricName = $metric; $translation = @$translations[$metric]; } diff --git a/core/Tracker/Cache.php b/core/Tracker/Cache.php index b8f0413c63..a29427fd8b 100644 --- a/core/Tracker/Cache.php +++ b/core/Tracker/Cache.php @@ -10,7 +10,7 @@ namespace Piwik\Tracker; use Piwik\Access; use Piwik\ArchiveProcessor\Rules; -use Piwik\CacheFile; +use Piwik\Cache as PiwikCache; use Piwik\Common; use Piwik\Config; use Piwik\Option; @@ -23,19 +23,29 @@ use Piwik\Tracker; */ class Cache { + private static $cacheIdGeneral = 'general'; + /** * Public for tests only - * @var CacheFile + * @var \Piwik\Cache\Lazy */ - public static $trackerCache = null; + public static $cache; - protected static function getInstance() + /** + * @return \Piwik\Cache\Lazy + */ + private static function getCache() { - if (is_null(self::$trackerCache)) { - $ttl = Config::getInstance()->Tracker['tracker_cache_file_ttl']; - self::$trackerCache = new CacheFile('tracker', $ttl); + if (is_null(self::$cache)) { + self::$cache = PiwikCache::getLazyCache(); } - return self::$trackerCache; + + return self::$cache; + } + + private static function getTtl() + { + return Config::getInstance()->Tracker['tracker_cache_file_ttl']; } /** @@ -55,8 +65,9 @@ class Cache return array(); } - $cache = self::getInstance(); - $cacheContent = $cache->get($idSite); + $cache = self::getCache(); + $cacheId = (int) $idSite; + $cacheContent = $cache->fetch($cacheId); if (false !== $cacheContent) { return $cacheContent; @@ -91,7 +102,7 @@ class Cache // if nothing is returned from the plugins, we don't save the content // this is not expected: all websites are expected to have at least one URL if (!empty($content)) { - $cache->set($idSite, $content); + $cache->save($cacheId, $content, self::getTtl()); } return $content; @@ -102,7 +113,7 @@ class Cache */ public static function clearCacheGeneral() { - self::getInstance()->delete('general'); + self::getCache()->delete(self::$cacheIdGeneral); } /** @@ -113,10 +124,8 @@ class Cache */ public static function getCacheGeneral() { - $cache = self::getInstance(); - $cacheId = 'general'; - - $cacheContent = $cache->get($cacheId); + $cache = self::getCache(); + $cacheContent = $cache->fetch(self::$cacheIdGeneral); if (false !== $cacheContent) { return $cacheContent; @@ -162,11 +171,9 @@ class Cache */ public static function setCacheGeneral($value) { - $cache = self::getInstance(); - $cacheId = 'general'; - $cache->set($cacheId, $value); + $cache = self::getCache(); - return true; + return $cache->save(self::$cacheIdGeneral, $value, self::getTtl()); } /** @@ -193,8 +200,7 @@ class Cache */ public static function deleteCacheWebsiteAttributes($idSite) { - $idSite = (int)$idSite; - self::getInstance()->delete($idSite); + self::getCache()->delete((int) $idSite); } /** @@ -202,6 +208,6 @@ class Cache */ public static function deleteTrackerCache() { - self::getInstance()->deleteAll(); + self::getCache()->flushAll(); } } diff --git a/core/Tracker/SettingsStorage.php b/core/Tracker/SettingsStorage.php index 2e3ac5e17d..7ffb3de872 100644 --- a/core/Tracker/SettingsStorage.php +++ b/core/Tracker/SettingsStorage.php @@ -9,9 +9,9 @@ namespace Piwik\Tracker; -use Piwik\Cache\PersistentCache; use Piwik\Settings\Storage; use Piwik\Tracker; +use Piwik\Cache as PiwikCache; /** * Loads settings from tracker cache instead of database. If not yet present in tracker cache will cache it. @@ -20,14 +20,15 @@ class SettingsStorage extends Storage { protected function loadSettings() { + $cacheId = $this->getOptionKey(); $cache = $this->getCache(); - if ($cache->has()) { - $settings = $cache->get(); + if ($cache->contains($cacheId)) { + $settings = $cache->fetch($cacheId); } else { $settings = parent::loadSettings(); - $cache->set($settings); + $cache->save($cacheId, $settings); } return $settings; @@ -41,13 +42,18 @@ class SettingsStorage extends Storage private function getCache() { - return new PersistentCache($this->getOptionKey()); + return self::buildCache($this->getOptionKey()); } public static function clearCache() { Cache::deleteTrackerCache(); - PersistentCache::_reset(); + self::buildCache()->flushAll(); + } + + private static function buildCache() + { + return PiwikCache::getEagerCache(); } } diff --git a/core/WidgetsList.php b/core/WidgetsList.php index 943dfceb68..c474061606 100644 --- a/core/WidgetsList.php +++ b/core/WidgetsList.php @@ -8,7 +8,7 @@ */ namespace Piwik; -use Piwik\Cache\PluginAwareStaticCache; +use Piwik\Cache as PiwikCache; use Piwik\Plugin\Report; use Piwik\Plugin\Widgets; @@ -63,9 +63,11 @@ class WidgetsList extends Singleton */ public static function get() { - $cache = self::getCacheForCompleteList(); - if (!self::$listCacheToBeInvalidated && $cache->has()) { - return $cache->get(); + $cache = self::getCacheForCompleteList(); + $cacheId = self::getCacheId(); + + if (!self::$listCacheToBeInvalidated && $cache->contains($cacheId)) { + return $cache->fetch($cacheId); } self::addWidgets(); @@ -83,7 +85,7 @@ class WidgetsList extends Singleton $widgets[$category] = $v; } - $cache->set($widgets); + $cache->save($cacheId, $widgets); self::$listCacheToBeInvalidated = false; return $widgets; @@ -270,11 +272,16 @@ class WidgetsList extends Singleton { self::$widgets = array(); self::$hookCalled = false; - self::getCacheForCompleteList()->clear(); + self::getCacheForCompleteList()->delete(self::getCacheId()); + } + + private static function getCacheId() + { + return CacheId::pluginAware('WidgetsList'); } private static function getCacheForCompleteList() { - return new PluginAwareStaticCache('WidgetsList'); + return PiwikCache::getTransientCache(); } } |