From 6eb6313b6f9f8b42dc58bea3f432235b954a2d5c Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Tue, 7 Aug 2012 15:25:46 +1000 Subject: [PATCH] Allow session storage to be configured independently * Introduce $wgSessionCacheType to allow the session storage to be configured independently of $wgMemc. * Renamed $wgSessionsInMemcached to $wgSessionsInObjectCache to reflect the new versatility. * Modernized the relevant code, removing the explicit require_once(), used the autoloader instead. Moved it to ObjectCacheSessionHandler. * Tested with memcached, external sharded MySQL and APC, it all seems to work just fine. Change-Id: I473334bb56cafb4e21ac1c1304d69095676fc0c4 --- RELEASE-NOTES-1.20 | 4 + includes/AutoLoader.php | 1 + includes/DefaultSettings.php | 21 ++- includes/GlobalFunctions.php | 17 +-- includes/cache/MemcachedSessions.php | 115 --------------- .../objectcache/ObjectCacheSessionHandler.php | 137 ++++++++++++++++++ 6 files changed, 163 insertions(+), 132 deletions(-) delete mode 100644 includes/cache/MemcachedSessions.php create mode 100644 includes/objectcache/ObjectCacheSessionHandler.php diff --git a/RELEASE-NOTES-1.20 b/RELEASE-NOTES-1.20 index 5a76c84e2d..c52ff60970 100644 --- a/RELEASE-NOTES-1.20 +++ b/RELEASE-NOTES-1.20 @@ -108,6 +108,10 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki. * Added support in jquery.localize for placeholder attributes. * (bug 38151) Implemented mw.user.getRights for getting and caching the current user's user rights. +* Session storage can now configured independently of general object cache + storage, by using $wgSessionCacheType. $wgSessionsInMemcached has been + renamed to $wgSessionsInObjectCache, with the old name retained for backwards + compatibility. * Implemented mw.user.getGroups for getting and caching user groups. * (bug 37830) Added $wgRequirePasswordforEmailChange to control whether password confirmation is required for changing an email address or not. diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index e9e0440bb5..e50430eb23 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -731,6 +731,7 @@ $wgAutoloadLocalClasses = array( 'MultiWriteBagOStuff' => 'includes/objectcache/MultiWriteBagOStuff.php', 'MWMemcached' => 'includes/objectcache/MemcachedClient.php', 'ObjectCache' => 'includes/objectcache/ObjectCache.php', + 'ObjectCacheSessionHandler' => 'includes/objectcache/ObjectCacheSessionHandler.php', 'SqlBagOStuff' => 'includes/objectcache/SqlBagOStuff.php', 'WinCacheBagOStuff' => 'includes/objectcache/WinCacheBagOStuff.php', 'XCacheBagOStuff' => 'includes/objectcache/XCacheBagOStuff.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index ffe22cad55..dda191e4f1 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1659,6 +1659,13 @@ $wgMessageCacheType = CACHE_ANYTHING; */ $wgParserCacheType = CACHE_ANYTHING; +/** + * The cache type for storing session data. Used if $wgSessionsInObjectCache is true. + * + * For available types see $wgMainCacheType. + */ +$wgSessionCacheType = CACHE_ANYTHING; + /** * The cache type for storing language conversion tables, * which are used when parsing certain text and interface messages. @@ -1714,12 +1721,20 @@ $wgParserCacheExpireTime = 86400; $wgDBAhandler = 'db3'; /** - * Store sessions in MemCached. This can be useful to improve performance, or to - * avoid the locking behaviour of PHP's default session handler, which tends to - * prevent multiple requests for the same user from acting concurrently. + * Deprecated alias for $wgSessionsInObjectCache. + * + * @deprecated Use $wgSessionsInObjectCache */ $wgSessionsInMemcached = false; +/** + * Store sessions in an object cache, configured by $wgSessionCacheType. This + * can be useful to improve performance, or to avoid the locking behaviour of + * PHP's default session handler, which tends to prevent multiple requests for + * the same user from acting concurrently. + */ +$wgSessionsInObjectCache = false; + /** * This is used for setting php's session.save_handler. In practice, you will * almost never need to change this ever. Other options might be 'user' or diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index e25ce26685..3e2b63e71b 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -3372,21 +3372,10 @@ function wfFixSessionID() { * @param $sessionId Bool */ function wfSetupSession( $sessionId = false ) { - global $wgSessionsInMemcached, $wgCookiePath, $wgCookieDomain, + global $wgSessionsInMemcached, $wgSessionsInObjectCache, $wgCookiePath, $wgCookieDomain, $wgCookieSecure, $wgCookieHttpOnly, $wgSessionHandler; - if( $wgSessionsInMemcached ) { - if ( !defined( 'MW_COMPILED' ) ) { - global $IP; - require_once( "$IP/includes/cache/MemcachedSessions.php" ); - } - session_set_save_handler( 'memsess_open', 'memsess_close', 'memsess_read', - 'memsess_write', 'memsess_destroy', 'memsess_gc' ); - - // It's necessary to register a shutdown function to call session_write_close(), - // because by the time the request shutdown function for the session module is - // called, $wgMemc has already been destroyed. Shutdown functions registered - // this way are called before object destruction. - register_shutdown_function( 'memsess_write_close' ); + if( $wgSessionsInObjectCache || $wgSessionsInMemcached ) { + ObjectCacheSessionHandler::install(); } elseif( $wgSessionHandler && $wgSessionHandler != ini_get( 'session.save_handler' ) ) { # Only set this if $wgSessionHandler isn't null and session.save_handler # hasn't already been set to the desired value (that causes errors) diff --git a/includes/cache/MemcachedSessions.php b/includes/cache/MemcachedSessions.php deleted file mode 100644 index fe43635422..0000000000 --- a/includes/cache/MemcachedSessions.php +++ /dev/null @@ -1,115 +0,0 @@ -get( memsess_key( $id ) ); - if( ! $data ) return ''; - return $data; -} - -/** - * Callback when writing session data. - * - * @param $id String: session id - * @param $data Mixed: session data - * @return Boolean: success - */ -function memsess_write( $id, $data ) { - global $wgMemc; - $wgMemc->set( memsess_key( $id ), $data, 3600 ); - return true; -} - -/** - * Callback to destroy a session when calling session_destroy(). - * - * @param $id String: session id - * @return Boolean: success - */ -function memsess_destroy( $id ) { - global $wgMemc; - - $wgMemc->delete( memsess_key( $id ) ); - return true; -} - -/** - * Callback to execute garbage collection. - * NOP: Memcached performs garbage collection. - * - * @param $maxlifetime Integer: maximum session life time - * @return Boolean: success - */ -function memsess_gc( $maxlifetime ) { - return true; -} - -function memsess_write_close() { - session_write_close(); -} - diff --git a/includes/objectcache/ObjectCacheSessionHandler.php b/includes/objectcache/ObjectCacheSessionHandler.php new file mode 100644 index 0000000000..3dcfa9f690 --- /dev/null +++ b/includes/objectcache/ObjectCacheSessionHandler.php @@ -0,0 +1,137 @@ +get( self::getKey( $id ) ); + if( $data === false ) { + return ''; + } + return $data; + } + + /** + * Callback when writing session data. + * + * @param $id String: session id + * @param $data Mixed: session data + * @return Boolean: success + */ + static function write( $id, $data ) { + self::getCache()->set( self::getKey( $id ), $data, 3600 ); + return true; + } + + /** + * Callback to destroy a session when calling session_destroy(). + * + * @param $id String: session id + * @return Boolean: success + */ + static function destroy( $id ) { + self::getCache()->delete( self::getKey( $id ) ); + return true; + } + + /** + * Callback to execute garbage collection. + * NOP: Object caches perform garbage collection implicitly + * + * @param $maxlifetime Integer: maximum session life time + * @return Boolean: success + */ + static function gc( $maxlifetime ) { + return true; + } + + /** + * Shutdown function. See the comment inside ObjectCacheSessionHandler::install + * for rationale. + */ + static function handleShutdown() { + session_write_close(); + } +} -- 2.20.1