summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoricewind1991 <icewind1991@gmail.com>2013-07-16 13:25:07 -0700
committericewind1991 <icewind1991@gmail.com>2013-07-16 13:25:07 -0700
commite09ffb6f57439353e992af516d47b170272cbbae (patch)
treef8ea1149f95de72ee785bd5571380724830523a5
parent285f288cf344625dbddd3c6e4bacb9df1ddb6ce0 (diff)
parentdc1a17b6f486c565ff5b30a6446421f1436355af (diff)
downloadnextcloud-server-e09ffb6f57439353e992af516d47b170272cbbae.tar.gz
nextcloud-server-e09ffb6f57439353e992af516d47b170272cbbae.zip
Merge pull request #2395 from owncloud/cache
Seperate the memory based cache and file based cache in OC_Cache
-rw-r--r--lib/cache.php67
-rw-r--r--lib/cache/apc.php64
-rw-r--r--lib/memcache/apc.php67
-rw-r--r--lib/memcache/cache.php77
-rw-r--r--lib/memcache/factory.php38
-rw-r--r--lib/memcache/memcached.php76
-rw-r--r--lib/memcache/xcache.php (renamed from lib/cache/xcache.php)34
-rw-r--r--tests/lib/cache/apc.php35
-rw-r--r--tests/lib/cache/xcache.php31
-rw-r--r--tests/lib/memcache/apc.php20
-rw-r--r--tests/lib/memcache/cache.php58
-rw-r--r--tests/lib/memcache/memcached.php20
-rw-r--r--tests/lib/memcache/xcache.php20
13 files changed, 403 insertions, 204 deletions
diff --git a/lib/cache.php b/lib/cache.php
index bc74ed83f8b..48b9964ba9d 100644
--- a/lib/cache.php
+++ b/lib/cache.php
@@ -15,41 +15,14 @@ class OC_Cache {
* @var OC_Cache $global_cache
*/
static protected $global_cache;
- /**
- * @var OC_Cache $global_cache_fast
- */
- static protected $global_cache_fast;
- /**
- * @var OC_Cache $user_cache_fast
- */
- static protected $user_cache_fast;
- static protected $isFast=null;
/**
* get the global cache
* @return OC_Cache
*/
- static public function getGlobalCache($fast=false) {
+ static public function getGlobalCache() {
if (!self::$global_cache) {
- self::$global_cache_fast = null;
- if (!self::$global_cache_fast && function_exists('xcache_set')) {
- self::$global_cache_fast = new OC_Cache_XCache(true);
- }
- if (!self::$global_cache_fast && function_exists('apc_store')) {
- self::$global_cache_fast = new OC_Cache_APC(true);
- }
-
self::$global_cache = new OC_Cache_FileGlobal();
- if (self::$global_cache_fast) {
- self::$global_cache = new OC_Cache_Broker(self::$global_cache_fast, self::$global_cache);
- }
- }
- if($fast) {
- if(self::$global_cache_fast) {
- return self::$global_cache_fast;
- }else{
- return false;
- }
}
return self::$global_cache;
}
@@ -58,34 +31,16 @@ class OC_Cache {
* get the user cache
* @return OC_Cache
*/
- static public function getUserCache($fast=false) {
+ static public function getUserCache() {
if (!self::$user_cache) {
- self::$user_cache_fast = null;
- if (!self::$user_cache_fast && function_exists('xcache_set')) {
- self::$user_cache_fast = new OC_Cache_XCache();
- }
- if (!self::$user_cache_fast && function_exists('apc_store')) {
- self::$user_cache_fast = new OC_Cache_APC();
- }
-
self::$user_cache = new OC_Cache_File();
- if (self::$user_cache_fast) {
- self::$user_cache = new OC_Cache_Broker(self::$user_cache_fast, self::$user_cache);
- }
- }
-
- if($fast) {
- if(self::$user_cache_fast) {
- return self::$user_cache_fast;
- }else{
- return false;
- }
}
return self::$user_cache;
}
/**
* get a value from the user cache
+ * @param string $key
* @return mixed
*/
static public function get($key) {
@@ -95,6 +50,9 @@ class OC_Cache {
/**
* set a value in the user cache
+ * @param string $key
+ * @param mixed $value
+ * @param int $ttl
* @return bool
*/
static public function set($key, $value, $ttl=0) {
@@ -107,6 +65,7 @@ class OC_Cache {
/**
* check if a value is set in the user cache
+ * @param string $key
* @return bool
*/
static public function hasKey($key) {
@@ -116,6 +75,7 @@ class OC_Cache {
/**
* remove an item from the user cache
+ * @param string $key
* @return bool
*/
static public function remove($key) {
@@ -133,17 +93,6 @@ class OC_Cache {
return $user_cache->clear($prefix);
}
- /**
- * check if a fast memory based cache is available
- * @return true
- */
- static public function isFast() {
- if(is_null(self::$isFast)) {
- self::$isFast=function_exists('xcache_set') || function_exists('apc_store');
- }
- return self::$isFast;
- }
-
static public function generateCacheKeyFromFiles($files) {
$key = '';
sort($files);
diff --git a/lib/cache/apc.php b/lib/cache/apc.php
deleted file mode 100644
index 895d307ea26..00000000000
--- a/lib/cache/apc.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
- */
-
-class OC_Cache_APC {
- protected $prefix;
-
- public function __construct($global = false) {
- $this->prefix = OC_Util::getInstanceId().'/';
- if (!$global) {
- $this->prefix .= OC_User::getUser().'/';
- }
- }
-
- /**
- * entries in APC gets namespaced to prevent collisions between owncloud instances and users
- */
- protected function getNameSpace() {
- return $this->prefix;
- }
-
- public function get($key) {
- $result = apc_fetch($this->getNamespace().$key, $success);
- if (!$success) {
- return null;
- }
- return $result;
- }
-
- public function set($key, $value, $ttl=0) {
- return apc_store($this->getNamespace().$key, $value, $ttl);
- }
-
- public function hasKey($key) {
- return apc_exists($this->getNamespace().$key);
- }
-
- public function remove($key) {
- return apc_delete($this->getNamespace().$key);
- }
-
- public function clear($prefix='') {
- $ns = $this->getNamespace().$prefix;
- $cache = apc_cache_info('user');
- foreach($cache['cache_list'] as $entry) {
- if (strpos($entry['info'], $ns) === 0) {
- apc_delete($entry['info']);
- }
- }
- return true;
- }
-}
-if(!function_exists('apc_exists')) {
- function apc_exists($keys)
- {
- $result=false;
- apc_fetch($keys, $result);
- return $result;
- }
-}
diff --git a/lib/memcache/apc.php b/lib/memcache/apc.php
new file mode 100644
index 00000000000..575ee4427db
--- /dev/null
+++ b/lib/memcache/apc.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Memcache;
+
+class APC extends Cache {
+ /**
+ * entries in APC gets namespaced to prevent collisions between owncloud instances and users
+ */
+ protected function getNameSpace() {
+ return $this->prefix;
+ }
+
+ public function get($key) {
+ $result = apc_fetch($this->getNamespace() . $key, $success);
+ if (!$success) {
+ return null;
+ }
+ return $result;
+ }
+
+ public function set($key, $value, $ttl = 0) {
+ return apc_store($this->getNamespace() . $key, $value, $ttl);
+ }
+
+ public function hasKey($key) {
+ return apc_exists($this->getNamespace() . $key);
+ }
+
+ public function remove($key) {
+ return apc_delete($this->getNamespace() . $key);
+ }
+
+ public function clear($prefix = '') {
+ $ns = $this->getNamespace() . $prefix;
+ $cache = apc_cache_info('user');
+ foreach ($cache['cache_list'] as $entry) {
+ if (strpos($entry['info'], $ns) === 0) {
+ apc_delete($entry['info']);
+ }
+ }
+ return true;
+ }
+
+ static public function isAvailable() {
+ if (!extension_loaded('apc')) {
+ return false;
+ } elseif (!ini_get('apc.enable_cli') && \OC::$CLI) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+}
+
+if (!function_exists('apc_exists')) {
+ function apc_exists($keys) {
+ $result = false;
+ apc_fetch($keys, $result);
+ return $result;
+ }
+}
diff --git a/lib/memcache/cache.php b/lib/memcache/cache.php
new file mode 100644
index 00000000000..0ad1cc7ec03
--- /dev/null
+++ b/lib/memcache/cache.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Memcache;
+
+abstract class Cache implements \ArrayAccess {
+ /**
+ * @var string $prefix
+ */
+ protected $prefix;
+
+ /**
+ * @param string $prefix
+ */
+ public function __construct($prefix = '') {
+ $this->prefix = \OC_Util::getInstanceId() . '/' . $prefix;
+ }
+
+ public function getPrefix() {
+ return $this->prefix;
+ }
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ abstract public function get($key);
+
+ /**
+ * @param string $key
+ * @param mixed $value
+ * @param int $ttl
+ * @return mixed
+ */
+ abstract public function set($key, $value, $ttl = 0);
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ abstract public function hasKey($key);
+
+ /**
+ * @param string $key
+ * @return mixed
+ */
+ abstract public function remove($key);
+
+ /**
+ * @param string $prefix
+ * @return mixed
+ */
+ abstract public function clear($prefix = '');
+
+ //implement the ArrayAccess interface
+
+ public function offsetExists($offset) {
+ return $this->hasKey($offset);
+ }
+
+ public function offsetSet($offset, $value) {
+ $this->set($offset, $value);
+ }
+
+ public function offsetGet($offset) {
+ return $this->get($offset);
+ }
+
+ public function offsetUnset($offset) {
+ $this->remove($offset);
+ }
+}
diff --git a/lib/memcache/factory.php b/lib/memcache/factory.php
new file mode 100644
index 00000000000..b1b49971031
--- /dev/null
+++ b/lib/memcache/factory.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Memcache;
+
+class Factory {
+ /**
+ * get a cache instance, will return null if no backend is available
+ *
+ * @param string $prefix
+ * @return \OC\Memcache\Cache
+ */
+ function create($prefix = '') {
+ if (XCache::isAvailable()) {
+ return new XCache($prefix);
+ } elseif (APC::isAvailable()) {
+ return new APC($prefix);
+ } elseif (Memcached::isAvailable()) {
+ return new Memcached($prefix);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * check if there is a memcache backend available
+ *
+ * @return bool
+ */
+ public function isAvailable() {
+ return XCache::isAvailable() || APC::isAvailable() || Memcached::isAvailable();
+ }
+}
diff --git a/lib/memcache/memcached.php b/lib/memcache/memcached.php
new file mode 100644
index 00000000000..978e6c2eff1
--- /dev/null
+++ b/lib/memcache/memcached.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Memcache;
+
+class Memcached extends Cache {
+ /**
+ * @var \Memcached $cache
+ */
+ private static $cache = null;
+
+ public function __construct($prefix = '') {
+ parent::__construct($prefix);
+ if (is_null(self::$cache)) {
+ self::$cache = new \Memcached();
+ list($host, $port) = \OC_Config::getValue('memcached_server', array('localhost', 11211));
+ self::$cache->addServer($host, $port);
+ }
+ }
+
+ /**
+ * entries in XCache gets namespaced to prevent collisions between owncloud instances and users
+ */
+ protected function getNameSpace() {
+ return $this->prefix;
+ }
+
+ public function get($key) {
+ $result = self::$cache->get($this->getNamespace() . $key);
+ if ($result === false and self::$cache->getResultCode() == \Memcached::RES_NOTFOUND) {
+ return null;
+ } else {
+ return $result;
+ }
+ }
+
+ public function set($key, $value, $ttl = 0) {
+ if ($ttl > 0) {
+ return self::$cache->set($this->getNamespace() . $key, $value, $ttl);
+ } else {
+ return self::$cache->set($this->getNamespace() . $key, $value);
+ }
+ }
+
+ public function hasKey($key) {
+ self::$cache->get($this->getNamespace() . $key);
+ return self::$cache->getResultCode() !== \Memcached::RES_NOTFOUND;
+ }
+
+ public function remove($key) {
+ return self::$cache->delete($this->getNamespace() . $key);
+ }
+
+ public function clear($prefix = '') {
+ $prefix = $this->getNamespace() . $prefix;
+ $allKeys = self::$cache->getAllKeys();
+ $keys = array();
+ $prefixLength = strlen($prefix);
+ foreach ($allKeys as $key) {
+ if (substr($key, 0, $prefixLength) === $prefix) {
+ $keys[] = $key;
+ }
+ }
+ self::$cache->deleteMulti($keys);
+ return true;
+ }
+
+ static public function isAvailable() {
+ return extension_loaded('memcached');
+ }
+}
diff --git a/lib/cache/xcache.php b/lib/memcache/xcache.php
index 9f380f870b9..33de30562f9 100644
--- a/lib/cache/xcache.php
+++ b/lib/memcache/xcache.php
@@ -6,16 +6,9 @@
* See the COPYING-README file.
*/
-class OC_Cache_XCache {
- protected $prefix;
-
- public function __construct($global = false) {
- $this->prefix = OC_Util::getInstanceId().'/';
- if (!$global) {
- $this->prefix .= OC_User::getUser().'/';
- }
- }
+namespace OC\Memcache;
+class XCache extends Cache {
/**
* entries in XCache gets namespaced to prevent collisions between owncloud instances and users
*/
@@ -44,13 +37,24 @@ class OC_Cache_XCache {
}
public function clear($prefix='') {
- if(!function_exists('xcache_unset_by_prefix')) {
- function xcache_unset_by_prefix($prefix) {
- // Since we can't clear targetted cache, we'll clear all. :(
- xcache_clear_cache(XC_TYPE_VAR, 0);
- }
- }
xcache_unset_by_prefix($this->getNamespace().$prefix);
return true;
}
+
+ static public function isAvailable(){
+ if (!extension_loaded('xcache')) {
+ return false;
+ } elseif (\OC::$CLI) {
+ return false;
+ }else{
+ return true;
+ }
+ }
+}
+
+if(!function_exists('xcache_unset_by_prefix')) {
+ function xcache_unset_by_prefix($prefix) {
+ // Since we can't clear targetted cache, we'll clear all. :(
+ xcache_clear_cache(\XC_TYPE_VAR, 0);
+ }
}
diff --git a/tests/lib/cache/apc.php b/tests/lib/cache/apc.php
deleted file mode 100644
index bb5eb483dbf..00000000000
--- a/tests/lib/cache/apc.php
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Robin Appelman
-* @copyright 2012 Robin Appelman icewind@owncloud.com
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-class Test_Cache_APC extends Test_Cache {
- public function setUp() {
- if(!extension_loaded('apc')) {
- $this->markTestSkipped('The apc extension is not available.');
- return;
- }
- if(!ini_get('apc.enable_cli') && OC::$CLI) {
- $this->markTestSkipped('apc not available in CLI.');
- return;
- }
- $this->instance=new OC_Cache_APC();
- }
-}
diff --git a/tests/lib/cache/xcache.php b/tests/lib/cache/xcache.php
deleted file mode 100644
index 43bed2db037..00000000000
--- a/tests/lib/cache/xcache.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Robin Appelman
-* @copyright 2012 Robin Appelman icewind@owncloud.com
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-class Test_Cache_XCache extends Test_Cache {
- public function setUp() {
- if(!function_exists('xcache_get')) {
- $this->markTestSkipped('The xcache extension is not available.');
- return;
- }
- $this->instance=new OC_Cache_XCache();
- }
-}
diff --git a/tests/lib/memcache/apc.php b/tests/lib/memcache/apc.php
new file mode 100644
index 00000000000..6b2a49470ba
--- /dev/null
+++ b/tests/lib/memcache/apc.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Memcache;
+
+class APC extends Cache {
+ public function setUp() {
+ if(!\OC\Memcache\APC::isAvailable()) {
+ $this->markTestSkipped('The apc extension is not available.');
+ return;
+ }
+ $this->instance=new \OC\Memcache\APC(uniqid());
+ }
+}
diff --git a/tests/lib/memcache/cache.php b/tests/lib/memcache/cache.php
new file mode 100644
index 00000000000..e2643b9fcd9
--- /dev/null
+++ b/tests/lib/memcache/cache.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Memcache;
+
+class Cache extends \Test_Cache {
+ public function testExistsAfterSet() {
+ $this->assertFalse($this->instance->hasKey('foo'));
+ $this->instance->set('foo', 'bar');
+ $this->assertTrue($this->instance->hasKey('foo'));
+ }
+
+ public function testGetAfterSet() {
+ $this->assertNull($this->instance->get('foo'));
+ $this->instance->set('foo', 'bar');
+ $this->assertEquals('bar', $this->instance->get('foo'));
+ }
+
+ public function testDoesNotExistAfterRemove() {
+ $this->instance->set('foo', 'bar');
+ $this->instance->remove('foo');
+ $this->assertFalse($this->instance->hasKey('foo'));
+ }
+
+ public function testArrayAccessSet() {
+ $this->instance['foo'] = 'bar';
+ $this->assertEquals('bar', $this->instance->get('foo'));
+ }
+
+ public function testArrayAccessGet() {
+ $this->instance->set('foo', 'bar');
+ $this->assertEquals('bar', $this->instance['foo']);
+ }
+
+ public function testArrayAccessExists() {
+ $this->assertFalse(isset($this->instance['foo']));
+ $this->instance->set('foo', 'bar');
+ $this->assertTrue(isset($this->instance['foo']));
+ }
+
+ public function testArrayAccessUnset() {
+ $this->instance->set('foo', 'bar');
+ unset($this->instance['foo']);
+ $this->assertFalse($this->instance->hasKey('foo'));
+ }
+
+ public function tearDown() {
+ if ($this->instance) {
+ $this->instance->clear();
+ }
+ }
+}
diff --git a/tests/lib/memcache/memcached.php b/tests/lib/memcache/memcached.php
new file mode 100644
index 00000000000..4b38ae8ef3c
--- /dev/null
+++ b/tests/lib/memcache/memcached.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Memcache;
+
+class Memcached extends Cache {
+ public function setUp() {
+ if (!\OC\Memcache\Memcached::isAvailable()) {
+ $this->markTestSkipped('The memcached extension is not available.');
+ return;
+ }
+ $this->instance = new \OC\Memcache\Memcached(uniqid());
+ }
+}
diff --git a/tests/lib/memcache/xcache.php b/tests/lib/memcache/xcache.php
new file mode 100644
index 00000000000..f59afda3966
--- /dev/null
+++ b/tests/lib/memcache/xcache.php
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Memcache;
+
+class XCache extends Cache {
+ public function setUp() {
+ if (!\OC\Memcache\XCache::isAvailable()) {
+ $this->markTestSkipped('The xcache extension is not available.');
+ return;
+ }
+ $this->instance = new \OC\Memcache\XCache(uniqid());
+ }
+}