[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/classes/session/ -> memcached.php (source)

   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   * Memcached based session handler.
  19   *
  20   * @package    core
  21   * @copyright  2013 Petr Skoda {@link http://skodak.org}
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace core\session;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  /**
  30   * Memcached based session handler.
  31   *
  32   * @package    core
  33   * @copyright  2013 Petr Skoda {@link http://skodak.org}
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class memcached extends handler {
  37      /** @var string $savepath save_path string  */
  38      protected $savepath;
  39      /** @var array $servers list of servers parsed from save_path */
  40      protected $servers;
  41      /** @var string $prefix session key prefix  */
  42      protected $prefix;
  43      /** @var int $acquiretimeout how long to wait for session lock */
  44      protected $acquiretimeout = 120;
  45      /**
  46       * @var int $lockexpire how long to wait before expiring the lock so that other requests
  47       * may continue execution, ignored if memcached <= 2.1.0.
  48       */
  49      protected $lockexpire = 7200;
  50  
  51      /**
  52       * Create new instance of handler.
  53       */
  54      public function __construct() {
  55          global $CFG;
  56  
  57          if (empty($CFG->session_memcached_save_path)) {
  58              $this->savepath = '';
  59          } else {
  60              $this->savepath =  $CFG->session_memcached_save_path;
  61          }
  62  
  63          if (empty($this->savepath)) {
  64              $this->servers = array();
  65          } else {
  66              $this->servers = util::connection_string_to_memcache_servers($this->savepath);
  67          }
  68  
  69          if (empty($CFG->session_memcached_prefix)) {
  70              $this->prefix = ini_get('memcached.sess_prefix');
  71          } else {
  72              $this->prefix = $CFG->session_memcached_prefix;
  73          }
  74  
  75          if (!empty($CFG->session_memcached_acquire_lock_timeout)) {
  76              $this->acquiretimeout = (int)$CFG->session_memcached_acquire_lock_timeout;
  77          }
  78  
  79          if (!empty($CFG->session_memcached_lock_expire)) {
  80              $this->lockexpire = (int)$CFG->session_memcached_lock_expire;
  81          }
  82      }
  83  
  84      /**
  85       * Start the session.
  86       * @return bool success
  87       */
  88      public function start() {
  89          // NOTE: memcached <= 2.1.0 expires session locks automatically after max_execution_time,
  90          //       this leads to major difference compared to other session drivers that timeout
  91          //       and stop the second request execution instead.
  92  
  93          $default = ini_get('max_execution_time');
  94          set_time_limit($this->acquiretimeout);
  95  
  96          $result = parent::start();
  97  
  98          set_time_limit($default);
  99          return $result;
 100      }
 101  
 102      /**
 103       * Init session handler.
 104       */
 105      public function init() {
 106          if (!extension_loaded('memcached')) {
 107              throw new exception('sessionhandlerproblem', 'error', '', null, 'memcached extension is not loaded');
 108          }
 109          $version = phpversion('memcached');
 110          if (!$version or version_compare($version, '2.0') < 0) {
 111              throw new exception('sessionhandlerproblem', 'error', '', null, 'memcached extension version must be at least 2.0');
 112          }
 113          if (empty($this->savepath)) {
 114              throw new exception('sessionhandlerproblem', 'error', '', null, '$CFG->session_memcached_save_path must be specified in config.php');
 115          }
 116  
 117          ini_set('session.save_handler', 'memcached');
 118          ini_set('session.save_path', $this->savepath);
 119          ini_set('memcached.sess_prefix', $this->prefix);
 120          ini_set('memcached.sess_locking', '1'); // Locking is required!
 121  
 122          // Try to configure lock and expire timeouts - ignored if memcached <=2.1.0.
 123          ini_set('memcached.sess_lock_max_wait', $this->acquiretimeout);
 124          ini_set('memcached.sess_lock_expire', $this->lockexpire);
 125      }
 126  
 127      /**
 128       * Check the backend contains data for this session id.
 129       *
 130       * Note: this is intended to be called from manager::session_exists() only.
 131       *
 132       * @param string $sid
 133       * @return bool true if session found.
 134       */
 135      public function session_exists($sid) {
 136          if (!$this->servers) {
 137              return false;
 138          }
 139  
 140          // Go through the list of all servers because
 141          // we do not know where the session handler put the
 142          // data.
 143  
 144          foreach ($this->servers as $server) {
 145              list($host, $port) = $server;
 146              $memcached = new \Memcached();
 147              $memcached->addServer($host, $port);
 148              $value = $memcached->get($this->prefix . $sid);
 149              $memcached->quit();
 150              if ($value !== false) {
 151                  return true;
 152              }
 153          }
 154  
 155          return false;
 156      }
 157  
 158      /**
 159       * Kill all active sessions, the core sessions table is
 160       * purged afterwards.
 161       */
 162      public function kill_all_sessions() {
 163          global $DB;
 164          if (!$this->servers) {
 165              return;
 166          }
 167  
 168          // Go through the list of all servers because
 169          // we do not know where the session handler put the
 170          // data.
 171  
 172          $memcacheds = array();
 173          foreach ($this->servers as $server) {
 174              list($host, $port) = $server;
 175              $memcached = new \Memcached();
 176              $memcached->addServer($host, $port);
 177              $memcacheds[] = $memcached;
 178          }
 179  
 180          // Note: this can be significantly improved by fetching keys from memcached,
 181          //       but we need to make sure we are not deleting somebody else's sessions.
 182  
 183          $rs = $DB->get_recordset('sessions', array(), 'id DESC', 'id, sid');
 184          foreach ($rs as $record) {
 185              foreach ($memcacheds as $memcached) {
 186                  $memcached->delete($this->prefix . $record->sid);
 187              }
 188          }
 189          $rs->close();
 190  
 191          foreach ($memcacheds as $memcached) {
 192              $memcached->quit();
 193          }
 194      }
 195  
 196      /**
 197       * Kill one session, the session record is removed afterwards.
 198       * @param string $sid
 199       */
 200      public function kill_session($sid) {
 201          if (!$this->servers) {
 202              return;
 203          }
 204  
 205          // Go through the list of all servers because
 206          // we do not know where the session handler put the
 207          // data.
 208  
 209          foreach ($this->servers as $server) {
 210              list($host, $port) = $server;
 211              $memcached = new \Memcached();
 212              $memcached->addServer($host, $port);
 213              $memcached->delete($this->prefix . $sid);
 214              $memcached->quit();
 215          }
 216      }
 217  
 218  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1