From e8b52671aea20b26584973dadbb89833d829c0cb Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Thu, 7 Aug 2014 15:21:07 +1200 Subject: [PATCH] MDL-46711 session: add support for multiple servers to memcache session driver Includes proper definition of object properties which fixes handling of timout default. --- lib/classes/session/memcache.php | 64 +++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/lib/classes/session/memcache.php b/lib/classes/session/memcache.php index fc3005064c0..fc7eb61f88f 100644 --- a/lib/classes/session/memcache.php +++ b/lib/classes/session/memcache.php @@ -20,6 +20,9 @@ * This is based on the memcached code. It lacks some features, such as * locking options, but appears to work in practice. * + * Note: You may need to manually configure redundancy and fail-over + * if you specify multiple servers. + * * @package core * @copyright 2014 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -37,6 +40,13 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class memcache extends handler { + /** @var string $savepath save_path string */ + protected $savepath; + /** @var array $servers list of servers parsed from save_path */ + protected $servers; + /** @var int $acquiretimeout how long to wait for session lock */ + protected $acquiretimeout = 120; + /** * Creates new instance of handler. */ @@ -119,28 +129,39 @@ class memcache extends handler { * @return bool true if session found. */ public function session_exists($sid) { - if (!$this->servers) { - return false; + $result = false; + + foreach ($this->get_memcaches() as $memcache) { + if ($result === false) { + $value = $memcache->get($sid); + if ($value !== false) { + $result = true; + } + } + $memcache->close(); } - $memcache = $this->get_memcache(); - $value = $memcache->get($sid); - $memcache->close(); - - return ($value !== false); + return $result; } /** - * Gets the memcache object with all the servers added to it. + * Gets the Memcache objects, one for each server. + * The connects must be closed manually after use. * - * @return \Memcache Initialised memcache object + * Note: the servers are not automatically synchronised + * when accessed via Memcache class, it needs to be + * done manually by accessing all configured servers. + * + * @return \Memcache[] Array of initialised memcache objects */ - protected function get_memcache() { - $memcache = new \Memcache(); + protected function get_memcaches() { + $result = array(); foreach ($this->servers as $server) { + $memcache = new \Memcache(); $memcache->addServer($server[0], $server[1]); + $result[] = $memcache; } - return $memcache; + return $result; } /** @@ -152,18 +173,22 @@ class memcache extends handler { return; } - $memcache = $this->get_memcache(); + $memcaches = $this->get_memcaches(); // Note: this can be significantly improved by fetching keys from memcache, // but we need to make sure we are not deleting somebody else's sessions. $rs = $DB->get_recordset('sessions', array(), 'id DESC', 'id, sid'); foreach ($rs as $record) { - $memcache->delete($record->sid); + foreach ($memcaches as $memcache) { + $memcache->delete($record->sid); + } } $rs->close(); - $memcache->close(); + foreach ($memcaches as $memcache) { + $memcache->close(); + } } /** @@ -172,12 +197,9 @@ class memcache extends handler { * @param string $sid PHP session ID */ public function kill_session($sid) { - if (!$this->servers) { - return; + foreach ($this->get_memcaches() as $memcache) { + $memcache->delete($sid); + $memcache->close(); } - - $memcache = $this->get_memcache(); - $memcache->delete($sid); - $memcache->close(); } }