From 80a3f8d066b7deffe70a232ca956746db02db138 Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Sun, 17 Mar 2013 16:00:39 +0100
Subject: [PATCH 1/7] Seperate memory based cache from OC_Cache

---
 lib/cache.php                                 | 67 ++--------------
 lib/cache/apc.php                             | 64 ----------------
 lib/memcache/apc.php                          | 76 +++++++++++++++++++
 lib/memcache/cache.php                        | 69 +++++++++++++++++
 lib/{cache => memcache}/xcache.php            | 31 +++++---
 tests/lib/cache/apc.php                       | 35 ---------
 .../{cache/xcache.php => memcache/apc.php}    |  8 +-
 tests/lib/memcache/xcache.php                 | 31 ++++++++
 8 files changed, 210 insertions(+), 171 deletions(-)
 delete mode 100644 lib/cache/apc.php
 create mode 100644 lib/memcache/apc.php
 create mode 100644 lib/memcache/cache.php
 rename lib/{cache => memcache}/xcache.php (66%)
 delete mode 100644 tests/lib/cache/apc.php
 rename tests/lib/{cache/xcache.php => memcache/apc.php} (80%)
 create mode 100644 tests/lib/memcache/xcache.php

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..b3bb68223b4
--- /dev/null
+++ b/lib/memcache/apc.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 APC extends Cache {
+	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;
+	}
+
+	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..d77ea27933f
--- /dev/null
+++ b/lib/memcache/cache.php
@@ -0,0 +1,69 @@
+<?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 {
+	/**
+	 * get a cache instance
+	 *
+	 * @param bool $global
+	 * @return Cache
+	 */
+	static function create($global = false) {
+		if (XCache::isAvailable()) {
+			return new XCache($global);
+		} elseif (APC::isAvailable()) {
+			return new APC($global);
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * @param bool $global
+	 */
+	abstract public function __construct($global);
+
+	/**
+	 * @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 = '');
+
+	/**
+	 * @return bool
+	 */
+	//static public function isAvailable();
+}
diff --git a/lib/cache/xcache.php b/lib/memcache/xcache.php
similarity index 66%
rename from lib/cache/xcache.php
rename to lib/memcache/xcache.php
index 9f380f870b9..0ee34c667d3 100644
--- a/lib/cache/xcache.php
+++ b/lib/memcache/xcache.php
@@ -6,13 +6,15 @@
  * See the COPYING-README file.
  */
 
-class OC_Cache_XCache {
+namespace OC\Memcache;
+
+class XCache extends Cache {
 	protected $prefix;
 
 	public function __construct($global = false) {
-		$this->prefix = OC_Util::getInstanceId().'/';
+		$this->prefix = \OC_Util::getInstanceId().'/';
 		if (!$global) {
-			$this->prefix .= OC_User::getUser().'/';
+			$this->prefix .= \OC_User::getUser().'/';
 		}
 	}
 
@@ -44,13 +46,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/memcache/apc.php
similarity index 80%
rename from tests/lib/cache/xcache.php
rename to tests/lib/memcache/apc.php
index 43bed2db037..e3dccc09669 100644
--- a/tests/lib/cache/xcache.php
+++ b/tests/lib/memcache/apc.php
@@ -20,12 +20,12 @@
 *
 */
 
-class Test_Cache_XCache extends Test_Cache {
+class Test_Memcache_APC extends Test_Cache {
 	public function setUp() {
-		if(!function_exists('xcache_get')) {
-			$this->markTestSkipped('The xcache extension is not available.');
+		if(!\OC\Memcache\APC::isAvailable()) {
+			$this->markTestSkipped('The apc extension is not available.');
 			return;
 		}
-		$this->instance=new OC_Cache_XCache();
+		$this->instance=new \OC\Memcache\APC();
 	}
 }
diff --git a/tests/lib/memcache/xcache.php b/tests/lib/memcache/xcache.php
new file mode 100644
index 00000000000..48773533c89
--- /dev/null
+++ b/tests/lib/memcache/xcache.php
@@ -0,0 +1,31 @@
+<?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_Memcache_XCache extends Test_Cache {
+	public function setUp() {
+		if (!\OC\Memcache\XCache::isAvailable()) {
+			$this->markTestSkipped('The xcache extension is not available.');
+			return;
+		}
+		$this->instance = new \OC\Memcache\XCache();
+	}
+}

From 5418c98a81caba2da00b2e81fb56fe373737a7c8 Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Sun, 17 Mar 2013 16:01:10 +0100
Subject: [PATCH 2/7] Add memcached backend

---
 lib/memcache/cache.php           |  6 ++-
 lib/memcache/memcached.php       | 81 ++++++++++++++++++++++++++++++++
 tests/lib/memcache/memcached.php | 17 +++++++
 3 files changed, 103 insertions(+), 1 deletion(-)
 create mode 100644 lib/memcache/memcached.php
 create mode 100644 tests/lib/memcache/memcached.php

diff --git a/lib/memcache/cache.php b/lib/memcache/cache.php
index d77ea27933f..331c689f065 100644
--- a/lib/memcache/cache.php
+++ b/lib/memcache/cache.php
@@ -20,6 +20,8 @@ abstract class Cache {
 			return new XCache($global);
 		} elseif (APC::isAvailable()) {
 			return new APC($global);
+		} elseif (Memcached::isAvailable()) {
+			return new Memcached($global);
 		} else {
 			return null;
 		}
@@ -65,5 +67,7 @@ abstract class Cache {
 	/**
 	 * @return bool
 	 */
-	//static public function isAvailable();
+	static 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..ab35bd8bbac
--- /dev/null
+++ b/lib/memcache/memcached.php
@@ -0,0 +1,81 @@
+<?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 {
+	protected $prefix;
+
+	/**
+	 * @var \Memcached $cache
+	 */
+	private static $cache = null;
+
+	public function __construct($global = false) {
+		$this->prefix = \OC_Util::getInstanceId() . '/';
+		if (!$global) {
+			$this->prefix .= \OC_User::getUser() . '/';
+		}
+		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/tests/lib/memcache/memcached.php b/tests/lib/memcache/memcached.php
new file mode 100644
index 00000000000..a0be047ed1f
--- /dev/null
+++ b/tests/lib/memcache/memcached.php
@@ -0,0 +1,17 @@
+<?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.
+ */
+
+class Test_Memcache_Memcached extends Test_Cache {
+	public function setUp() {
+		if (!\OC\Memcache\Memcached::isAvailable()) {
+			$this->markTestSkipped('The memcached extension is not available.');
+			return;
+		}
+		$this->instance = new \OC\Memcache\Memcached();
+	}
+}

From d82c1dfcabe84709ff02ea5c13c82c573d524937 Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Tue, 16 Jul 2013 15:34:22 +0200
Subject: [PATCH 3/7] split out memcache factory from base class

---
 lib/memcache/cache.php   | 25 +------------------------
 lib/memcache/factory.php | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 24 deletions(-)
 create mode 100644 lib/memcache/factory.php

diff --git a/lib/memcache/cache.php b/lib/memcache/cache.php
index 331c689f065..b9e0c2249ac 100644
--- a/lib/memcache/cache.php
+++ b/lib/memcache/cache.php
@@ -9,23 +9,7 @@
 namespace OC\Memcache;
 
 abstract class Cache {
-	/**
-	 * get a cache instance
-	 *
-	 * @param bool $global
-	 * @return Cache
-	 */
-	static function create($global = false) {
-		if (XCache::isAvailable()) {
-			return new XCache($global);
-		} elseif (APC::isAvailable()) {
-			return new APC($global);
-		} elseif (Memcached::isAvailable()) {
-			return new Memcached($global);
-		} else {
-			return null;
-		}
-	}
+
 
 	/**
 	 * @param bool $global
@@ -63,11 +47,4 @@ abstract class Cache {
 	 * @return mixed
 	 */
 	abstract public function clear($prefix = '');
-
-	/**
-	 * @return bool
-	 */
-	static public function isAvailable() {
-		return XCache::isAvailable() || APC::isAvailable() || Memcached::isAvailable();
-	}
 }
diff --git a/lib/memcache/factory.php b/lib/memcache/factory.php
new file mode 100644
index 00000000000..1926582aa5c
--- /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 bool $global
+	 * @return \OC\Memcache\Cache
+	 */
+	function create($global = false) {
+		if (XCache::isAvailable()) {
+			return new XCache($global);
+		} elseif (APC::isAvailable()) {
+			return new APC($global);
+		} elseif (Memcached::isAvailable()) {
+			return new Memcached($global);
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * check if there is a memcache backend available
+	 *
+	 * @return bool
+	 */
+	public function isAvailable() {
+		return XCache::isAvailable() || APC::isAvailable() || Memcached::isAvailable();
+	}
+}

From 69048ab71f615ea7a219f7f119855319cf38621d Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Tue, 16 Jul 2013 15:42:40 +0200
Subject: [PATCH 4/7] memchache: use prefix string instead of global flag

---
 lib/memcache/apc.php       | 11 +----------
 lib/memcache/cache.php     | 15 ++++++++++++---
 lib/memcache/memcached.php |  9 ++-------
 lib/memcache/xcache.php    |  9 ---------
 4 files changed, 15 insertions(+), 29 deletions(-)

diff --git a/lib/memcache/apc.php b/lib/memcache/apc.php
index b3bb68223b4..575ee4427db 100644
--- a/lib/memcache/apc.php
+++ b/lib/memcache/apc.php
@@ -9,15 +9,6 @@
 namespace OC\Memcache;
 
 class APC extends Cache {
-	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
 	 */
@@ -61,7 +52,7 @@ class APC extends Cache {
 			return false;
 		} elseif (!ini_get('apc.enable_cli') && \OC::$CLI) {
 			return false;
-		}else{
+		} else {
 			return true;
 		}
 	}
diff --git a/lib/memcache/cache.php b/lib/memcache/cache.php
index b9e0c2249ac..9db69ae4104 100644
--- a/lib/memcache/cache.php
+++ b/lib/memcache/cache.php
@@ -9,12 +9,21 @@
 namespace OC\Memcache;
 
 abstract class Cache {
-
+	/**
+	 * @var string $prefix
+	 */
+	protected $prefix;
 
 	/**
-	 * @param bool $global
+	 * @param string $prefix
 	 */
-	abstract public function __construct($global);
+	public function __construct($prefix = '') {
+		$this->prefix = \OC_Util::getInstanceId() . '/' . $prefix;
+	}
+
+	public function getPrefix() {
+		return $this->prefix;
+	}
 
 	/**
 	 * @param string $key
diff --git a/lib/memcache/memcached.php b/lib/memcache/memcached.php
index ab35bd8bbac..978e6c2eff1 100644
--- a/lib/memcache/memcached.php
+++ b/lib/memcache/memcached.php
@@ -9,18 +9,13 @@
 namespace OC\Memcache;
 
 class Memcached extends Cache {
-	protected $prefix;
-
 	/**
 	 * @var \Memcached $cache
 	 */
 	private static $cache = null;
 
-	public function __construct($global = false) {
-		$this->prefix = \OC_Util::getInstanceId() . '/';
-		if (!$global) {
-			$this->prefix .= \OC_User::getUser() . '/';
-		}
+	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));
diff --git a/lib/memcache/xcache.php b/lib/memcache/xcache.php
index 0ee34c667d3..33de30562f9 100644
--- a/lib/memcache/xcache.php
+++ b/lib/memcache/xcache.php
@@ -9,15 +9,6 @@
 namespace OC\Memcache;
 
 class XCache extends Cache {
-	protected $prefix;
-
-	public function __construct($global = false) {
-		$this->prefix = \OC_Util::getInstanceId().'/';
-		if (!$global) {
-			$this->prefix .= \OC_User::getUser().'/';
-		}
-	}
-
 	/**
 	 * entries in XCache gets namespaced to prevent collisions between owncloud instances and users
 	 */

From 8ad148feaf975481815b3f2413fc1fa34b3e8be7 Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Tue, 16 Jul 2013 15:46:27 +0200
Subject: [PATCH 5/7] memcache: some additional unit tests

---
 tests/lib/memcache/apc.php       | 31 +++++++++------------------
 tests/lib/memcache/cache.php     | 36 ++++++++++++++++++++++++++++++++
 tests/lib/memcache/memcached.php |  7 +++++--
 tests/lib/memcache/xcache.php    | 29 ++++++++-----------------
 4 files changed, 60 insertions(+), 43 deletions(-)
 create mode 100644 tests/lib/memcache/cache.php

diff --git a/tests/lib/memcache/apc.php b/tests/lib/memcache/apc.php
index e3dccc09669..6b2a49470ba 100644
--- a/tests/lib/memcache/apc.php
+++ b/tests/lib/memcache/apc.php
@@ -1,31 +1,20 @@
 <?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/>.
-*
-*/
+ * 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 Test_Memcache_APC extends Test_Cache {
+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();
+		$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..2c1dbc9d2f7
--- /dev/null
+++ b/tests/lib/memcache/cache.php
@@ -0,0 +1,36 @@
+<?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 tearDown() {
+		if ($this->instance) {
+			$this->instance->clear();
+		}
+	}
+}
diff --git a/tests/lib/memcache/memcached.php b/tests/lib/memcache/memcached.php
index a0be047ed1f..4b38ae8ef3c 100644
--- a/tests/lib/memcache/memcached.php
+++ b/tests/lib/memcache/memcached.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
  * This file is licensed under the Affero General Public License version 3 or
@@ -6,12 +7,14 @@
  * See the COPYING-README file.
  */
 
-class Test_Memcache_Memcached extends Test_Cache {
+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();
+		$this->instance = new \OC\Memcache\Memcached(uniqid());
 	}
 }
diff --git a/tests/lib/memcache/xcache.php b/tests/lib/memcache/xcache.php
index 48773533c89..f59afda3966 100644
--- a/tests/lib/memcache/xcache.php
+++ b/tests/lib/memcache/xcache.php
@@ -1,31 +1,20 @@
 <?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/>.
- *
+ * 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.
  */
 
-class Test_Memcache_XCache extends Test_Cache {
+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();
+		$this->instance = new \OC\Memcache\XCache(uniqid());
 	}
 }

From 504089940de88220a425db21e8e133582fe15c30 Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Tue, 16 Jul 2013 16:06:00 +0200
Subject: [PATCH 6/7] mamcache: implement the ArrayAccess interface

---
 lib/memcache/cache.php       | 20 +++++++++++++++++++-
 tests/lib/memcache/cache.php | 22 ++++++++++++++++++++++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/lib/memcache/cache.php b/lib/memcache/cache.php
index 9db69ae4104..0ad1cc7ec03 100644
--- a/lib/memcache/cache.php
+++ b/lib/memcache/cache.php
@@ -8,7 +8,7 @@
 
 namespace OC\Memcache;
 
-abstract class Cache {
+abstract class Cache implements \ArrayAccess {
 	/**
 	 * @var string $prefix
 	 */
@@ -56,4 +56,22 @@ abstract class Cache {
 	 * @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/tests/lib/memcache/cache.php b/tests/lib/memcache/cache.php
index 2c1dbc9d2f7..e2643b9fcd9 100644
--- a/tests/lib/memcache/cache.php
+++ b/tests/lib/memcache/cache.php
@@ -28,6 +28,28 @@ class Cache extends \Test_Cache {
 		$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();

From dc1a17b6f486c565ff5b30a6446421f1436355af Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Tue, 16 Jul 2013 16:08:37 +0200
Subject: [PATCH 7/7] memcache: also switch factory to prefix

---
 lib/memcache/factory.php | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/memcache/factory.php b/lib/memcache/factory.php
index 1926582aa5c..b1b49971031 100644
--- a/lib/memcache/factory.php
+++ b/lib/memcache/factory.php
@@ -12,16 +12,16 @@ class Factory {
 	/**
 	 * get a cache instance, will return null if no backend is available
 	 *
-	 * @param bool $global
+	 * @param string $prefix
 	 * @return \OC\Memcache\Cache
 	 */
-	function create($global = false) {
+	function create($prefix = '') {
 		if (XCache::isAvailable()) {
-			return new XCache($global);
+			return new XCache($prefix);
 		} elseif (APC::isAvailable()) {
-			return new APC($global);
+			return new APC($prefix);
 		} elseif (Memcached::isAvailable()) {
-			return new Memcached($global);
+			return new Memcached($prefix);
 		} else {
 			return null;
 		}