[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/classes/session/ -> memcache.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   * 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  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1