Major overhaul of caching system (work in progress)
authorAlexander Ebert <ebert@woltlab.com>
Sun, 3 Feb 2013 22:47:36 +0000 (23:47 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 3 Feb 2013 22:47:36 +0000 (23:47 +0100)
See #1124

15 files changed:
com.woltlab.wcf/option.xml
wcfsetup/install/files/js/WCF.js
wcfsetup/install/files/lib/system/WCF.class.php
wcfsetup/install/files/lib/system/cache/CacheHandler.class.php
wcfsetup/install/files/lib/system/cache/builder/AbstractCacheBuilder.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/cache/builder/ICacheBuilder.class.php
wcfsetup/install/files/lib/system/cache/source/ApcCacheSource.class.php
wcfsetup/install/files/lib/system/cache/source/DiskCacheSource.class.php
wcfsetup/install/files/lib/system/cache/source/ICacheSource.class.php
wcfsetup/install/files/lib/system/cache/source/MemcachedAdapter.class.php [deleted file]
wcfsetup/install/files/lib/system/cache/source/MemcachedCacheSource.class.php
wcfsetup/install/files/lib/system/cache/source/NoCacheSource.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml
wcfsetup/setup/db/install.sql

index 9943fb60bccba4cef769d5a7cf71855314e378d7..bb62172a54568a25d095677737931da510be0d93 100644 (file)
@@ -388,10 +388,10 @@ debug:mail_debug_logfile_path,!mail_use_f_param,!mail_smtp_host,!mail_smtp_port,
 memcached:wcf.acp.option.cache_source_type.memcached
 apc:wcf.acp.option.cache_source_type.apc
 no:wcf.acp.option.cache_source_type.no]]></selectoptions>
-                               <enableoptions><![CDATA[disk:!cache_source_memcached_host,!cache_source_memcached_use_pconnect
-memcached:cache_source_memcached_host,cache_source_memcached_use_pconnect
-apc:!cache_source_memcached_host,!cache_source_memcached_use_pconnect
-no:!cache_source_memcached_host,!cache_source_memcached_use_pconnect]]></enableoptions>
+                               <enableoptions><![CDATA[disk:!cache_source_memcached_host
+memcached:cache_source_memcached_host
+apc:!cache_source_memcached_host
+no:!cache_source_memcached_host]]></enableoptions>
                        </option>
                        
                        <option name="cache_source_memcached_host">
