[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Memcache based session handler. 19 * 20 * This is based on the memcached code. It lacks some features, such as 21 * locking options, but appears to work in practice. 22 * 23 * Note: You may need to manually configure redundancy and fail-over 24 * if you specify multiple servers. 25 * 26 * @package core 27 * @copyright 2014 The Open University 28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 29 */ 30 31 namespace core\session; 32 33 defined('MOODLE_INTERNAL') || die(); 34 35 /** 36 * Memcache based session handler. 37 * 38 * @package core 39 * @copyright 2014 The Open University 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42 class memcache extends handler { 43 /** @var string $savepath save_path string */ 44 protected $savepath; 45 /** @var array $servers list of servers parsed from save_path */ 46 protected $servers; 47 /** @var int $acquiretimeout how long to wait for session lock */ 48 protected $acquiretimeout = 120; 49 50 /** 51 * Creates new instance of handler. 52 */ 53 public function __construct() { 54 global $CFG; 55 56 if (empty($CFG->session_memcache_save_path)) { 57 $this->savepath = ''; 58 } else { 59 $this->savepath = $CFG->session_memcache_save_path; 60 } 61 62 if (empty($this->savepath)) { 63 $this->servers = array(); 64 } else { 65 $this->servers = util::connection_string_to_memcache_servers($this->savepath); 66 } 67 68 if (!empty($CFG->session_memcache_acquire_lock_timeout)) { 69 $this->acquiretimeout = (int)$CFG->session_memcache_acquire_lock_timeout; 70 } 71 } 72 73 /** 74 * Starts the session. 75 * 76 * @return bool success 77 */ 78 public function start() { 79 $default = ini_get('max_execution_time'); 80 set_time_limit($this->acquiretimeout); 81 82 $result = parent::start(); 83 84 set_time_limit($default); 85 return $result; 86 } 87 88 /** 89 * Inits session handler. 90 */ 91 public function init() { 92 if (!extension_loaded('memcache')) { 93 throw new exception('sessionhandlerproblem', 'error', '', null, 94 'memcache extension is not loaded'); 95 } 96 $version = phpversion('memcache'); 97 if (!$version or version_compare($version, '2.2') < 0) { 98 throw new exception('sessionhandlerproblem', 'error', '', null, 99 'memcache extension version must be at least 2.2'); 100 } 101 if (empty($this->savepath)) { 102 throw new exception('sessionhandlerproblem', 'error', '', null, 103 '$CFG->session_memcache_save_path must be specified in config.php'); 104 } 105 // Check in case anybody mistakenly includes tcp://, which you 106 // would do in the raw PHP config. We require the same format as 107 // for memcached (without tcp://). Otherwse the code that splits it into 108 // individual servers won't have worked properly. 109 if (strpos($this->savepath, 'tcp://') !== false) { 110 throw new exception('sessionhandlerproblem', 'error', '', null, 111 '$CFG->session_memcache_save_path should not contain tcp://'); 112 } 113 114 ini_set('session.save_handler', 'memcache'); 115 116 // The format of save_path is different for memcache (compared to memcached). 117 // We are using the same format in config.php to avoid confusion. 118 // It has to have tcp:// at the start of each entry. 119 $memcacheformat = preg_replace('~(^|,\s*)~','$1tcp://', $this->savepath); 120 ini_set('session.save_path', $memcacheformat); 121 } 122 123 /** 124 * Check the backend contains data for this session id. 125 * 126 * Note: this is intended to be called from manager::session_exists() only. 127 * 128 * @param string $sid PHP session ID 129 * @return bool true if session found. 130 */ 131 public function session_exists($sid) { 132 $result = false; 133 134 foreach ($this->get_memcaches() as $memcache) { 135 if ($result === false) { 136 $value = $memcache->get($sid); 137 if ($value !== false) { 138 $result = true; 139 } 140 } 141 $memcache->close(); 142 } 143 144 return $result; 145 } 146 147 /** 148 * Gets the Memcache objects, one for each server. 149 * The connects must be closed manually after use. 150 * 151 * Note: the servers are not automatically synchronised 152 * when accessed via Memcache class, it needs to be 153 * done manually by accessing all configured servers. 154 * 155 * @return \Memcache[] Array of initialised memcache objects 156 */ 157 protected function get_memcaches() { 158 $result = array(); 159 foreach ($this->servers as $server) { 160 $memcache = new \Memcache(); 161 $memcache->addServer($server[0], $server[1]); 162 $result[] = $memcache; 163 } 164 return $result; 165 } 166 167 /** 168 * Kills all active sessions, the core sessions table is purged afterwards. 169 */ 170 public function kill_all_sessions() { 171 global $DB; 172 if (!$this->servers) { 173 return; 174 } 175 176 $memcaches = $this->get_memcaches(); 177 178 // Note: this can be significantly improved by fetching keys from memcache, 179 // but we need to make sure we are not deleting somebody else's sessions. 180 181 $rs = $DB->get_recordset('sessions', array(), 'id DESC', 'id, sid'); 182 foreach ($rs as $record) { 183 foreach ($memcaches as $memcache) { 184 $memcache->delete($record->sid); 185 } 186 } 187 $rs->close(); 188 189 foreach ($memcaches as $memcache) { 190 $memcache->close(); 191 } 192 } 193 194 /** 195 * Kills one session, the session record is removed afterwards. 196 * 197 * @param string $sid PHP session ID 198 */ 199 public function kill_session($sid) { 200 foreach ($this->get_memcaches() as $memcache) { 201 $memcache->delete($sid); 202 $memcache->close(); 203 } 204 } 205 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |