Merge branch 'w44_MDL-42485_m26_memcachedlocktimeout' of https://github.com/skodak...
authorDan Poltawski <dan@moodle.com>
Tue, 29 Oct 2013 05:42:56 +0000 (13:42 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 29 Oct 2013 05:42:56 +0000 (13:42 +0800)
config-dist.php
lib/classes/session/handler.php
lib/classes/session/manager.php
lib/classes/session/memcached.php

index c5bf4be..3050973 100644 (file)
@@ -237,6 +237,8 @@ $CFG->admin = 'admin';
 //      $CFG->session_handler_class = '\core\session\memcached';
 //      $CFG->session_memcached_save_path = '127.0.0.1:11211';
 //      $CFG->session_memcached_prefix = 'memc.sess.key.';
+//      $CFG->session_memcached_acquire_lock_timeout = 120;
+//      $CFG->session_memcached_lock_expire = 7200;       // Ignored if memcached extension <= 2.1.0
 //
 // Following setting allows you to alter how frequently is timemodified updated in sessions table.
 //      $CFG->session_update_timemodified_frequency = 20; // In seconds.
index a656175..995784a 100644 (file)
@@ -34,6 +34,14 @@ defined('MOODLE_INTERNAL') || die();
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 abstract class handler {
+    /**
+     * Start the session.
+     * @return bool success
+     */
+    public function start() {
+        return session_start();
+    }
+
     /**
      * Init session handler.
      */
index 2b1e7f0..c5e764c 100644 (file)
@@ -74,7 +74,7 @@ class manager {
             self::prepare_cookies();
             $newsid = empty($_COOKIE[session_name()]);
 
-            session_start();
+            self::$handler->start();
 
             self::initialise_user_session($newsid);
             self::check_security();
index 7281537..4e07f3c 100644 (file)
@@ -40,6 +40,13 @@ class memcached extends handler {
     protected $servers;
     /** @var string $prefix session key prefix  */
     protected $prefix;
+    /** @var int $acquiretimeout how long to wait for session lock */
+    protected $acquiretimeout = 120;
+    /**
+     * @var int $lockexpire how long to wait before expiring the lock so that other requests
+     * may continue execution, ignored if memcached <= 2.1.0.
+     */
+    protected $lockexpire = 7200;
 
     /**
      * Create new instance of handler.
@@ -64,6 +71,32 @@ class memcached extends handler {
         } else {
             $this->prefix = $CFG->session_memcached_prefix;
         }
+
+        if (!empty($CFG->session_memcached_acquire_lock_timeout)) {
+            $this->acquiretimeout = (int)$CFG->session_memcached_acquire_lock_timeout;
+        }
+
+        if (!empty($CFG->session_memcached_lock_expire)) {
+            $this->lockexpire = (int)$CFG->session_memcached_lock_expire;
+        }
+    }
+
+    /**
+     * Start the session.
+     * @return bool success
+     */
+    public function start() {
+        // NOTE: memcached <= 2.1.0 expires session locks automatically after max_execution_time,
+        //       this leads to major difference compared to other session drivers that timeout
+        //       and stop the second request execution instead.
+
+        $default = ini_get('max_execution_time');
+        set_time_limit($this->acquiretimeout);
+
+        $result = parent::start();
+
+        set_time_limit($default);
+        return $result;
     }
 
     /**
@@ -81,11 +114,14 @@ class memcached extends handler {
             throw new exception('sessionhandlerproblem', 'error', '', null, '$CFG->session_memcached_save_path must be specified in config.php');
         }
 
-        // NOTE: we cannot set any lock acquiring timeout here - bad luck.
         ini_set('session.save_handler', 'memcached');
         ini_set('session.save_path', $this->savepath);
         ini_set('memcached.sess_prefix', $this->prefix);
         ini_set('memcached.sess_locking', '1'); // Locking is required!
+
+        // Try to configure lock and expire timeouts - ignored if memcached <=2.1.0.
+        ini_set('memcached.sess_lock_max_wait', $this->acquiretimeout);
+        ini_set('memcached.sess_lock_expire', $this->lockexpire);
     }
 
     /**