index 99a1f5322e6d53b96922eb36988c3869d1c786a5..ac0fde47d5d371bfa62d103c4d219c35586bc1c9 100755 (executable)
@@ -6257,7 +6257,7 @@ WCF.Popover = Class.extend({
         * @var object
         */
        _delay: {
-               show: 250,
+               show: 800,
                hide: 500
        },
        
@@ -6341,7 +6341,7 @@ WCF.Popover = Class.extend({
                        y: 'top'
                };
                this._delay = {
-                       show: 250,
+                       show: 800,
                        hide: 500
                };
                this._hoverElement = false;
index 2174b0d358def1faa94d4094d6b1723a5ce27a11..03514eab69bf38514ced8dc6e81b47aeb629e4ab 100644 (file)
@@ -145,11 +145,6 @@ class WCF {
                                self::getSession()->update();
                        }
                        
-                       // close cache source
-                       if (CacheHandler::isInitialized() && is_object(CacheHandler::getInstance()) && is_object(CacheHandler::getInstance()->getCacheSource())) {
-                               CacheHandler::getInstance()->getCacheSource()->close();
-                       }
-                       
                        // execute shutdown actions of user storage handler
                        UserStorageHandler::getInstance()->shutdown();
                }
index 1cd4633859dc445db49d54f6abe511d378ec86d3..9ab1be24bc26247141e4eae4afc7d740b73b0ef6 100644 (file)
@@ -1,26 +1,22 @@
 <?php
 namespace wcf\system\cache;
+use wcf\system\cache\builder\ICacheBuilder;
 use wcf\system\cache\source\DiskCacheSource;
 use wcf\system\exception\SystemException;
 use wcf\system\SingletonFactory;
+use wcf\util\StringUtil;
 
 /**
- * CacheHandler holds all registered cache resources.
+ * Manages transparent cache access.
  * 
- * @author     Marcel Werk
- * @copyright  2001-2012 WoltLab GmbH
+ * @author     Alexander Ebert, Marcel Werk
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.cache
  * @category   Community Framework
  */
 class CacheHandler extends SingletonFactory {
-       /**
-        * registered cache resources
-        * @var array
-        */
-       protected $cacheResources = array();
-       
        /**
         * cache source object
         * @var wcf\system\cache\source\ICacheSource
@@ -48,108 +44,64 @@ class CacheHandler extends SingletonFactory {
        }
        
        /**
-        * Registers a new cache resource.
+        * Flushed cache for given resource.
         * 
-        * @param       string          $cache          name of this resource
-        * @param       string          $file           data file for this resource
-        * @param       string          $className
-        * @param       integer         $maxLifetime
+        * @param       wcf\system\cache\builder\ICacheBuilder          $cacheBuilder
+        * @param       array                                           $parameters
         */
-       public function addResource($cache, $file, $className, $maxLifetime = 0) {
-               $this->cacheResources[$cache] = array(
-                       'cache' => $cache,
-                       'file' => $file, 
-                       'className' => $className, 
-                       'maxLifetime' => $maxLifetime
-               );
+       public function flush(ICacheBuilder $cacheBuilder, array $parameters) {
+               $useWildCard = (empty($parameters)) ? false : true;
+               $this->getCacheSource()->flush($this->getCacheName($cacheBuilder), $useWildCard);
        }
        
        /**
-        * Deletes a registered cache resource.
+        * Returns cached value for given resource, false if no cache exists.
         * 
-        * @param       string          $cache
+        * @param       wcf\system\cache\builder\ICacheBuilder          $cacheBuilder
+        * @param       array                                           $parameters
+        * @return      mixed
         */
-       public function clearResource($cache) {
-               if (!isset($this->cacheResources[$cache])) {
-                       throw new SystemException("cache resource '".$cache."' does not exist");
-               }
-               
-               $this->getCacheSource()->delete($this->cacheResources[$cache]);
+       public function get(ICacheBuilder $cacheBuilder, array $parameters) {
+               return $this->getCacheSource()->get($this->getCacheName($cacheBuilder, $parameters), $cacheBuilder->getMaxLifetime());
        }
        
        /**
-        * Marks cached files as obsolete.
+        * Caches a value for given resource,
         * 
-        * @param       string          $directory
-        * @param       string          $filepattern
+        * @param       wcf\system\cache\builder\ICacheBuilder          $cacheBuilder
+        * @param       array                                           $parameters
+        * @param       array                                           $data
         */
-       public function clear($directory, $filepattern) {
-               $this->getCacheSource()->clear($directory, $filepattern);
+       public function set(ICacheBuilder $cacheBuilder, array $parameters, array $data) {
+               $this->getCacheSource()->set($this->getCacheName($cacheBuilder, $parameters), $data, $cacheBuilder->getMaxLifetime());
        }
        
        /**
-        * Returns a cached variable.
+        * Returns cache index hash.
         * 
-        * @param       string          $cache
-        * @param       string          $variable
-        * @return      mixed           $value
+        * @param       array           $parameters
+        * @return      string
         */
-       public function get($cache, $variable = '') {
-               if (!isset($this->cacheResources[$cache])) {
-                       throw new SystemException("unknown cache resource '".$cache."'");
-               }
-               
-               // try to get value
-               $value = $this->getCacheSource()->get($this->cacheResources[$cache]);
-               if ($value === null) {
-                       // rebuild cache
-                       $this->rebuild($this->cacheResources[$cache]);
-                       
-                       // try to get value again
-                       $value = $this->getCacheSource()->get($this->cacheResources[$cache]);
-                       if ($value === null) {
-                               throw new SystemException("cache resource '".$cache."' does not exist");
-                       }
-               }
-               
-               // return value
-               if (!empty($variable)) {
-                       if (!isset($value[$variable])) {
-                               throw new SystemException("variable '".$variable."' does not exist in cache resource '".$cache."'");
-                       }
-                       
-                       return $value[$variable];
-               }
-               else {
-                       return $value;
-               }
+       public function getCacheIndex(array $parameters) {
+               return sha1(serialize($this->orderParameters($parameters)));
        }
        
        /**
-        * Rebuilds a cache resource.
+        * Builds cache name.
         * 
-        * @param       array           $cacheResource
-        * @return      boolean result
+        * @param       wcf\system\cache\builder\ICacheBuilder          $cacheBuilder
+        * @param       array                                           $parameters
+        * @return      string
         */
-       public function rebuild($cacheResource) {
-               // instance cache class
-               if (!class_exists($cacheResource['className'])) {
-                       throw new SystemException("Unable to find class '".$cacheResource['className']."'");
-               }
-               
-               // update file last modified time to avoid multiple users rebuilding cache at the same time
-               if (get_class($this->getCacheSource()) == 'wcf\system\cache\source\DiskCacheSource') {
-                       @touch($cacheResource['file']);
+       protected function getCacheName(ICacheBuilder $cacheBuilder, array $parameters = array()) {
+               $className = explode('\\', get_class($cacheBuilder));
+               $application = array_shift($className);
+               $cacheName = StringUtil::replace('CacheBuilder', '', array_pop($className));
+               if (!empty($parameters)) {
+                       $cacheName .= '-' . $this->getCacheIndex($parameters);
                }
                
-               // build cache
-               $cacheBuilder = new $cacheResource['className'];
-               $value = $cacheBuilder->getData($cacheResource);
-
-               // save cache
-               $this->getCacheSource()->set($cacheResource, $value);
-               
-               return true;
+               return $application . '_' . StringUtil::firstCharToLowerCase($cacheName);
        }
        
        /**
@@ -160,4 +112,18 @@ class CacheHandler extends SingletonFactory {
        public function getCacheSource() {
                return $this->cacheSource;
        }
+       
+       /**
+        * Unifys parameter order, numeric indizes will be discarded.
+        * 
+        * @param       array           $parameters
+        * @return      array
+        */
+       protected function orderParameters($parameters) {
+               if (!empty($parameters)) {
+                       array_multisort($parameters);
+               }
+               
+               return $parameters;
+       }
 }
diff --git a/wcfsetup/install/files/lib/system/cache/builder/AbstractCacheBuilder.class.php b/wcfsetup/install/files/lib/system/cache/builder/AbstractCacheBuilder.class.php
new file mode 100644 (file)
index 0000000..a12fb2e
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+namespace wcf\system\cache\builder;
+use wcf\system\cache\CacheHandler;
+use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
+
+/**
+ * Default implementation for cache builders.
+ * 
+ * @author     Alexander Ebert
+ * @copyright  2001-2013 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.cache.builder
+ * @category   Community Framework
+ */
+abstract class AbstractCacheBuilder extends SingletonFactory implements ICacheBuilder {
+       /**
+        * list of cache resources by index
+        * @var array<array>
+        */
+       protected $cache = array();
+       
+       /**
+        * maximum cache lifetime in seconds, '0' equals infinite
+        * @var integer
+        */
+       protected $maxLifetime = 0;
+       
+       /**
+        * @see wcf\system\cache\builder\ICacheBuilder::getData()
+        */
+       public function getData(array $parameters = array(), $arrayIndex = '') {
+               $index = CacheHandler::getInstance()->getCacheIndex($parameters);
+               
+               if (!isset($this->cache[$index])) {
+                       // fetch cache or rebuild if missing
+                       $this->cache[$index] = CacheHandler::getInstance()->get($this, $parameters);
+                       if ($this->cache[$index] === null) {
+                               $this->cache[$index] = $this->rebuild($parameters);
+                               
+                               // update cache
+                               CacheHandler::getInstance()->set($this, $parameters, $this->cache[$index]);
+                       }
+               }
+               
+               if (!empty($arrayIndex)) {
+                       if (!isset($this->cache[$index][$arrayIndex])) {
+                               throw new SystemException("array index '".$arrayIndex."' does not exist in cache resource");
+                       }
+                       
+                       return $this->cache[$index][$arrayIndex];
+               }
+               
+               return $this->cache[$index];
+       }
+       
+       /**
+        * @see wcf\system\cache\builder\ICacheBuilder::getMaxLifetime()
+        */
+       public function getMaxLifetime() {
+               return $this->maxLifetime;
+       }
+       
+       /**
+        * @see wcf\system\cache\builder\ICacheBuilder::reset()
+        */
+       public function reset(array $parameters = array()) {
+               CacheHandler::getInstance()->flush($this, $parameters);
+       }
+       
+       /**
+        * Rebuilds cache for current resource.
+        * 
+        * @param       array           $parameters
+        */
+       abstract protected function rebuild(array $parameters);
+}
index 5a97f9cdfa5f171ce73d02e418682f7feca49cec..7e8a6f0cf1ffe4813ca5b2a7c099a4362053091c 100644 (file)
@@ -4,19 +4,35 @@ namespace wcf\system\cache\builder;
 /**
  * A cache builder provides data for the cache handler that ought to be cached.
  * 
- * @author     Marcel Werk
- * @copyright  2001-2012 WoltLab GmbH
+ * @author     Alexander Ebert
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
- * @subpackage system.cache
+ * @subpackage system.cache.builder
  * @category   Community Framework
  */
 interface ICacheBuilder {
        /**
         * Returns the data that ought to be cached.
         * 
-        * @param       array           $cacheResource
+        * @param       array           $parameters
+        * @param       string          $arrayIndex
         * @return      array
         */
-       public function getData(array $cacheResource);
+       public function getData(array $parameters = array(), $arrayIndex = '');
+       
+       /**
+        * Returns maximum lifetime for cache resource.
+        * 
+        * @return      integer
+        */
+       public function getMaxLifetime();
+       
+       /**
+        * Flushes cache. If no parameters are given, all caches starting with
+        * the same cache name will be flushed too.
+        * 
+        * @param       array           $parameters
+        */
+       public function reset(array $parameters = array());
 }
index 69516664bfa2c7dc134cbedfcaefbb57411f8106..4ce0278d6f8664d685547e3ea06d9c6192b9fe0f 100644 (file)
@@ -1,19 +1,27 @@
 <?php
 namespace wcf\system\cache\source;
 use wcf\system\exception\SystemException;
+use wcf\system\Regex;
 use wcf\util\FileUtil;
+use wcf\util\StringUtil;
 
 /**
  * ApcCacheSource is an implementation of CacheSource that uses APC to store cached variables.
  * 
- * @author     Markus Bartz
- * @copyright  2011 Markus Bartz
+ * @author     Alexander Ebert
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.cache.source
  * @category   Community Framework
  */
 class ApcCacheSource implements ICacheSource {
+       /**
+        * key prefix
+        * @var string
+        */
+       protected $prefix = '';
+       
        /**
         * Creates a new ApcCacheSource object.
         */
@@ -21,13 +29,35 @@ class ApcCacheSource implements ICacheSource {
                if (!function_exists('apc_store')) {
                        throw new SystemException('APC support is not enabled.');
                }
+               
+               // set variable prefix to prevent collision
+               $this->prefix = substr(sha1(WCF_DIR), 0, 8) . '_';
+       }
+       
+       /**
+        * @see wcf\system\cache\source\ICacheSource::flush()
+        */
+       public function flush($cacheName, $useWildcard) {
+               if ($useWildcard) {
+                       $this->removeKeys($this->prefix . $cacheName . '(\-[a-f0-9]+)?');
+               }
+               else {
+                       apc_delete($this->prefix . $cacheName);
+               }
+       }
+       
+       /**
+        * @see wcf\system\cache\source\ICacheSource::flushAll()
+        */
+       public function flushAll() {
+               $this->removeKeys();
        }
        
        /**
         * @see wcf\system\cache\source\ICacheSource::get()
         */
-       public function get(array $cacheResource) {
-               if (($data = apc_fetch($cacheResource['file'])) === false) {
+       public function get($cacheName, $maxLifetime) {
+               if (($data = apc_fetch($this->prefix . $cacheName)) === false) {
                        return null;
                }
                
@@ -37,43 +67,51 @@ class ApcCacheSource implements ICacheSource {
        /**
         * @see wcf\system\cache\source\ICacheSource::set()
         */
-       public function set(array $cacheResource, $value) {
-               apc_store($cacheResource['file'], $value, $cacheResource['maxLifetime']);
+       public function set($cacheName, $value, $maxLifetime) {
+               apc_store($this->prefix . $cacheName, $value, $this->getTTL($maxLifetime));
        }
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::delete()
+        * Returns time to live in seconds, defaults to 3 days.
+        * 
+        * @param       integer         $maxLifetime
+        * @return      integer
         */
-       public function delete(array $cacheResource) {
-               apc_delete($cacheResource['file']);
+       protected function getTTL($maxLifetime = 0) {
+               if ($maxLifetime) {
+                       // max lifetime is a timestamp, discard (similar to http://www.php.net/manual/en/memcached.expiration.php)
+                       if ($maxLifetime > (60 * 60 * 24 * 30)) {
+                               $maxLifetime = 0;
+                       }
+               }
+               
+               if ($maxLifetime) {
+                       return $maxLifetime;
+               }
+               
+               // default TTL: 3 days
+               return (60 * 60 * 24 * 3);
        }
        
        /**
         * @see wcf\system\cache\source\ICacheSource::clear()
         */
-       public function clear($directory, $filepattern) {
-               $pattern = preg_quote(FileUtil::addTrailingSlash($directory), '%').str_replace('*', '.*', str_replace('.', '\.', $filepattern));
+       public function removeKeys($pattern = null) {
+               $regex = null;
+               if ($pattern !== null) {
+                       $regex = new Regex('^'.$pattern.'$');
+               }
                
-               $apcinfo = apc_cache_info('user');
-               $cacheList = $apcinfo['cache_list'];
-               foreach ($cacheList as $cache) {
-                       if (preg_match('%^'.$pattern.'$%i', $cache['info'])) {
+               $apcCacheInfo = apc_cache_info('user');
+               foreach ($apcCacheInfo['cache_list'] as $cache) {
+                       if ($regex === null) {
+                               if (StringUtil::startsWith($cache['info'], $this->prefix)) {
+                                       apc_delete($cache['info']);
+                               }
+                       }
+                       else if ($regex->match($cache['info'])) {
                                apc_delete($cache['info']);
                        }
                }
        }
-       
-       /**
-        * @see wcf\system\cache\source\ICacheSource::close()
-        */
-       public function close() {
-               // does nothing
-       }
-       
-       /**
-        * @see wcf\system\cache\source\ICacheSource::flush()
-        */
-       public function flush() {
-               apc_clear_cache('user');
-       }
 }
index 22b9fb924abbb9be9af80ae53a5c8293e76d84cc..a7fd036cca2617586350eaa976d03352974f83e9 100644 (file)
@@ -11,8 +11,8 @@ use wcf\util\FileUtil;
 /**
  * DiskCacheSource is an implementation of CacheSource that stores the cache as simple files in the file system.
  * 
- * @author     Marcel Werk
- * @copyright  2001-2012 WoltLab GmbH
+ * @author     Alexander Ebert, Marcel Werk
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.cache.source
@@ -20,118 +20,103 @@ use wcf\util\FileUtil;
  */
 class DiskCacheSource implements ICacheSource {
        /**
-        * loaded cache
-        * @var array
+        * @see wcf\system\cache\source\ICacheSource::flush()
         */
-       protected $cache = null;
+       public function flush($cacheName, $useWildcard) {
+               if ($useWildcard) {
+                       $this->removeFiles('cache.'.$cacheName.'(-[a-f0-9]+)?.php');
+               }
+               else {
+                       $this->removeFiles('cache.'.$cacheName.'.php');
+               }
+       }
        
        /**
-        * list of loaded resources
-        * @var array
+        * @see wcf\system\cache\source\ICacheSource::flushAll()
         */
-       protected $loaded = array();
+       public function flushAll() {
+               DirectoryUtil::getInstance(WCF_DIR.'cache/')->removePattern(new Regex('.*\.php$'));
+       }
        
        /**
         * @see wcf\system\cache\source\ICacheSource::get()
         */
-       public function get(array $cacheResource) {
-               if (!isset($this->cache[$cacheResource['cache']])) {
-                       // check for rebuilt
-                       if ($this->needRebuild($cacheResource)) {
-                               return null;
-                       }
-                       
-                       // load resource
-                       if (!$this->load($cacheResource)) {
-                               return null;
-                       }
-                       
-                       if (!isset($this->cache[$cacheResource['cache']])) {
-                               return null;
-                       }
+       public function get($cacheName, $maxLifetime) {
+               $filename = $this->getFilename($cacheName);
+               if ($this->needRebuild($filename, $maxLifetime)) {
+                       return null;
                }
                
-               return $this->cache[$cacheResource['cache']];
+               // load cache
+               try {
+                       return $this->readCache($filename);
+               }
+               catch (\Exception $e) {
+                       return null;
+               }
        }
        
        /**
         * @see wcf\system\cache\source\ICacheSource::set()
         */
-       public function set(array $cacheResource, $value) {
-               // write cache
-               $targetFile = new File($cacheResource['file']);
-               $targetFile->write("<?php exit; /* cache: ".$cacheResource['cache']." (generated at ".gmdate('r').") DO NOT EDIT THIS FILE */ ?>\n");
-               $targetFile->write(serialize($value));
-               $targetFile->close();
-               
-               // add value
-               $this->cache[$cacheResource['cache']] = $value;
-               $this->loaded[$cacheResource['file']] = true;
+       public function set($cacheName, $value, $maxLifetime) {
+               $file = new File($this->getFilename($cacheName));
+               $file->write("<?php exit; /* cache: ".$cacheName." (generated at ".gmdate('r').") DO NOT EDIT THIS FILE */ ?>\n");
+               $file->write(serialize($value));
+               $file->close();
        }
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::delete()
+        * Returns cache filename.
+        * 
+        * @param       string          $cacheName
+        * @return      string
         */
-       public function delete(array $cacheResource) {
-               if (file_exists($cacheResource['file'])) {
-                       if (!@touch($cacheResource['file'], 1)) {
-                               @unlink($cacheResource['file']);
-                       }
-                       
-                       // reset open cache
-                       if (isset($this->cache[$cacheResource['cache']])) {
-                               unset($this->cache[$cacheResource['cache']]);
-                       }
-                       if (isset($this->loaded[$cacheResource['file']])) {
-                               unset($this->loaded[$cacheResource['file']]);
-                       }
-               }
+       protected function getFilename($cacheName) {
+               return WCF_DIR.'cache/cache.'.$cacheName.'.php';
        }
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::clear()
+        * Removes files matching given pattern.
+        * 
+        * @param       string          $pattern
         */
-       public function clear($directory, $filepattern) {
-               // unify parameters
-               $directory = FileUtil::unifyDirSeperator($directory);
-               $filepattern = FileUtil::unifyDirSeperator($filepattern);
-               
-               $filepattern = str_replace('*', '.*', str_replace('.', '\.', $filepattern));
-               if (substr($directory, -1) != '/') {
-                       $directory .= '/';
-               }
+       protected function removeFiles($pattern) {
+               $directory = FileUtil::unifyDirSeperator(WCF_DIR.'cache/');
+               $pattern = str_replace('*', '.*', str_replace('.', '\.', $pattern));
                
                DirectoryUtil::getInstance($directory)->executeCallback(new Callback(function ($filename) {
                        if (!@touch($filename, 1)) {
                                @unlink($filename);
                        }
-               }), new Regex('^'.$directory.$filepattern.'$', Regex::CASE_INSENSITIVE));
+               }), new Regex('^'.$directory.$pattern.'$', Regex::CASE_INSENSITIVE));
        }
        
        /**
         * Determines wheater the cache needs to be rebuild or not.
         * 
-        * @param       array           $cacheResource
+        * @param       string          $filename
+        * @param       integer         $maxLifetime
         * @return      boolean
         */
-       protected function needRebuild(array $cacheResource) {
+       protected function needRebuild($filename, $maxLifetime) {
                // cache does not exist
-               if (!file_exists($cacheResource['file'])) {
+               if (!file_exists($filename)) {
                        return true;
                }
                
                // cache is empty
-               if (!@filesize($cacheResource['file'])) {
+               if (!@filesize($filename)) {
                        return true;
                }
                
                // cache resource was marked as obsolete
-               if (($mtime = filemtime($cacheResource['file'])) <= 1) {
+               if (($mtime = filemtime($filename)) <= 1) {
                        return true;
                }
                
                // maxlifetime expired
-               if ($cacheResource['maxLifetime'] > 0 && (TIME_NOW - $mtime) > $cacheResource['maxLifetime']) {
+               if ($maxLifetime > 0 && (TIME_NOW - $mtime) > $filename) {
                        return true;
                }
                
@@ -139,68 +124,32 @@ class DiskCacheSource implements ICacheSource {
                return false;
        }
        
-       /**
-        * Loads a cached resource.
-        * 
-        * @param       array           $cacheResource
-        */
-       public function load(array $cacheResource) {
-               if (!isset($this->loaded[$cacheResource['file']])) {
-                       try {
-                               // load cache file
-                               $this->loadCacheFile($cacheResource);
-                       }
-                       catch (\Exception $e) {
-                               return false;
-                       }
-                       
-                       $this->loaded[$cacheResource['file']] = true;
-               }
-               
-               return true;
-       }
-       
        /**
         * Loads the file of a cached resource.
         * 
-        * @param       array           $cacheResource
+        * @param       string          $cacheName
+        * @param       string          $filename
+        * @return      mixed
         */
-       protected function loadCacheFile(array $cacheResource) {
+       protected function readCache($cacheName, $filename) {
                // get file contents
-               $contents = file_get_contents($cacheResource['file']);
+               $contents = file_get_contents($filename);
                
                // find first newline
                $position = strpos($contents, "\n");
-               if ($position === false) throw new SystemException("Unable to load cache resource '".$cacheResource['cache']."'");
+               if ($position === false) {
+                       throw new SystemException("Unable to load cache resource '".$cacheName."'");
+               }
                
                // cut contents
                $contents = substr($contents, $position + 1);
                
                // unserialize
-               $this->cache[$cacheResource['cache']] = @unserialize($contents);
-               if ($this->cache[$cacheResource['cache']] === false) throw new SystemException("Unable to load cache resource '".$cacheResource['cache']."'");
-       }
-       
-       /**
-        * @see wcf\system\cache\source\ICacheSource::close()
-        */
-       public function close() {
-               // does nothing
-       }
-       
-       /**
-        * @see wcf\system\cache\source\ICacheSource::flush()
-        */
-       public function flush() {
-               $sql = "SELECT  packageDir
-                       FROM    wcf".WCF_N."_package
-                       WHERE   isApplication = ?";
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array(1));
-               while ($row = $statement->fetchArray()) {
-                       $packageDir = FileUtil::getRealPath(WCF_DIR.$row['packageDir']);
-                       $cacheDir = $packageDir.'cache';
-                       DirectoryUtil::getInstance($cacheDir)->removePattern(new Regex('.*\.php$'));
+               $value = @unserialize($contents);
+               if ($value === false) {
+                       throw new SystemException("Unable to load cache resource '".$cacheName."'");
                }
+               
+               return $value;
        }
 }
index 36ca674ff1389bacedcb0c4cea299c012036a231..dd4b8afa1f5466c6e79dee8f0ce1c573a7602588 100644 (file)
@@ -4,8 +4,8 @@ namespace wcf\system\cache\source;
 /**
  * Any cache sources should implement this interface.
  * 
- * @author     Marcel Werk
- * @copyright  2001-2012 WoltLab GmbH
+ * @author     Alexander Ebert
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.cache.source
@@ -13,43 +13,33 @@ namespace wcf\system\cache\source;
  */
 interface ICacheSource {
        /**
-        * Returns a cached variable.
-        * 
-        * @param       array           $cacheResource
-        * @return      mixed
+        * Flushes a specific cache, optionally removing caches which share the same name.
+        *
+        * @param       string          $cacheName
+        * @param       boolean         $useWildcard
         */
-       public function get(array $cacheResource);
+       public function flush($cacheName, $useWildcard);
        
        /**
-        * Stores a variable in the cache.
-        * 
-        * @param       array           $cacheResource
-        * @param       mixed           $value
+        * Clears the cache completely.
         */
-       public function set(array $cacheResource, $value);
+       public function flushAll();
        
        /**
-        * Deletes a variable in the cache.
+        * Returns a cached variable.
         * 
-        * @param       array           $cacheResource
+        * @param       string          $cacheName
+        * @param       integer         $maxLifetime
+        * @return      mixed
         */
-       public function delete(array $cacheResource);
+       public function get($cacheName, $maxLifetime);
        
        /**
-        * Marks cached files as obsolete.
+        * Stores a variable in the cache.
         * 
-        * @param       string          $directory
-        * @param       string          $filepattern
-        */
-       public function clear($directory, $filepattern);
-       
-       /**
-        * Closes this cache source.
-        */
-       public function close();
-       
-       /**
-        * Clears the cache completely.
+        * @param       string          $cacheName
+        * @param       mixed           $value
+        * @param       integer         $maxLifetime
         */
-       public function flush();
+       public function set($cacheName, $value, $maxLifetime);
 }
diff --git a/wcfsetup/install/files/lib/system/cache/source/MemcachedAdapter.class.php b/wcfsetup/install/files/lib/system/cache/source/MemcachedAdapter.class.php
deleted file mode 100644 (file)
index 357b395..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-namespace wcf\system\cache\source;
-use wcf\system\exception\SystemException;
-use wcf\system\SingletonFactory;
-use wcf\util\StringUtil;
-
-/**
- * Provides a global adapter for accessing the memcached server.
- * 
- * @author     Alexander Ebert
- * @copyright  2001-2013 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package    com.woltlab.wcf
- * @subpackage system.cache.source
- * @category   Community Framework
- */
-class MemcachedAdapter extends SingletonFactory {
-       /**
-        * memcached object
-        * @var \Memcached
-        */
-       private $memcached = null;
-       
-       /**
-        * @see wcf\system\SingletonFactory::init()
-        */
-       protected function init() {
-               if (!class_exists('Memcached')) {
-                       throw new SystemException('memcached support is not enabled.');
-               }
-               
-               // init memcached
-               if (CACHE_SOURCE_MEMCACHED_USE_PCONNECT) {
-                       $this->memcached = new \Memcached('wcf'.WCF_N.'_memcached');
-               }
-               else {
-                       $this->memcached = new \Memcached();
-               }
-               
-               // add servers
-               $tmp = explode("\n", StringUtil::unifyNewlines(CACHE_SOURCE_MEMCACHED_HOST));
-               $servers = array();
-               $defaultWeight = floor(100 / count($tmp));
-               foreach ($tmp as $server) {
-                       $server = StringUtil::trim($server);
-                       if (!empty($server)) {
-                               $host = $server;
-                               $port = 11211; // default memcached port
-                               $weight = $defaultWeight;
-                               
-                               // get port
-                               if (strpos($host, ':')) {
-                                       $parsedHost = explode(':', $host);
-                                       $host = $parsedHost[0];
-                                       $port = $parsedHost[1];
-                                       
-                                       if (isset($parsedHost[2])) {
-                                               $weight = $parsedHost[2];
-                                       }
-                               }
-                               
-                               $servers[] = array($host, $port, $weight);
-                       }
-               }
-               
-               $this->memcached->addServers($servers);
-               
-               // test connection
-               $this->memcached->get('testing');
-       }
-       
-       /**
-        * Returns the memcached object.
-        *
-        * @return      \Memcached
-        */
-       public function getMemcached() {
-               return $this->memcached;
-       }
-}
index 9dcac83e6b2ceebf41623bf5ee316f8e65d59683..5e39d22e11277b7c52273e092899b118f256b53d 100644 (file)
@@ -1,12 +1,12 @@
 <?php
 namespace wcf\system\cache\source;
-use wcf\system\WCF;
-use wcf\util\FileUtil;
+use wcf\system\exception\SystemException;
+use wcf\util\StringUtil;
 
 /**
  * MemcachedCacheSource is an implementation of CacheSource that uses a Memcached server to store cached variables.
  * 
- * @author     Marcel Werk
+ * @author     Alexander Ebert
  * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
@@ -15,178 +15,209 @@ use wcf\util\FileUtil;
  */
 class MemcachedCacheSource implements ICacheSource {
        /**
-        * MemcachedAdapter object
-        * @var wcf\system\cache\source\MemcachedAdapter
+        * memcached object
+        * @var \Memcached
         */
-       protected $adapter = null;
+       protected $memcached = null;
        
        /**
-        * list of cache resources
-        * @var array<string>
+        * key prefix
+        * @var string
         */
-       protected $cacheResources = null;
+       protected $prefix = '';
        
        /**
-        * list of new cache resources
-        * @var array<string>
-        */
-       protected $newLogEntries = array();
-       
-       /**
-        * list of obsolete resources
-        * @var array<string>
-        */
-       protected $obsoleteLogEntries = array();
-       
-       /**
-        * Creates a new MemcachedCacheSource object.
+        * Creates a new instance of memcached.
         */
        public function __construct() {
-               $this->adapter = MemcachedAdapter::getInstance();
-       }
-       
-       /**
-        * Returns the memcached adapter.
-        * 
-        * @return      wcf\system\cache\source\MemcachedAdapter
-        */
-       public function getAdapter() {
-               return $this->adapter;
-       }
-       
-       // internal log functions
-       /**
-        * Loads the cache log.
-        */
-       protected function loadLog() {
-               if ($this->cacheResources === null) {
-                       $this->cacheResources = array();
-                       $sql = "SELECT  *
-                               FROM    wcf".WCF_N."_cache_resource";
-                       $statement = WCF::getDB()->prepareStatement($sql);
-                       $statement->execute();
-                       while ($row = $statement->fetchArray()) {
-                               $this->cacheResources[] = $row['cacheResource'];
-                       }
-               }
-       }
-       
-       /**
-        * Saves modifications of the cache log.
-        */
-       protected function updateLog() {
-               if (!empty($this->newLogEntries)) {
-                       $sql = "DELETE FROM     wcf".WCF_N."_cache_resource
-                               WHERE           cacheResource = ?";
-                       $statement = WCF::getDB()->prepareStatement($sql);
-                       foreach ($this->newLogEntries as $entry) {
-                               $statement->execute(array($entry));
-                       }
-                       
-                       $sql = "INSERT INTO     wcf".WCF_N."_cache_resource
-                                               (cacheResource)
-                               VALUES          (?)";
-                       $statement = WCF::getDB()->prepareStatement($sql);
-                       foreach ($this->newLogEntries as $entry) {
-                               $statement->execute(array($entry));
-                       }
-                       
+               if (!class_exists('Memcached')) {
+                       throw new SystemException('memcached support is not enabled.');
                }
                
-               if (!empty($this->obsoleteLogEntries)) {
-                       $sql = "DELETE FROM     wcf".WCF_N."_cache_resource
-                               WHERE           cacheResource = ?";
-                       $statement = WCF::getDB()->prepareStatement($sql);
-                       foreach ($this->obsoleteLogEntries as $entry) {
-                               $statement->execute(array($entry));
+               // init memcached
+               $this->memcached = new \Memcached();
+               
+               // add servers
+               $tmp = explode("\n", StringUtil::unifyNewlines(CACHE_SOURCE_MEMCACHED_HOST));
+               $servers = array();
+               $defaultWeight = floor(100 / count($tmp));
+               foreach ($tmp as $server) {
+                       $server = StringUtil::trim($server);
+                       if (!empty($server)) {
+                               $host = $server;
+                               $port = 11211; // default memcached port
+                               $weight = $defaultWeight;
+                               
+                               // get port
+                               if (strpos($host, ':')) {
+                                       $parsedHost = explode(':', $host);
+                                       $host = $parsedHost[0];
+                                       $port = $parsedHost[1];
+                                       
+                                       if (isset($parsedHost[2])) {
+                                               $weight = $parsedHost[2];
+                                       }
+                               }
+                               
+                               $servers[] = array($host, $port, $weight);
                        }
                }
+               
+               $this->memcached->addServers($servers);
+               
+               // test connection
+               $this->memcached->get('testing');
+               
+               // set variable prefix to prevent collision
+               $this->prefix = substr(sha1(WCF_DIR), 0, 8) . '_';
        }
        
        /**
-        * Adds a cache resource to cache log.
-        * 
-        * @param       string          $cacheResource
+        * @see wcf\system\cache\source\ICacheSource::flush()
         */
-       protected function addToLog($cacheResource) {
-               $this->newLogEntries[] = $cacheResource;
+       public function flush($cacheName, $useWildcard) {
+               $cacheName = $this->prefix . $cacheName;
+               $this->memcached->delete($cacheName);
+               
+               $this->updateMaster(null, $cacheName);
        }
        
        /**
-        * Removes an obsolete cache resource from cache log.
-        * 
-        * @param       string          $cacheResource
+        * @see wcf\system\cache\source\ICacheSource::flushAll()
         */
-       protected function removeFromLog($cacheResource) {
-               $this->obsoleteLogEntries[] = $cacheResource;
+       public function flushAll() {
+               // read all keys
+               $availableKeys = $this->memcached->get($this->prefix . 'master');
+               if ($availableKeys !== false) {
+                       $keys = @unserialize($availableKeys);
+                       if ($keys !== false) {
+                               $this->memcached->deleteMulti($keys);
+                       }
+               }
+               
+               // flush master
+               $this->memcached->set($this->prefix . 'master', serialize(array()), $this->getTTL());
        }
        
-       // CacheSource implementations
        /**
         * @see wcf\system\cache\source\ICacheSource::get()
         */
-       public function get(array $cacheResource) {
-               $value = $this->getAdapter()->getMemcached()->get($cacheResource['file']);
+       public function get($cacheName, $maxLifetime) {
+               $cacheName = $this->prefix . $cacheName;
+               $value = $this->memcached->get($cacheName);
+               
                if ($value === false) {
-                       // check if result code if return values is a boolean value instead of no result
-                       if ($this->getAdapter()->getMemcached()->getResultCode() == \Memcached::RES_NOTFOUND) {
+                       // check if value does not exist
+                       if ($this->memcached->getResultCode() !== \Memcached::RES_SUCCESS) {
+                               $this->updateMaster(null, $cacheName);
                                return null;
                        }
                }
                
+               $this->updateMaster($cacheName);
                return $value;
        }
        
        /**
         * @see wcf\system\cache\source\ICacheSource::set()
         */
-       public function set(array $cacheResource, $value) {
-               $this->getAdapter()->getMemcached()->set($cacheResource['file'], $value, $cacheResource['maxLifetime']);
-               $this->addToLog($cacheResource['file']);
-       }
-       
-       /**
-        * @see wcf\system\cache\source\ICacheSource::delete()
-        */
-       public function delete(array $cacheResource) {
-               $this->getAdapter()->getMemcached()->delete($cacheResource['file']);
-               $this->removeFromLog($cacheResource['file']);
+       public function set($cacheName, $value, $maxLifetime) {
+               $cacheName = $this->prefix . $cacheName;
+               $this->memcached->set($cacheName, $value, $this->getTTL($maxLifetime));
+               
+               $this->updateMaster($cacheName);
        }
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::clear()
+        * Updates master record for cached resources.
+        * 
+        * @param       string          $addResource
+        * @param       string          $removeResource
         */
-       public function clear($directory, $filepattern) {
-               $this->loadLog();
-               $pattern = preg_quote(FileUtil::addTrailingSlash($directory), '%').str_replace('*', '.*', str_replace('.', '\.', $filepattern));
-               foreach ($this->cacheResources as $cacheResource) {
-                       if (preg_match('%^'.$pattern.'$%i', $cacheResource)) {
-                               $this->getAdapter()->getMemcached()->delete($cacheResource);
-                               $this->removeFromLog($cacheResource);
+       protected function updateMaster($addResource = null, $removeResource = null) {
+               if ($addResource === null && $removeResource === null) {
+                       return;
+               }
+               
+               $master = $this->memcached->get($this->prefix . 'master');
+               $update = false;
+               
+               // master record missing
+               if ($master === false) {
+                       $update = true;
+                       $master = array();
+               }
+               else {
+                       $master = @unserialize($master);
+                       
+                       // master record is broken
+                       if ($master === false) {
+                               $update = true;
+                               $master = array();
                        }
+                       else {
+                               foreach ($master as $index => $key) {
+                                       if ($addResource !== null) {
+                                               // key is already tracked
+                                               if ($key === $addResource) {
+                                                       $addResource = null;
+                                                       
+                                                       if ($removeResource === null) {
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       
+                                       if ($removeResource !== null) {
+                                               if ($key === $removeResource) {
+                                                       $update = true;
+                                                       unset($master[$index]);
+                                                       
+                                                       if ($addResource === null) {
+                                                               break;
+                                                       }
+                                                       else {
+                                                               $removeResource = null;
+                                                       }
+                                               }
+                                       }
+                               }
+                               
+                               if ($addResource !== null) {
+                                       $update = true;
+                                       $master[] = $addResource;
+                               }
+                       }
+               }
+               
+               // update master record
+               if ($update) {
+                       $this->memcached->set($this->prefix . 'master', serialize($master), $this->getTTL());
                }
        }
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::flush()
-        */
-       public function flush() {
-               // clear cache
-               $this->getAdapter()->getMemcached()->flush();
+        * Returns time to live in seconds, defaults to 3 days.
+        * 
+        * @param       integer         $maxLifetime
+        * @return      integer
+        */
+       protected function getTTL($maxLifetime = 0) {
+               if ($maxLifetime) {
+                       // max lifetime is a timestamp -> http://www.php.net/manual/en/memcached.expiration.php
+                       if ($maxLifetime > (60 * 60 * 24 * 30)) {
+                               // timestamp is in the past, discard
+                               if ($maxLifetime < TIME_NOW) {
+                                       $maxLifetime = 0;
+                               }
+                       }
+               }
                
-               // clear log
-               $this->newLogEntries = $this->obsoleteLogEntries = array();
+               if ($maxLifetime) {
+                       return $maxLifetime;
+               }
                
-               $sql = "DELETE FROM     wcf".WCF_N."_cache_resource";
-               $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute();
-       }
-       
-       /**
-        * @see wcf\system\cache\source\ICacheSource::close()
-        */
-       public function close() {
-               // update log
-               $this->updateLog();
+               // default TTL: 3 days
+               return (60 * 60 * 24 * 3);
        }
 }
index e43a4eabe4d9a5fa85e882dfc69d1db737912b5b..35ab0ab8b0faae94beb3a0bf2290dc86a5cfcf1f 100644 (file)
@@ -1,11 +1,12 @@
 <?php
 namespace wcf\system\cache\source;
+use wcf\util\StringUtil;
 
 /**
  * NoCacheSource is an implementation of CacheSource that does not store any data.
  * 
- * @author     Tim Düsterhus
- * @copyright  2011 Tim Düsterhus
+ * @author     Alexander Ebert
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.cache.source
@@ -13,52 +14,51 @@ namespace wcf\system\cache\source;
  */
 class NoCacheSource implements ICacheSource {
        /**
-        * @see wcf\system\cache\source\ICacheSource::get()
-        */
-       public function get(array $cacheResource) {
-               if (!isset($this->cache[$cacheResource['cache']])) return null;
-               
-               return $this->cache[$cacheResource['cache']];
-       }
-       
-       /**
-        * @see wcf\system\cache\source\ICacheSource::set()
+        * list of cached values
+        * @var array<array>
         */
-       public function set(array $cacheResource, $value) {
-               // we have to keep it temporarily
-               $this->cache[$cacheResource['cache']] = $value;
-               $this->loaded[$cacheResource['file']] = true;
-       }
+       protected $cache = array();
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::delete()
+        * @see wcf\system\cache\source\ICacheSource::flush()
         */
-       public function delete(array $cacheResource) {  
-               // reset open cache
-               if (isset($this->cache[$cacheResource['cache']])) unset($this->cache[$cacheResource['cache']]);
-               if (isset($this->loaded[$cacheResource['file']])) unset($this->loaded[$cacheResource['file']]);
-
-               return;
+       public function flush($cacheName, $useWildcard) {
+               if (isset($this->cache[$cacheName])) {
+                       unset($this->cache[$cacheName]);
+               }
+               
+               if ($useWildcard) {
+                       $cacheName .= '-';
+                       foreach (array_keys($this->cache) as $key) {
+                               if (StringUtil::startsWith($key, $cacheName)) {
+                                       unset($this->cache[$key]);
+                               }
+                       }
+               } 
        }
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::clear()
+        * @see wcf\system\cache\source\ICacheSource::flushAll()
         */
-       public function clear($directory, $filepattern) {
-               return;
+       public function flushAll() {
+               $this->cache = array();
        }
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::close()
+        * @see wcf\system\cache\source\ICacheSource::get()
         */
-       public function close() {
-               return;
+       public function get($cacheName, $maxLifetime) {
+               if (isset($this->cache[$cacheName])) {
+                       return $this->cache[$cacheName];
+               }
+               
+               return null;
        }
        
        /**
-        * @see wcf\system\cache\source\ICacheSource::flush()
+        * @see wcf\system\cache\source\ICacheSource::set()
         */
-       public function flush() {
-               return;
+       public function set($cacheName, $value, $maxLifetime) {
+               $this->cache[$cacheName] = $value;
        }
 }
index 67d2600e1ecd6ee7cc9168933f55cc4dfcf4fd7a..dc5031263cf17784be3e9d91361d01423d645f81 100644 (file)
                <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Eine Browser-Kennung (User-Agent) pro Zeile]]></item>
                <item name="wcf.acp.option.cache_source_memcached_host"><![CDATA[Memcached-Server]]></item>
                <item name="wcf.acp.option.cache_source_memcached_host.description"><![CDATA[Mehrere Server können zeilenweise angegeben werden, die Gewichtung kann als dritter Parameter angegeben werden, zum Beispiel „localhost:11211:67“ oder „10.0.13.37:31337:33“.]]></item>
-               <item name="wcf.acp.option.cache_source_memcached_use_pconnect"><![CDATA[Persistente Verbindungen aktivieren]]></item>
                <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache-Methode]]></item>
                <item name="wcf.acp.option.cache_source_type.apc"><![CDATA[Alternative PHP Cache (experimentell)]]></item>
                <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Beachten Sie, dass einige Methoden spezielle Anforderungen an das Server-System stellen und nicht auf jedem Server zur Verfügung stehen.]]></item>
index be610e212b98adccfaf9e7fd0eb7d966b207c5e9..44591aaa19190df20261614219aa2892f9d93611 100644 (file)
                <item name="wcf.acp.option.blacklist_user_agents.description"><![CDATA[Enter one user agent each row.]]></item>
                <item name="wcf.acp.option.cache_source_memcache_host"><![CDATA[Memcache server]]></item>
                <item name="wcf.acp.option.cache_source_memcache_host.description"><![CDATA[You can enter one server each row.]]></item>
-               <item name="wcf.acp.option.cache_source_memcache_use_pconnect"><![CDATA[Use persistent connections]]></item>
                <item name="wcf.acp.option.cache_source_type"><![CDATA[Cache type]]></item>
                <item name="wcf.acp.option.cache_source_type.apc"><![CDATA[Alternative PHP Cache (experimental)]]></item>
                <item name="wcf.acp.option.cache_source_type.description"><![CDATA[Some of the types have special requirements to the server system and cannot be used in any environment.]]></item>
index ab87c110267375264eff81ce79866c57e2b2d5df..cb71a40c7b3c464c5dda550db8f017aa2cd29bd3 100644 (file)
@@ -120,11 +120,6 @@ CREATE TABLE wcf1_application (
        isPrimary TINYINT(1) NOT NULL DEFAULT 0
 );
 
-DROP TABLE IF EXISTS wcf1_cache_resource;
-CREATE TABLE wcf1_cache_resource (
-       cacheResource VARCHAR(255) NOT NULL PRIMARY KEY
-);
-
 DROP TABLE IF EXISTS wcf1_category;
 CREATE TABLE wcf1_category (
        categoryID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,