Location: PHPKode > scripts > Distributed Session Manager > sessionmanager.php
<?php

/**
 * Distributed Session Manager class
 * 
 * @author Robin Schuil <hide@address.com>
 * @version 0.1.0
 * 
 * Usage:
 *   $sessionmanager = new SessionManager();
 *   session_start();
 */

/* Path to your session hosts configuration file */
define( 'SESSIONS_HOSTS_FILE', './session_hosts.ini' );

/* MySQL connect timeout for session servers */
define( 'SESSIONS_CONNECT_TIMEOUT', 2 );

/* The number of replica's you want to be stored of each session */
define( 'SESSIONS_NUM_COPIES', 1 );

class SessionManager {
	
	var $hosts;
	var $dbs;
	
	function SessionManager() {
		
		// Read the maxlifetime setting from PHP
		$this->life_time = get_cfg_var("session.gc_maxlifetime");
		
		// Read the hosts configuration file
		$this->hosts = parse_ini_file( SESSIONS_HOSTS_FILE, true );
		
		// Database pool
		$this->dbs = array();
		
		// Register this object as the session handler
		session_set_save_handler( 
			array( &$this, "open" ), 
			array( &$this, "close" ),
			array( &$this, "read" ),
			array( &$this, "write"),
			array( &$this, "destroy"),
			array( &$this, "gc" )
		);
		
	}
	
	function open( $save_path, $session_name ) {
		
		// Don't need to do anything. Just return TRUE.
		return true;
		
	}
	
	function close() {
		
		// Clean up all opened database connections
		while( $db = array_shift( $this->dbs ) ) {
			@mysql_close( $db );
		}
		
	}
	
	function read( $id ) {
		
		// Get a copy of the hosts configuration
		$tmp_hosts = $this->hosts;
		
		// Seed the pseudo randomizer with a CRC32 checksum of the session ID
		srand( crc32( $id ) );
		
		// 'Randomly' shuffle the array of hosts
		shuffle( $tmp_hosts );
		
		do {
			
			// Get next host from list
			$config = array_shift( $tmp_hosts );
			if( !$config ) {
				// Oops, no hosts left to try. Escape
				break;
			}
			
			// Try to connect
			$db = $this->mysql_quick_connect( $config['host'], $config['user'], $config['password'], $config['database'] );
												
		} while( !$db ); // Repeat until we've succesfully connected to a host
		
		// Set empty result
		$data = '';
		
		if( $db ) {

			// Fetch session data from the selected database
			$sql = 'SELECT `session_data` FROM `sessions` WHERE `session_id` = \'' . addslashes( $id ) . '\' AND `expires` < UNIX_TIMESTAMP();';
			$result = mysql_query( $sql, $db );
			
			if( $result && mysql_num_rows( $result ) ) {
				
				$data = mysql_result( $result, 0, 'session_data' );
				
				@mysql_free_result( $result );
				
			}
			
		}
		
		return $data;
		
	}
	
	function write( $id, $data ) {
		
		// Get a copy of the hosts configuration
		$tmp_hosts = $this->hosts;

		// Seed the pseudo randomizer with a CRC32 checksum of the session ID	
		srand( crc32( $id ) );
		
		// 'Randomly' shuffle the array of hosts
		shuffle( $tmp_hosts );

		// Initialize the replication counter at 0
		$replicate_count = 0;
		
		// Build query before we start looping		
		$sql = 'REPLACE `sessions` (`session_id`,`session_data`,`expires`) VALUES(\'' . addslashes( $id ) . '\', \'' . addslashes( $data ) . '\', UNIX_TIMESTAMP() + ' . $this->life_time . ');';
		
		do {
			
			// Get next host from list
			$config = array_shift( $tmp_hosts );
			if( !$config ) {
				// Oops, no hosts left to try. Escape
				break;
			}
			
			// Try to connect
			$db = $this->mysql_quick_connect( $config['host'], $config['user'], $config['password'], $config['database'] );

			// If we're connected, try to execute the query
			if( $db && mysql_query( $sql, $db ) ) {
				
				// Query was executed succesfull; increase the replication counter
				$replicate_count++;
					
			}
			
		} while( $replicate_count < SESSIONS_NUM_COPIES ); // Keep going until we've reached SESSION_NUM_COPIES
		
		// Return TRUE if at least one copy was stored
		return (bool) ( $replicate_count > 0 );
		
	}
	
	function destroy( $id ) {

		// Get a copy of the hosts configuration
		$tmp_hosts = $this->hosts;
		
		// Seed the pseudo randomizer with a CRC32 checksum of the session ID	
		srand( crc32( $id ) );
		
		// 'Randomly' shuffle the array of hosts
		shuffle( $tmp_hosts );

		// Initialize the replication counter at 0
		$replicate_count = 0;

		// Build query before we start looping		
		$sql = 'DELETE FROM `sessions` WHERE `session_id` = \'' . addslashes( $id ) . '\';';
		
		do {
			
			// Get next host from list
			$config = array_shift( $tmp_hosts );
			if( !$config ) {
				// Oops, no hosts left to try. Escape
				break;
			}
			
			// Try to connect
			$db = $this->mysql_quick_connect( $config['host'], $config['user'], $config['password'], $config['database'] );

			// If we're connected, try to execute the query
			if( $db && mysql_query( $sql, $db ) ) {
				
				// Query was executed succesfull; increase the replication counter
				$replicate_count++;
					
			}
			
		} while( $replicate_count < SESSIONS_NUM_COPIES ); // Keep going until we've reached SESSION_NUM_COPIES
		
		// Return TRUE if at least one query was succesfull
		return (bool) ( $replicate_count > 0 );		
		
	}
	
	function gc() {
		
		// Build DELETE query
		$sql = 'DELETE FROM `sessions` WHERE `expires` >= UNIX_TIMESTAMP();';
		
		// For each open database connection
		foreach( $this->dbs as $db ) {

			// Execute query
			@mysql_query( $sql, $db );
			
		}
		
		// Always return TRUE
		return true;
		
	}
	
	function mysql_quick_connect( $host, $user, $password, $database ) {
		
		// See if it is in the database pool
		if( $this->dbs[$host] ) {
			
			// If so, return the link identifier from the pool
			return $this->dbs[$host];
			
		}
		else {
			
			// Set MySQL connect timeout to our low value
			ini_set( "mysql.connect_timeout", SESSIONS_CONNECT_TIMEOUT );
			
			// Try to connect
			$link_id = @mysql_connect( $host, $user, $password );
			
			if( $link_id ) {
				
				// Connection established!
			
				// Select the database
				@mysql_select_db( $database );
					
				// Add this connection to our pool
				$this->dbs[$host] = $link_id;
				
			}
			
			// Restore PHP's default setting
			ini_restore( "mysql.connect_timeout" );
			
			// Return the link identifier
			return $link_id;
			
		}
		
	}
	
}


?>
Return current item: Distributed Session Manager