asmuts 02/01/14 22:49:00
Added: src/java/org/apache/stratum/jcs/utils/servlet/session
DistSession.java DistSessionGC.java
DistSessionPoolManager.java DistSessionTracker.java
HttpServletRequestFacade.java
ISessionConstants.java MetaHttpSession.java
SessionIdGenerator.java SessionInfo.java
Log:
distributed session management
needs to be updated. should be fairly easy
Revision Changes Path
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/DistSession.java
Index: DistSession.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
import java.io.*;
import java.util.*;
import javax.servlet.http.*;
import java.util.Enumeration;
import org.apache.stratum.jcs.engine.*;
import org.apache.stratum.jcs.engine.behavior.*;
import org.apache.stratum.jcs.engine.control.*;
import org.apache.stratum.jcs.engine.group.*;
import org.apache.stratum.jcs.access.*;
import org.apache.stratum.jcs.engine.control.Cache;
import org.apache.stratum.jcs.auxiliary.disk.*;
import org.apache.stratum.jcs.auxiliary.remote.*;
import org.apache.stratum.jcs.auxiliary.remote.behavior.*;
import org.apache.stratum.jcs.utils.reuse.*;
import org.apache.stratum.jcs.utils.log.*;
////////////////////////////////////////////////////////////////
/**
* DistSession uses the CompositeCache and GroupCache to create a failover-safe
* distributed session.
*
*/
public class DistSession implements HttpSession, ICleanForPool, ISessionConstants {
private static boolean SET_ATTR_INVOCATION = true;
private static boolean REMOVE_ATTR_INVOCATION = false;
private String session_id;
private SessionInfo sessInfo;
private Logger log;
private GroupCacheAccess sessCache;
private boolean isNew;
private boolean isValid=true;
///////////////////////////////////////////////
public DistSession(){
log = LoggerManager.getLogger( this );
try {
sessCache = GroupCacheAccess.getGroupAccess( SESS_CACHE_NAME );
} catch( Exception e ) {}
}
///////////////////////////////////////////////
/**
* Initialization for an existing session.
* The session must be initialized to be used.
* The sessInfo is not passed int he constructor, becaue these will be pooled.
* @return true if the init is successful;
*/
public boolean init(String session_id) {
this.isNew = false;
this.session_id = session_id;
//sessInfo = (SessionInfo)sessInfoCache.get( session_id );
// not necessary if you don't set default element attributes
// try to get data in the session_id group under the session_id key
sessInfo = (SessionInfo)sessCache.getG( session_id, session_id );
if (sessInfo == null) {
log.info("session not found for " + session_id);
return false;
}
log.info("found session" + sessInfo );
return true;
}
/** Initialization for a new session. */
public void initNew() {
try {
this.isNew = true;
sessInfo = new SessionInfo();
session_id = SessionIdGenerator.createSessionId();
// key, group, value
sessCache.putG( session_id, session_id, sessInfo );
} catch( Exception e ) {}
log.info( "createUserSession " + this);
}
/////////////////////////////////////////////
public void clean() {
sessInfo = null;
}
//REQUIRED INTERFACE METHODS
/////////////////////////////////////////////
public Object getAttribute(String name) {
if (!isValid) {
throw new IllegalStateException("Cannot setAttribute on an invalid session "
+ this);
}
return sessCache.getG(name, session_id);
}
////////////////////////////////////////////////
public Enumeration getAttributeNames() {
return sessCache.getAttributeNames(session_id);
}
///////////////////////////////////////
public long getCreationTime() {
return sessInfo.creationTime;
}
////////////////////////////////////////
public String getId() {
return session_id;
}
/////////////////////////////////////////
public long getLastAccessedTime() {
return sessInfo.lastAccessedTime;
}
/** Update the last access time. */
public void access() {
try {
log.info ( "updating lastAccess for " + this);
sessInfo.lastAccessedTime = System.currentTimeMillis();
sessCache.putG( session_id, session_id, sessInfo );
} catch( Exception e ) {}
return;
}
/////////////////////////////////////////
public int getMaxInactiveInterval() {
return sessInfo.maxInactiveInterval;
}
/**
* @deprecated As of Version 2.1, this method is
* deprecated and has no replacement.
* It will be removed in a future
* version of the Java Servlet API.
*/
public HttpSessionContext getSessionContext(){
return null;
}
////////////////////////////////////
public Object getValue(String name) {
return getAttribute(name);
}
/////////////////////////////////////////
public String[] getValueNames() {
return (String[])sessCache.getAttributeNameSet(session_id).toArray(new
String[0]);
}
/////////////////////////////////////
public void invalidate(){
if (!isValid) {
throw new IllegalStateException("Cannot setAttribute on an invalid session "
+ this);
}
log.info ( "destroying session " + this);
isValid = false;
sessCache.invalidateGroup(session_id);
return;
}
/////////////////////////////////////////
public boolean isNew() {
if (!isValid) {
throw new IllegalStateException("Cannot setAttribute on an invalid session "
+ this);
}
return isNew;
}
///////////////////////////////////////////////
// need to remove the serialzable restrction
public void putValue(String name, Object value) {
setAttribute(name, value);
}
/////////////////////////////////////////////
public void removeAttribute(String name) {
removeAttribute(name, REMOVE_ATTR_INVOCATION);
}
private void removeAttribute(String name, boolean invocation) {
if (!isValid) {
throw new IllegalStateException("Cannot setAttribute on an invalid session "
+ this);
}
// Needs to retrive the attribute so as to do object unbinding, if necessary.
Serializable val = (Serializable)sessCache.getG(name, session_id);
if (val == null)
return;
if (invocation == REMOVE_ATTR_INVOCATION) {
// remove attribute - name set taken care of by the session cache.
sessCache.destroy(name, session_id);
}
// Generate object unbinding event if necessary.
if (val instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) val).valueUnbound(new
HttpSessionBindingEvent(this, name));
}
return;
}
///////////////////////////////////////////////
public void removeValue(String name){
removeAttribute(name);
}
///////////////////////////////////////////////////
public void setAttribute(String name, Object value) {
if (!isValid) {
throw new IllegalStateException("Cannot setAttribute on an invalid session "
+ this);
}
// unbind object first if any.
//removeAttribute(name, SET_ATTR_INVOCATION);
//try {
// sessCache.put(new GroupAttrName(session_id, name), (Serializable)value);
//} catch( Exception e ) {}
try {
sessCache.putG( name, session_id, value );
} catch( Exception e ) {}
// Generate object binding event if necessary.
if (value instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) value).valueBound(new
HttpSessionBindingEvent(this, name));
}
return;
}
///////////////////////////////////////////////////
public void setMaxInactiveInterval(int i) {
sessInfo.maxInactiveInterval = i;
}
public String toString() {
return "[sesson_id=" + session_id + ", sessInfo=" + sessInfo + "]";
}
}
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/DistSessionGC.java
Index: DistSessionGC.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
import org.apache.stratum.jcs.utils.log.*;
import java.util.*;
/** Garbage collector for the DistSession objects. */
class DistSessionGC extends Thread implements ISessionConstants {
private static final long IDLE_PERIOD = DFLT_INACTIVE_INTERVAL;
private static Logger log =
LoggerManager.getInstance().getLogger(DistSessionGC.class);
private final Set sessIdSet;
/** Constructs with the given set of session id's. */
DistSessionGC (Set sessIdSet) {
this.sessIdSet = sessIdSet;
}
/**
* Notifies the garbage collector that there is session available
* and kicks off the garbage collection process.
*/
void notifySession () {
synchronized (this) {
notify();
}
}
// Run forever.
// Minimize the use of any synchronization in the process of garbage collection
// for performance reason.
public void run () {
do {
if (sessIdSet.size() == 0) {
synchronized (this) {
if (sessIdSet.size() == 0) {
if (log.DEBUG <= log.logLevel) {
log.debug("entering into a wait state");
}
// Garbage driven mode.
try {
wait(); // wake up only if there is garbage.
} catch (InterruptedException ignore) {}
}
}
}
// Time driven mode: sleep between each round of garbage collection.
try {
if (log.DEBUG <= log.logLevel) {
log.debug("sessIdSet.size()=" + sessIdSet.size());
log.debug("sleeping for " + IDLE_PERIOD);
}
Thread.currentThread().sleep(IDLE_PERIOD);
} catch (InterruptedException ex) {
// ignore;
}
long now = System.currentTimeMillis();
// Take a snapshot of the hashtable.
String[] sessIds = null;
synchronized (sessIdSet) {
sessIds = (String[])sessIdSet.toArray(new String[0]);
}
if (log.DEBUG <= log.logLevel) {
log.debug("garbage collecting...");
}
for (int i = 0; i < sessIds.length; i++) {
String session_id = sessIds[i];
DistSession sess = new DistSession();
if (!sess.init(session_id)) {
continue;
}
long idleTime = System.currentTimeMillis() - sess.getLastAccessedTime();
int max = sess.getMaxInactiveInterval();
if (idleTime >= max) {
sessIdSet.remove(session_id);
sess.invalidate();
continue;
}
} // end for loop.
} while (true);
}
}
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/DistSessionPoolManager.java
Index: DistSessionPoolManager.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
import java.util.*;
import org.apache.stratum.jcs.utils.log.*;
///////////////////////////////////////////////////////
public class DistSessionPoolManager {
Logger log;
DistSession[] pool;
boolean[] inUse;
///////////////////////////////////////////////////////
public static void main( String args[] ) {
DistSessionPoolManager hpm = new DistSessionPoolManager( 200 );
int num = 1000000;
long start = System.currentTimeMillis();
for ( int i = 0; i < num; i++ ) {
DistSession ht = new DistSession();
}
long end = System.currentTimeMillis();
System.out.println( "New DistSession creation took " + String.valueOf( end -
start ) + " millis." );
start = System.currentTimeMillis();
for ( int i = 0; i < num; i++ ) {
DistSession ht = hpm.getDistSession();
//ht.put( "tre", "ret" );
hpm.returnDistSession( ht );
}
end = System.currentTimeMillis();
System.out.println( "Pooled get and return of Hashtable took " + String.valueOf(
end - start ) + " millis." );
}
////////////////////////////////////////////////////////////
public DistSessionPoolManager(int initialPoolSize) {
log = LoggerManager.getLogger( this );
log.info( "initialPoolSize = " + initialPoolSize );
pool = new DistSession[initialPoolSize];
inUse = new boolean[initialPoolSize];
for (int i = pool.length-1; i>=0; i--) {
pool[i] = new DistSession();
inUse[i] = false;
}
}
////////////////////////////////////////////////////////////
public synchronized DistSession getDistSession() {
for (int i = inUse.length-1; i >= 0; i--)
if (!inUse[i]) {
inUse[i] = true;
return pool[i];
}
//If we got here, then all the DistSessions are in use. We will increase the
number in our
//pool by 10.
boolean[] old_inUse = inUse;
inUse = new boolean[old_inUse.length+10];
System.arraycopy(old_inUse, 0, inUse, 0, old_inUse.length);
DistSession[] old_pool = pool;
pool = new DistSession[old_pool.length+10];
System.arraycopy(old_pool, 0, pool, 0, old_pool.length);
for (int i = old_pool.length; i < pool.length; i++) {
pool[i] = new DistSession();
inUse[i] = false;
}
inUse[pool.length-1] = true;
return pool[pool.length-1];
}
////////////////////////////////////////////////////////////
public synchronized void returnDistSession(DistSession v) {
for (int i = inUse.length-1; i >= 0; i--) {
if (pool[i] == v) {
inUse[i] = false;
v.clean();
return;
}
}
log.warn( "DistSession was not obtained from the pool: " + v );
}
} // end class
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/DistSessionTracker.java
Index: DistSessionTracker.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
import java.io.*;
import java.rmi.dgc.VMID;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.stratum.jcs.engine.control.*;
import org.apache.stratum.jcs.engine.group.*;
import org.apache.stratum.jcs.engine.behavior.*;
import org.apache.stratum.jcs.access.*;
import org.apache.stratum.jcs.utils.log.*;
import org.apache.stratum.jcs.utils.reuse.*;
////////////////////////////////////////////////////////////////////////
/**
* Manages sessions for the HttpRequestSessionWrapper
*
* @author Aaron Smuts
* @version $Revision: 1.1 $ $Date: 2002/01/15 06:49:00 $
*/
public class DistSessionTracker implements ISessionConstants {
public static final String SESSION_COOKIE_NAME = "SESSION_ID";
private static Logger log = LoggerManager.getLogger(DistSessionTracker.class);
private static DistSessionPoolManager dsMgr = new DistSessionPoolManager(200);
public static DistSessionTracker instance;
static int clients;
/** Used to check and remove expired DistSession objects. */
private static transient Set sessIdSet = Collections.synchronizedSet(new
HashSet());
/** Used to asynchronously remove expired DistSession objects. */
private static transient DistSessionGC gc = new DistSessionGC(sessIdSet);
static {
gc.setDaemon(true);
gc.start();
}
////////////////////////////////////////////////////////////////
private DistSessionTracker () {
}
///////////////////////////////////////////////////////////////////
public static DistSessionTracker getInstance () {
if (instance == null) {
synchronized (DistSessionTracker.class) {
if (instance == null) {
instance = new DistSessionTracker();
}
}
}
clients++;
return instance;
}
//////////////////////////////////////////////
public MetaHttpSession getSession (HttpServletRequest req) {
return getSession(false, req, null);
}
//////////////////////////////////////////////
public MetaHttpSession getSession (boolean create, HttpServletRequest req,
HttpServletResponse res) {
MetaHttpSession ses = getDistSession(req);
return !ses.valid() && create ? createDistSession(req, res) : ses;
}
///////////////////////////////////////////////
private MetaHttpSession createDistSession (HttpServletRequest req,
HttpServletResponse res) {
//not really a pool but a factory. needs to be changed
// theres no way to get it back int the pool
//DistSession sess = ds.Mgr.getDistSession()
String session_id = null;
DistSession sess = new DistSession();
try {
// create a cookie that corrsponds to a session value in the svo
sess.initNew();
// sess.initNew(req.getServerName());
session_id = sess.getId();
Cookie c = new Cookie(SESSION_COOKIE_NAME, session_id);
c.setPath("/");
c.setMaxAge(-1);
res.addCookie(c);
if (log.INFO <= log.logLevel) {
log.info("created cookie session with session=" + sess);
}
if (!sessIdSet.add(session_id)) {
log.error("Session " + sess + " already exist when creating a session");
}
gc.notifySession();
} catch (Exception e) {
log.error(e);
return new MetaHttpSession(session_id, null);
}
return new MetaHttpSession(session_id, sess);
} // end createSession
///////////////////////////////////////////////
private MetaHttpSession getDistSession (HttpServletRequest req) {
log.info("in getSession");
DistSession sess = null;
String session_id = null;
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
String tempName = cookies[i].getName();
if (tempName.equals(SESSION_COOKIE_NAME)) {
session_id = cookies[i].getValue();
}
}
}
if (session_id == null) {
log.info("no cookie found");
return new MetaHttpSession(null, null);
}
sess = new DistSession();
if (!sess.init(session_id)) {
return new MetaHttpSession(session_id, null);
}
long idleTime = System.currentTimeMillis() - sess.getLastAccessedTime();
int max = sess.getMaxInactiveInterval();
if (idleTime > max/2) {
if (idleTime < max) {
sess.access();
}
else {
sessIdSet.remove(session_id);
sess.invalidate();
return new MetaHttpSession(session_id, null);
}
}
return new MetaHttpSession(session_id, sess);
} // end getSession
///////////////////////////
public void release () {
clients--;
}
///////////////////////////
public String getStats () {
String stats = "Number of clients: " + clients;
return stats;
}
} // end class
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/HttpServletRequestFacade.java
Index: HttpServletRequestFacade.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
import java.io.*;
import java.security.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HttpServletRequestFacade implements HttpServletRequest {
private static transient final DistSessionTracker dst =
DistSessionTracker.getInstance();
private final HttpServletRequest req;
private final HttpServletResponse res;
private MetaHttpSession ms;
/////////////////////////////////////////////////////////////////////
/**
* Needs some way to get cookies out, must pass res too!
*/
public HttpServletRequestFacade (HttpServletRequest req, HttpServletResponse res) {
this.req = req;
this.res = res;
}
public String getSessionId() {
return ms == null ? null : ms.session_id;
}
/////////////////////////////////////////////////////////////////
public HttpSession getSession () {
return getSession(false);
}
///////////////////////////////////////////////////////////////
public HttpSession getSession (boolean create) {
if (!create && ms != null) {
return ms.sess;
}
ms = dst.getSession(create, req, res);
return ms.sess;
}
//////////////////////// implements the ServletRequest interface.
//////////////////
public Object getAttribute (String name) {
return req.getAttribute(name);
}
public Enumeration getAttributeNames () {
return req.getAttributeNames();
}
public String getCharacterEncoding () {
return req.getCharacterEncoding();
}
public int getContentLength () {
return req.getContentLength();
}
public String getContentType () {
return req.getContentType();
}
public ServletInputStream getInputStream () throws IOException {
return req.getInputStream();
}
public String getParameter (String name) {
return req.getParameter(name);
}
public Enumeration getParameterNames () {
return req.getParameterNames();
}
public String[] getParameterValues (String name) {
return req.getParameterValues(name);
}
public String getProtocol () {
return req.getProtocol();
}
public String getScheme () {
return req.getScheme();
}
public String getServerName () {
return req.getServerName();
}
public int getServerPort () {
return req.getServerPort();
}
public BufferedReader getReader () throws IOException {
return req.getReader();
}
public String getRemoteAddr () {
return req.getRemoteAddr();
}
public String getRemoteHost () {
return req.getRemoteHost();
}
public void setAttribute (String key, Object o) {
req.setAttribute(key, o);
}
public void removeAttribute (String name) {
req.removeAttribute(name);
}
public Locale getLocale () {
return req.getLocale();
}
public Enumeration getLocales () {
return req.getLocales();
}
public boolean isSecure () {
return req.isSecure();
}
public RequestDispatcher getRequestDispatcher (String path) {
return req.getRequestDispatcher(path);
}
public String getRealPath (String path) {
return req.getRealPath(path);
}
//////////////////////////// implements the HttpServletRequest interface.
/////////////////
public String getAuthType () {
return req.getAuthType();
}
public Cookie[] getCookies () {
return req.getCookies();
}
public long getDateHeader (String name) {
return req.getDateHeader(name);
}
public String getHeader (String name) {
return req.getHeader(name);
}
public Enumeration getHeaders (String name) {
return req.getHeaders(name);
}
public Enumeration getHeaderNames () {
return req.getHeaderNames();
}
public int getIntHeader (String name) {
return req.getIntHeader(name);
}
public String getMethod () {
return req.getMethod();
}
public String getPathInfo () {
return req.getPathInfo();
}
public String getPathTranslated () {
return req.getPathTranslated();
}
public String getContextPath () {
return req.getContextPath();
}
public String getQueryString () {
return req.getQueryString();
}
public String getRemoteUser () {
return req.getRemoteUser();
}
public boolean isUserInRole (String role) {
return req.isUserInRole(role);
}
public Principal getUserPrincipal () {
return req.getUserPrincipal();
}
public String getRequestedSessionId () {
return req.getRequestedSessionId();
}
public String getRequestURI () {
return req.getRequestURI();
}
public String getServletPath () {
return req.getServletPath();
}
public boolean isRequestedSessionIdValid () {
return req.isRequestedSessionIdValid();
}
public boolean isRequestedSessionIdFromCookie () {
return req.isRequestedSessionIdFromCookie();
}
public boolean isRequestedSessionIdFromURL () {
return req.isRequestedSessionIdFromURL();
}
public boolean isRequestedSessionIdFromUrl () {
return req.isRequestedSessionIdFromUrl();
}
} // end HttpServletRequestFacade
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/ISessionConstants.java
Index: ISessionConstants.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
public interface ISessionConstants {
/* probably not necessary*/
public static final String SESS_CACHE_NAME = "sessionCache";
public static final int SESS_CACHE_SIZE = 2000;
public static final String SESS_INFO_CACHE_NAME = "sessionInfoCache";
public static final int SESS_INFO_CACHE_SIZE = 2000;
// 30 minutes after first hour
public static final int DFLT_INACTIVE_INTERVAL = 60 * 60 * 1000;
}
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/MetaHttpSession.java
Index: MetaHttpSession.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
import javax.servlet.http.*;
/** Used to contain an http session and/or the associated information. */
class MetaHttpSession {
/** The corresponding cookie id of the http session. */
final String session_id;
/** The http session. */
final HttpSession sess;
/** Constructs with the given session id, and the http session. Both values can
be null. */
MetaHttpSession (String session_id, HttpSession sess) {
this.session_id = session_id;
this.sess = sess;
}
/** Returns true iff both the session id and the http session are not null. */
boolean valid () {
return session_id != null && sess != null;
}
}
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/SessionIdGenerator.java
Index: SessionIdGenerator.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
import java.io.*;
import java.util.*;
import javax.servlet.http.*;
import java.rmi.dgc.VMID;
public class SessionIdGenerator {
private static int[] count = new int[1];
public static final String JVM_ID = new VMID().toString();
/*
public static String createSessionId(SessionInfo svo, String jvmId) {
synchronized(count) {
return jvmId + svo.creationTime + count[0]++;
return jvmId + count[0]++;
}
}
*/
public static String createSessionId() {
synchronized(count) {
return JVM_ID + count[0]++;
}
}
}
1.1
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/SessionInfo.java
Index: SessionInfo.java
===================================================================
package org.apache.stratum.jcs.utils.servlet.session;
import java.io.*;
import java.util.*;
import javax.servlet.http.*;
public class SessionInfo implements Serializable {
final long creationTime;
long lastAccessedTime;
// at first login this might be twice the set amount, depending
// on the update ration
int maxInactiveInterval = 60 * 60 * 1000; // 30 minutes after first hour
SessionInfo() {
lastAccessedTime = creationTime = System.currentTimeMillis();
}
public String toString() {
return "[creationTime=" + creationTime
+ ", lastAccessedTime=" + lastAccessedTime
+", maxInactiveInterval=" + maxInactiveInterval
+"]"
;
}
} // end SessionInfo
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>