You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by cr...@locus.apache.org on 2000/01/31 06:29:04 UTC

cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session StandardManager.java

craigmcc    00/01/30 21:29:04

  Modified:    proposals/catalina/src/share/org/apache/tomcat/session
                        StandardManager.java
  Log:
  Add support for optional session persistence (to a configurable disk file
  pathname) across server restarts.  This can also be used to provide
  persistence across auto-reloads of a web application when that is
  supported.
  
  Revision  Changes    Path
  1.4       +205 -7    jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardManager.java
  
  Index: StandardManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardManager.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- StandardManager.java	2000/01/29 07:46:35	1.3
  +++ StandardManager.java	2000/01/31 05:29:04	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardManager.java,v 1.3 2000/01/29 07:46:35 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/01/29 07:46:35 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/session/StandardManager.java,v 1.4 2000/01/31 05:29:04 craigmcc Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/01/31 05:29:04 $
    *
    * ====================================================================
    *
  @@ -64,7 +64,14 @@
   
   package org.apache.tomcat.session;
   
  +import java.io.BufferedInputStream;
  +import java.io.BufferedOutputStream;
  +import java.io.FileInputStream;
  +import java.io.FileNotFoundException;
  +import java.io.FileOutputStream;
   import java.io.IOException;
  +import java.io.ObjectInputStream;
  +import java.io.ObjectOutputStream;
   import java.util.Enumeration;
   import java.util.Hashtable;
   import java.util.Vector;
  @@ -80,11 +87,16 @@
   
   /**
    * Standard implementation of the <b>Manager</b> interface that provides
  - * no session persistence or distributable capabilities, but does support
  - * an optional, configurable, maximum number of active sessions allowed.
  + * simple session persistence across restarts of this component (such as
  + * when the entire server is shut down and restarted, or when a particular
  + * web application is reloaded.
  + * <p>
  + * <b>IMPLEMENTATION NOTE</b>:  Correct behavior of session storing and
  + * reloading depends upon external calls to the <code>start()</code> and
  + * <code>stop()</code> methods of this class at the correct times.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.3 $ $Date: 2000/01/29 07:46:35 $
  + * @version $Revision: 1.4 $ $Date: 2000/01/31 05:29:04 $
    */
   
   public final class StandardManager
  @@ -110,10 +122,18 @@
       /**
        * The maximum number of active Sessions allowed, or -1 for no limit.
        */
  -    protected int maxActiveSessions = -1;
  +    private int maxActiveSessions = -1;
   
   
       /**
  +     * Path name of the disk file in which active sessions are saved
  +     * when we stop, and from which these sessions are loaded when we start.
  +     * A <code>null</code> value indicates that no persistence is desired.
  +     */
  +    private String pathname = null;
  +
  +
  +    /**
        * The string manager for this package.
        */
       private StringManager sm =
  @@ -213,6 +233,31 @@
       }
   
   
  +    /**
  +     * Return the session persistence pathname, if any.
  +     */
  +    public String getPathname() {
  +
  +	return (this.pathname);
  +
  +    }
  +
  +
  +    /**
  +     * Set the session persistence pathname to the specified value.  If no
  +     * persistence support is desired, set the pathname to <code>null</code>.
  +     *
  +     * @param pathname New session persistence pathname
  +     */
  +    public void setPathname(String pathname) {
  +
  +	String oldPathname = this.pathname;
  +	this.pathname = pathname;
  +	support.firePropertyChange("pathname", oldPathname, this.pathname);
  +
  +    }
  +
  +
       // --------------------------------------------------------- Public Methods
   
   
  @@ -259,6 +304,9 @@
   		(sm.getString("standardManager.alreadyStarted"));
   	started = true;
   
  +	// Load any previously persisted sessions
  +	load();
  +
   	// Start the background reaper thread
   	threadStart();
   
  @@ -285,6 +333,9 @@
   	// Stop the background reaper thread
   	threadStop();
   
  +	// Save any currently active sessions
  +	unload();
  +
   	// Expire all active sessions
   	Session sessions[] = findSessions();
   	for (int i = 0; i < sessions.length; i++) {
  @@ -301,6 +352,83 @@
   
   
       /**
  +     * Load any currently active sessions that were previously unloaded
  +     * to the specified persistence file, if any.
  +     *
  +     * @exception LifecycleException if a fatal error is encountered
  +     */
  +    private void load() throws LifecycleException {
  +
  +	// Initialize our internal data structures
  +	recycled.removeAllElements();
  +	sessions.clear();
  +
  +	// Open an input stream to the specified pathname, if any
  +	if (pathname == null)
  +	    return;
  +	FileInputStream fis = null;
  +	ObjectInputStream ois = null;
  +	try {
  +	    fis = new FileInputStream(pathname);
  +	    ois = new ObjectInputStream(new BufferedInputStream(fis));
  +	} catch (FileNotFoundException e) {
  +	    return;
  +	} catch (IOException e) {
  +	    if (ois != null) {
  +		try {
  +		    ois.close();
  +		} catch (IOException f) {
  +		    ;
  +		}
  +		ois = null;
  +	    }
  +	    throw new LifecycleException("load/open: IOException", e);
  +	}
  +
  +	// Load the previously unloaded active sessions
  +	synchronized (sessions) {
  +	    try {
  +		Integer count = (Integer) ois.readObject();
  +		int n = count.intValue();
  +		for (int i = 0; i < n; i++) {
  +		    Session session = (Session) ois.readObject();
  +		    sessions.put(session.getId(), session);
  +		}
  +	    } catch (ClassNotFoundException e) {
  +		if (ois != null) {
  +		    try {
  +			ois.close();
  +		    } catch (IOException f) {
  +			;
  +		    }
  +		    ois = null;
  +		}
  +		throw new LifecycleException
  +		    ("load/read: ClassNotFoundException", e);
  +	    } catch (IOException e) {
  +		if (ois != null) {
  +		    try {
  +			ois.close();
  +		    } catch (IOException f) {
  +			;
  +		    }
  +		    ois = null;
  +		}
  +		throw new LifecycleException("load/read: IOException", e);
  +	    }
  +	}
  +
  +	// Close the input stream
  +	try {
  +	    ois.close();
  +	} catch (IOException f) {
  +	    ;
  +	}
  +
  +    }
  +
  +
  +    /**
        * Invalidate all sessions that have expired.
        */
       private void processExpires() {
  @@ -320,6 +448,76 @@
   	    if (timeIdle >= maxInactiveInterval)
   		session.expire();
   	}
  +    }
  +
  +
  +    /**
  +     * Save any currently active sessions in the specified persistence file,
  +     * if any.
  +     *
  +     * @exception LifecycleException if a fatal error is encountered
  +     */
  +    private void unload() throws LifecycleException {
  +
  +	// Open an output stream to the specified pathname, if any
  +	if (pathname == null)
  +	    return;
  +	FileOutputStream fos = null;
  +	ObjectOutputStream oos = null;
  +	try {
  +	    fos = new FileOutputStream(pathname);
  +	    oos = new ObjectOutputStream(new BufferedOutputStream(fos));
  +	} catch (IOException e) {
  +	    if (oos != null) {
  +		try {
  +		    oos.close();
  +		} catch (IOException f) {
  +		    ;
  +		}
  +		oos = null;
  +	    }
  +	    throw new LifecycleException("unload/open: IOException", e);
  +	}
  +
  +	// Write the number of active sessions, followed by the details
  +	synchronized (sessions) {
  +	    try {
  +		oos.writeObject(new Integer(sessions.size()));
  +		Enumeration elements = sessions.elements();
  +		while (elements.hasMoreElements()) {
  +		    Session session = (Session) elements.nextElement();
  +		    oos.writeObject(session);
  +		}
  +	    } catch (IOException e) {
  +		if (oos != null) {
  +		    try {
  +			oos.close();
  +		    } catch (IOException f) {
  +			;
  +		    }
  +		    oos = null;
  +		}
  +		throw new LifecycleException("unload/write: IOException", e);
  +	    }
  +	}
  +
  +	// Flush and close the output stream
  +	try {
  +	    oos.flush();
  +	    oos.close();
  +	    oos = null;
  +	} catch (IOException e) {
  +	    if (oos != null) {
  +		try {
  +		    oos.close();
  +		} catch (IOException f) {
  +		    ;
  +		}
  +		oos = null;
  +	    }
  +	    throw new LifecycleException("unload/close: IOException", e);
  +	}
  +
       }