[imp] memcached sessions

liam hoekenga liamr at umich.edu
Fri Oct 28 15:50:11 PDT 2005


> The mcache extension doesn't do compression natively, so you'd have 
> to (un)compress the data as it's transmitted.  The error condition 
> also doesn't seem to pick up when it's tried to connect to a server 
> it can't, while the extension itself does report this error:

Ok.. I added compression and persistent connections to my hack.  
Persistent connections don't quite right.  I can't seem to establish a 
connection w/ them (but if I switch to persistent connections 
mid-session, it works).  They also sometime effect the page load, in 
that when using persistent connections, the page will look completely 
loaded and is useable, but the browser keeps spinning, waiting for 
something else to be sent.

Still looks promising though.

Liam
-------------- next part --------------
<?php
/**
 * SessionHandler:: implementation for memcached.
 * memcached website: http://www.danga.com/memcached/
 *
 * Required parameters:<pre>
 *   'hostspec'  The hostname of the memcached server.
 *   'port'      The port on which to connect to the memcached server.</pre>
 *
 * $Horde: framework/SessionHandler/SessionHandler/memcached.php,v 1.8.2.1 2005/06/26 04:28:31 chuck Exp $
 *
 * Copyright 2005 Rong-En Fan <rafan at infor.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 at infor.org>
 * @since   Horde 3.1
 * @package Horde_SessionHandler
 */
class SessionHandler_mcache extends SessionHandler {

    /**
     * Current memcached connection.
     *
     * @var resource
     */
    var $_db;

    /**
     * Boolean indicating whether or not we're connected to the SQL server.
     *
     * @var boolean
     */
    var $_connected = false;

    /**
     * Read the data for a particular session identifier from the
     * SessionHandler backend.
     *
     * @param string $id  The session identifier.
     *
     * @return string  The session data.
     */
    function read($id)
    {
        /* Make sure we have a valid database connection. */
        $this->_connect($id);

        $result = $this->_db->get($id);

        if (!$result) {
            Horde::logMessage('Error retrieving session data (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_ERR);
            return false;
        }

	if($this->_params['compression']) {
	    $result = gzuncompress($result);
	}
        return $result;
    }

    /**
     * Write session data to the SessionHandler backend.
     *
     * @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)
    {
        /* Make sure we have a valid database connection. */
        $this->_connect($id);

        $lifetime = ini_get('session.gc_maxlifetime');
	if($this->_params['compression']) {
	    $session_data = gzcompress($session_data);
	}
        $result = $this->_db->set($id, $session_data, $lifetime);

        if (!$result) {
            Horde::logMessage('Error writing session data (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_ERR);
            return false;
        }

        return true;
    }

    /**
     * Destroy the data for a particular session identifier in the
     * SessionHandler backend.
     *
     * @param string $id  The session identifier.
     *
     * @return boolean  True on success, false otherwise.
     */
    function destroy($id)
    {
        /* Make sure we have a valid database connection. */
        $this->_connect($id);

        $result = $this->_db->delete($id);

        if (!$result) {
            Horde::logMessage('Failed to delete session (id = ' . $id . ')', __FILE__, __LINE__, PEAR_LOG_ERR);
            return false;
        }

        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)
    {
        return true;
    }

    /**
     * Attempts to open a connection to the memcached server.
     *
     * @access private
     */
    function _connect($id)
    {
        if ($this->_connected) {
            return;
        }

        Horde::assertDriverConfig($this->_params, 'sessionhandler',
            array('hostspec', 'port'),
            'session handler mcache');

        if (empty($this->_params['persistent'])) {
	    $this->_db = memcache();
	    Horde::logMessage( "non-persistent", __FILE__, __LINE__,PEAR_LOG_ERR);

	    for ($i = 0, $n = count($this->_params['hostspec']); $i < $n; $i++) {
		$this->_db->add_server($this->_params['hostspec'][$i],
				      $this->_params['port'][$i]); 
		Horde::logMessage('Added to memcached pool for mcache SessionHandler at ' . $this->_params['hostspec'][$i] . ':' . $this->_params['port'][$i] , __FILE__, __LINE__, PEAR_LOG_DEBUG);
		$this->_connected = true;
	    }
        } else {
	    $this->_db = pmemcache($id, ini_get('session.gc_maxlifetime'));
	    Horde::logMessage( "persistent: $id", __FILE__, __LINE__,PEAR_LOG_ERR);
	    if(!$this->_db->is_initialized()) {
		for ($i = 0, $n = count($this->_params['hostspec']); $i < $n; $i++) {
		    $this->_db->add_server($this->_params['hostspec'][$i],
					  $this->_params['port'][$i]); 
		    Horde::logMessage('Added to memcached pool for mcache SessionHandler at ' . $this->_params['hostspec'][$i] . ':' . $this->_params['port'][$i] , __FILE__, __LINE__, PEAR_LOG_DEBUG);
		    $this->_connected = true;
		}
		$this->_db->set_initialized(TRUE);
	    }
        }
    }
}


More information about the imp mailing list