/horde-3.3.13/lib/Horde/SessionHandler/memcache.php
PHP | 372 lines | 187 code | 50 blank | 135 comment | 38 complexity | 581076ac71e812c10d1a4e021548687c MD5 | raw file
Possible License(s): LGPL-2.0
- <?php
- require_once 'Horde/Memcache.php';
- /**
- * SessionHandler:: implementation for memcache.
- *
- * NOTE FOR WINDOWS USERS w/PHP 4: Due to limitations in PHP 4, you should not
- * use the memcache driver. Either upgrade to PHP 5 or use a different
- * session handler.
- *
- * Optional parameters:<pre>
- * 'persistent_driver' - (string) If set, uses this backend to store session
- * data persistently.
- * 'persistent_params' - (array) If using a persistent backend, the params
- * to use for the persistent backend.
- * 'track' - (boolean) Track active sessions?
- * 'track_lifetime' - (integer) The number of seconds after which tracked
- * sessions will be treated as expired.
- * </pre>
- *
- * $Horde: framework/SessionHandler/SessionHandler/memcache.php,v 1.1.2.13 2009/10/06 22:22:20 slusarz Exp $
- *
- * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (LGPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
- *
- * @author Rong-En Fan <rafan@infor.org>
- * @author Michael Slusarz <slusarz@curecanti.org>
- * @since Horde 3.1
- * @package Horde_SessionHandler
- */
- class SessionHandler_memcache extends SessionHandler {
- /**
- * Horde_Memcache object.
- *
- * @var Horde_Cache
- */
- var $_memcache;
- /**
- * Current session ID.
- *
- * @var string
- */
- var $_id;
- /**
- * Persistent backend driver.
- *
- * @var SessionHandler
- */
- var $_persistent;
- /**
- * Do read-only get?
- *
- * @var boolean
- */
- var $_readonly = false;
- /**
- * The ID used for session tracking.
- *
- * @var string
- */
- var $_trackID = 'horde_memcache_sessions_track';
- /**
- * Constructs a new Memcache SessionHandler object.
- *
- * @param array $params A hash containing connection parameters.
- */
- function SessionHandler_memcache($params = array())
- {
- if (!empty($params['persistent_driver'])) {
- $this->_persistent = &SessionHandler::singleton($params['persistent_driver'], empty($params['persistent_params']) ? null : $params['persistent_params']);
- if (is_a($this->_persistent, 'PEAR_Error')) {
- return PEAR::raiseError('Horde is unable to correctly start the persistent session handler.');
- }
- }
- parent::SessionHandler($params);
- // If using a persistent backend, don't track sessions in memcache
- if (isset($this->_persistent)) {
- $this->_params['track'] = false;
- }
- if (empty($this->_params['track_lifetime'])) {
- $this->_params['track_lifetime'] = ini_get('session.gc_maxlifetime');
- }
- }
- /**
- * Open the SessionHandler backend.
- *
- * @access private
- *
- * @param string $save_path The path to the session object.
- * @param string $session_name The name of the session.
- *
- * @return boolean True on success, false otherwise.
- */
- function _open($save_path = null, $session_name = null)
- {
- $this->_memcache = &Horde_Memcache::singleton();
- if (is_a($this->_memcache, 'PEAR_Error')) {
- return $this->_memcache;
- }
- if (isset($this->_persistent)) {
- $res = $this->_persistent->open($save_path, $session_name);
- if (is_a($res, 'PEAR_Error')) {
- return $res;
- }
- }
- // Garbage collection for session tracking information - run 0.1%
- // of all session accesses.
- if (!empty($this->_params['track']) && (rand(0, 999) == 0)) {
- register_shutdown_function(array(&$this, '_trackGC'));
- }
- return true;
- }
- /**
- * Close the SessionHandler backend.
- *
- * @access private
- *
- * @return boolean True on success, false otherwise.
- */
- function _close()
- {
- if (isset($this->_id)) {
- $this->_memcache->unlock($this->_id);
- }
- if (isset($this->_persistent)) {
- $this->_persistent->close();
- }
- return true;
- }
- /**
- * Read the data for a particular session identifier.
- *
- * @access private
- *
- * @param string $id The session identifier.
- *
- * @return string The session data.
- */
- function _read($id)
- {
- if (!$this->_readonly) {
- $this->_memcache->lock($id);
- }
- $result = $this->_memcache->get($id);
- if ($result === false) {
- if (!$this->_readonly) {
- $this->_memcache->unlock($id);
- }
- if (isset($this->_persistent)) {
- $result = $this->_persistent->read($id);
- }
- if ($result === false) {
- Horde::logMessage('Error retrieving session data (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_DEBUG);
- return false;
- }
- $this->_persistent->write($id, $session_data);
- }
- if (!$this->_readonly) {
- $this->_id = $id;
- }
- Horde::logMessage('Read session data (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_DEBUG);
- return $result;
- }
- /**
- * Write session data to the SessionHandler backend.
- *
- * @access private
- *
- * @param string $id The session identifier.
- * @param string $session_data The session data.
- *
- * @return boolean True on success, false otherwise.
- */
- function _write($id, $session_data)
- {
- if (!empty($this->_params['track'])) {
- // Do a replace - the only time it should fail is if we are
- // writing a session for the first time. If that is the case,
- // update the session tracker.
- $res = $this->_memcache->replace($id, $session_data);
- $track = !$res;
- } else {
- $res = $track = false;
- }
- if (!$res &&
- !$this->_memcache->set($id, $session_data)) {
- Horde::logMessage('Error writing session data (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_ERR);
- return false;
- }
- if (isset($this->_persistent)) {
- $result = $this->_persistent->write($id, $session_data);
- }
- if ($track) {
- $this->_memcache->lock($this->_trackID);
- $ids = $this->_memcache->get($this->_trackID);
- if ($ids === false) {
- $ids = array();
- }
- $ids[$id] = time();
- $this->_memcache->set($this->_trackID, $ids);
- $this->_memcache->unlock($this->_trackID);
- }
- Horde::logMessage('Wrote session data (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_DEBUG);
- return true;
- }
- /**
- * Destroy the data for a particular session identifier.
- *
- * @param string $id The session identifier.
- *
- * @return boolean True on success, false otherwise.
- */
- function destroy($id)
- {
- $result = $this->_memcache->delete($id);
- $this->_memcache->unlock($id);
- if ($result === false) {
- Horde::logMessage('Failed to delete session (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_DEBUG);
- return false;
- }
- if (isset($this->_persistent)) {
- $result = $this->_persistent->destroy($id);
- }
- if (!empty($this->_params['track'])) {
- $this->_memcache->lock($this->_trackID);
- $ids = $this->_memcache->get($this->_trackID);
- if ($ids !== false) {
- unset($ids[$id]);
- $this->_memcache->set($this->_trackID, $ids);
- }
- $this->_memcache->unlock($this->_trackID);
- }
- Horde::logMessage('Deleted session data (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_DEBUG);
- return true;
- }
- /**
- * Garbage collect stale sessions from the SessionHandler backend.
- *
- * @param integer $maxlifetime The maximum age of a session.
- *
- * @return boolean True on success, false otherwise.
- */
- function gc($maxlifetime = 300)
- {
- $result = true;
- if (isset($this->_persistent)) {
- $result = $this->_persistent->gc($maxlifetime);
- }
- // Memcache does its own garbage collection.
- return $result;
- }
- /**
- * Get a list of (possibly) valid session identifiers.
- *
- * @return array A list of session identifiers or PEAR_Error.
- */
- function getSessionIDs()
- {
- $err = null;
- if (isset($this->_persistent)) {
- return $this->_persistent->getSessionIDs();
- }
- if (!$this->_open()) {
- $err = PEAR::raiseError(_("Could not connect to memcache servers."));
- }
- if (is_null($err) && empty($this->_params['track'])) {
- $err = PEAR::raiseError(_("Memcache session tracking not enabled."));
- }
- if ($err) {
- if (isset($this->_persistent)) {
- return $this->_persistent->getSessionIDs();
- }
- return $err;
- }
- $this->_trackGC();
- $ids = $this->_memcache->get($this->_trackID);
- return ($ids === false) ? array() : array_keys($ids);
- }
- /**
- * Get session data read-only.
- *
- * @access private
- *
- * @param string $id The session identifier.
- *
- * @return string The session data.
- */
- function _readOnly($id)
- {
- $this->_readonly = true;
- $result = $this->_memcache->get($id);
- $this->_readonly = false;
- return $result;
- }
- /**
- * Do garbage collection for session tracking information.
- *
- * @access private
- */
- function _trackGC()
- {
- $this->_memcache->lock($this->_trackID);
- $ids = $this->_memcache->get($this->_trackID);
- if (empty($ids)) {
- $this->_memcache->unlock($this->_trackID);
- return;
- }
- $tstamp = time() - $this->_params['track_lifetime'];
- $alter = false;
- foreach ($ids as $key => $val) {
- if ($tstamp > $val) {
- unset($ids[$key]);
- $alter = true;
- }
- }
- if ($alter) {
- $this->_memcache->set($this->_trackID, $ids);
- }
- $this->_memcache->unlock($this->_trackID);
- }
- }