More implementation.
This commit is contained in:
parent
fa8232d3c8
commit
e2ecf7ca14
|
@ -46,6 +46,4 @@ public abstract class AbstractSessionDataStore extends AbstractLifeCycle impleme
|
|||
data.setDirty(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
|||
public abstract class AbstractSessionStore extends AbstractLifeCycle implements SessionStore
|
||||
{
|
||||
protected SessionDataStore _sessionDataStore;
|
||||
protected StalenessStrategy _staleStrategy;
|
||||
|
||||
|
||||
|
||||
|
@ -78,6 +79,16 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
|||
_sessionDataStore = sessionDataStore;
|
||||
}
|
||||
|
||||
public StalenessStrategy getStaleStrategy()
|
||||
{
|
||||
return _staleStrategy;
|
||||
}
|
||||
|
||||
public void setStaleStrategy(StalenessStrategy staleStrategy)
|
||||
{
|
||||
_staleStrategy = staleStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a session object.
|
||||
*
|
||||
|
@ -161,7 +172,6 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
|||
public boolean delete(SessionKey key) throws Exception
|
||||
{
|
||||
boolean deleted = true;
|
||||
//TODO synchronization???
|
||||
if (_sessionDataStore != null)
|
||||
deleted = _sessionDataStore.delete(key);
|
||||
doDelete(key);
|
||||
|
@ -170,7 +180,21 @@ public abstract class AbstractSessionStore extends AbstractLifeCycle implements
|
|||
|
||||
public boolean isStale (Session session)
|
||||
{
|
||||
//TODO implement (pluggable?) algorithm for deciding if memory is stale
|
||||
if (_staleStrategy != null)
|
||||
return _staleStrategy.isStale(session);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.x.SessionStore#scavenge()
|
||||
*/
|
||||
@Override
|
||||
public void scavenge()
|
||||
{
|
||||
if (!isStarted())
|
||||
return;
|
||||
_sessionDataStore.scavenge();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session.x;
|
||||
|
||||
/**
|
||||
* AlwaysStale
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class AlwaysStaleStrategy implements StalenessStrategy
|
||||
{
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.x.StalenessStrategy#isStale(org.eclipse.jetty.server.session.x.Session)
|
||||
*/
|
||||
@Override
|
||||
public boolean isStale(Session session)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -29,7 +29,9 @@ import java.io.InputStream;
|
|||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -182,13 +184,15 @@ public class FileSessionDataStore extends AbstractSessionDataStore
|
|||
if (size>0)
|
||||
{
|
||||
// input stream should not be closed here
|
||||
Map<String,Object> attributes = new HashMap<String,Object>();
|
||||
ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is);
|
||||
for (int i=0; i<size;i++)
|
||||
{
|
||||
String key = ois.readUTF();
|
||||
Object value = ois.readObject();
|
||||
data.setAttribute(key,value);
|
||||
attributes.put(key,value);
|
||||
}
|
||||
data.putAllAttributes(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,11 +32,12 @@ import java.sql.PreparedStatement;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
@ -57,6 +58,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
|
||||
protected int _deleteBlockSize = 10; //number of ids to include in where 'in' clause for finding long expired sessions
|
||||
protected boolean _initialized = false;
|
||||
protected long _lastScavengeTime = 0;
|
||||
|
||||
|
||||
|
||||
|
@ -321,19 +323,6 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
protected String _maxIntervalColumn = "maxInterval";
|
||||
protected String _mapColumn = "map";
|
||||
|
||||
private String _insertSession;
|
||||
|
||||
private String _deleteSession;
|
||||
|
||||
private String _updateSession;
|
||||
|
||||
private String _updateSessionNode;
|
||||
|
||||
private String _updateSessionAccessTime;
|
||||
|
||||
private String _selectBoundedExpiredSessions;
|
||||
|
||||
private String _selectExpiredSessions;
|
||||
|
||||
|
||||
protected void setDatabaseAdaptor(DatabaseAdaptor dbadaptor)
|
||||
|
@ -522,34 +511,34 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
public String getInsertSessionStatementAsString()
|
||||
{
|
||||
return "insert into "+getTableName()+
|
||||
" ("+getRowIdColumn()+", "+getIdColumn()+", "+getContextPathColumn()+", "+getVirtualHostColumn()+", "+getLastNodeColumn()+
|
||||
" ("+getIdColumn()+", "+getContextPathColumn()+", "+getVirtualHostColumn()+", "+getLastNodeColumn()+
|
||||
", "+getAccessTimeColumn()+", "+getLastAccessTimeColumn()+", "+getCreateTimeColumn()+", "+getCookieTimeColumn()+
|
||||
", "+getLastSavedTimeColumn()+", "+getExpiryTimeColumn()+", "+getMaxIntervalColumn()+", "+getMapColumn()+") "+
|
||||
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
" values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
}
|
||||
public String getDeleteSessionStatementAsString()
|
||||
|
||||
public String getUpdateSessionStatementAsString(SessionKey key)
|
||||
{
|
||||
return "delete from "+getTableName()+
|
||||
" where "+getRowIdColumn()+" = ?";
|
||||
}
|
||||
public String getUpdateSessionStatementAsString()
|
||||
{
|
||||
return "update "+getTableName()+
|
||||
String s = "update "+getTableName()+
|
||||
" set "+getIdColumn()+" = ?, "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+
|
||||
getLastAccessTimeColumn()+" = ?, "+getLastSavedTimeColumn()+" = ?, "+getExpiryTimeColumn()+" = ?, "+
|
||||
getMaxIntervalColumn()+" = ?, "+getMapColumn()+" = ? where "+getRowIdColumn()+" = ?";
|
||||
}
|
||||
public String getUpdateSessionNodeStatementAsString()
|
||||
{
|
||||
return "update "+getTableName()+
|
||||
" set "+getLastNodeColumn()+" = ? where "+getRowIdColumn()+" = ?";
|
||||
}
|
||||
public String getUpdateSessionAccessTimeStatementAsString()
|
||||
{
|
||||
return "update "+getTableName()+
|
||||
" set "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+getLastAccessTimeColumn()+" = ?, "+
|
||||
getLastSavedTimeColumn()+" = ?, "+getExpiryTimeColumn()+" = ?, "+getMaxIntervalColumn()+" = ? where "+getRowIdColumn()+" = ?";
|
||||
getMaxIntervalColumn()+" = ?, "+getMapColumn()+" = ? where ";
|
||||
|
||||
if (key.getCanonicalContextPath() == null || "".equals(key.getCanonicalContextPath()))
|
||||
{
|
||||
if (_dbAdaptor.isEmptyStringNull())
|
||||
{
|
||||
return s+getIdColumn()+" = ? and "+
|
||||
getContextPathColumn()+" is null and "+
|
||||
getVirtualHostColumn()+" = ?";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return s+getIdColumn()+" = ? and "+getContextPathColumn()+
|
||||
" = ? and "+getVirtualHostColumn()+" = ?";
|
||||
}
|
||||
|
||||
|
||||
public String getBoundedExpiredSessionsStatementAsString()
|
||||
{
|
||||
|
@ -593,6 +582,42 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
return statement;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public PreparedStatement getUpdateStatement (Connection connection, SessionKey key)
|
||||
throws SQLException
|
||||
{
|
||||
if (_dbAdaptor == null)
|
||||
throw new IllegalStateException("No DB adaptor");
|
||||
|
||||
String s = "update "+getTableName()+
|
||||
" set "+getIdColumn()+" = ?, "+getLastNodeColumn()+" = ?, "+getAccessTimeColumn()+" = ?, "+
|
||||
getLastAccessTimeColumn()+" = ?, "+getLastSavedTimeColumn()+" = ?, "+getExpiryTimeColumn()+" = ?, "+
|
||||
getMaxIntervalColumn()+" = ?, "+getMapColumn()+" = ? where ";
|
||||
|
||||
if (key.getCanonicalContextPath() == null || "".equals(key.getCanonicalContextPath()))
|
||||
{
|
||||
if (_dbAdaptor.isEmptyStringNull())
|
||||
{
|
||||
PreparedStatement statement = connection.prepareStatement(s+getIdColumn()+" = ? and "+
|
||||
getContextPathColumn()+" is null and "+
|
||||
getVirtualHostColumn()+" = ?");
|
||||
statement.setString(1, key.getId());
|
||||
statement.setString(2, key.getVhost());
|
||||
return statement;
|
||||
}
|
||||
}
|
||||
PreparedStatement statement = connection.prepareStatement(s+getIdColumn()+" = ? and "+getContextPathColumn()+
|
||||
" = ? and "+getVirtualHostColumn()+" = ?");
|
||||
statement.setString(1, key.getId());
|
||||
statement.setString(2, key.getCanonicalContextPath());
|
||||
statement.setString(3, key.getVhost());
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public PreparedStatement getDeleteStatement (Connection connection, SessionKey key)
|
||||
throws Exception
|
||||
|
@ -717,91 +742,13 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
statement.executeUpdate(getCreateIndexOverExpiryStatementAsString(index1));
|
||||
if (!index2Exists)
|
||||
statement.executeUpdate(getCreateIndexOverSessionStatementAsString(index2));
|
||||
|
||||
//set up some strings representing the statements for session manipulation
|
||||
_insertSession = getInsertSessionStatementAsString();
|
||||
_deleteSession = getDeleteSessionStatementAsString();
|
||||
_updateSession = getUpdateSessionStatementAsString();
|
||||
_updateSessionNode = getUpdateSessionNodeStatementAsString();
|
||||
_updateSessionAccessTime = getUpdateSessionAccessTimeStatementAsString();
|
||||
_selectBoundedExpiredSessions = getBoundedExpiredSessionsStatementAsString();
|
||||
_selectExpiredSessions = getSelectExpiredSessionsStatementAsString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* JDBCSessionData
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JDBCSessionData extends SessionData
|
||||
{
|
||||
protected String _rowId;
|
||||
protected long _lastSaved; //time in msec since last save
|
||||
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @param created
|
||||
* @param accessed
|
||||
* @param lastAccessed
|
||||
* @param maxInactiveMs
|
||||
*/
|
||||
public JDBCSessionData(String id, long created, long accessed, long lastAccessed, long maxInactiveMs)
|
||||
{
|
||||
super(id, created, accessed, lastAccessed, maxInactiveMs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getRowId()
|
||||
{
|
||||
return _rowId;
|
||||
}
|
||||
|
||||
public void setRowId(String rowId)
|
||||
{
|
||||
_rowId = rowId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public long getLastSaved()
|
||||
{
|
||||
return _lastSaved;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setLastSaved(long lastSaved)
|
||||
{
|
||||
_lastSaved = lastSaved;
|
||||
}
|
||||
|
||||
|
||||
public void setAttributes (Map<String, Object> attributes)
|
||||
{
|
||||
_attributes.putAll(attributes);
|
||||
}
|
||||
|
||||
//TODO immutable??
|
||||
public Map<String,Object> getAttributes ()
|
||||
{
|
||||
return _attributes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
public JDBCSessionDataStore ()
|
||||
{
|
||||
super ();
|
||||
|
@ -826,7 +773,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
@Override
|
||||
public SessionData newSessionData(String id, long created, long accessed, long lastAccessed, long maxInactiveMs)
|
||||
{
|
||||
return new JDBCSessionData(id, created, accessed, lastAccessed, maxInactiveMs);
|
||||
return new SessionData(id, created, accessed, lastAccessed, maxInactiveMs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -881,15 +828,14 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
PreparedStatement statement = _sessionTableSchema.getLoadStatement(connection, key);
|
||||
ResultSet result = statement.executeQuery())
|
||||
{
|
||||
JDBCSessionData data = null;
|
||||
SessionData data = null;
|
||||
if (result.next())
|
||||
{
|
||||
data = (JDBCSessionData)newSessionData(key.getId(),
|
||||
result.getLong(_sessionTableSchema.getCreateTimeColumn()),
|
||||
result.getLong(_sessionTableSchema.getAccessTimeColumn()),
|
||||
result.getLong(_sessionTableSchema.getLastAccessTimeColumn()),
|
||||
result.getLong(_sessionTableSchema.getMaxIntervalColumn()));
|
||||
data.setRowId(result.getString(_sessionTableSchema.getRowIdColumn()));
|
||||
data = newSessionData(key.getId(),
|
||||
result.getLong(_sessionTableSchema.getCreateTimeColumn()),
|
||||
result.getLong(_sessionTableSchema.getAccessTimeColumn()),
|
||||
result.getLong(_sessionTableSchema.getLastAccessTimeColumn()),
|
||||
result.getLong(_sessionTableSchema.getMaxIntervalColumn()));
|
||||
data.setCookieSet(result.getLong(_sessionTableSchema.getCookieTimeColumn()));
|
||||
data.setLastNode(result.getString(_sessionTableSchema.getLastNodeColumn()));
|
||||
data.setLastSaved(result.getLong(_sessionTableSchema.getLastSavedTimeColumn()));
|
||||
|
@ -901,7 +847,7 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is))
|
||||
{
|
||||
Object o = ois.readObject();
|
||||
data.setAttributes((Map<String,Object>)o);
|
||||
data.putAllAttributes((Map<String,Object>)o);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -946,41 +892,109 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
@Override
|
||||
public void doStore(SessionKey key, SessionData data) throws Exception
|
||||
{
|
||||
// TODO write session data to jdbc
|
||||
if (data==null || key==null)
|
||||
return;
|
||||
|
||||
try (Connection connection = _dbAdaptor.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(_sessionTableSchema.getUpdateSessionStatementAsString()))
|
||||
try (Connection connection = _dbAdaptor.getConnection())
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
connection.setAutoCommit(true);
|
||||
statement.setString(1, key.getId());
|
||||
statement.setString(2, data.getLastNode());//should be my node id
|
||||
statement.setLong(3, data.getAccessed());//accessTime
|
||||
statement.setLong(4, data.getLastAccessed()); //lastAccessTime
|
||||
statement.setLong(5, now); //last saved time
|
||||
statement.setLong(6, data.getExpiry());
|
||||
statement.setLong(7, data.getMaxInactiveMs());
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(((JDBCSessionData)data).getAttributes());
|
||||
oos.flush();
|
||||
byte[] bytes = baos.toByteArray();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||
|
||||
statement.setBinaryStream(8, bais, bytes.length);//attribute map as blob
|
||||
statement.setString(9, ((JDBCSessionData)data).getRowId()); //rowId
|
||||
statement.executeUpdate();
|
||||
|
||||
((JDBCSessionData)data).setLastSaved(now);
|
||||
|
||||
//If last saved field not set, then this is a fresh session that has never been persisted
|
||||
if (data.getLastSaved() <= 0)
|
||||
{
|
||||
doInsert(connection, key, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
doUpdate(connection, key, data);
|
||||
}
|
||||
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Updated session "+data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void doInsert (Connection connection, SessionKey key, SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
String s = _sessionTableSchema.getInsertSessionStatementAsString();
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(s))
|
||||
{
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
|
||||
statement.setString(1, key.getId()); //session id
|
||||
statement.setString(2, key.getCanonicalContextPath()); //context path
|
||||
statement.setString(3, key.getVhost()); //first vhost
|
||||
statement.setString(4, data.getLastNode());//my node id
|
||||
statement.setLong(5, data.getAccessed());//accessTime
|
||||
statement.setLong(6, data.getLastAccessed()); //lastAccessTime
|
||||
statement.setLong(7, data.getCreated()); //time created
|
||||
statement.setLong(8, data.getCookieSet());//time cookie was set
|
||||
statement.setLong(9, now); //last saved time
|
||||
statement.setLong(10, data.getExpiry());
|
||||
statement.setLong(11, data.getMaxInactiveMs());
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(data.getAllAttributes());
|
||||
oos.flush();
|
||||
byte[] bytes = baos.toByteArray();
|
||||
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||
statement.setBinaryStream(12, bais, bytes.length);//attribute map as blob
|
||||
statement.executeUpdate();
|
||||
data.setLastSaved(now);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Inserted session "+data);
|
||||
}
|
||||
}
|
||||
|
||||
private void doUpdate (Connection connection, SessionKey key, SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
try (PreparedStatement statement = connection.prepareStatement(_sessionTableSchema.getUpdateSessionStatementAsString(key)))
|
||||
{
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
|
||||
statement.setString(1, data.getLastNode());//should be my node id
|
||||
statement.setLong(2, data.getAccessed());//accessTime
|
||||
statement.setLong(3, data.getLastAccessed()); //lastAccessTime
|
||||
statement.setLong(4, now); //last saved time
|
||||
statement.setLong(5, data.getExpiry());
|
||||
statement.setLong(6, data.getMaxInactiveMs());
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(data.getAllAttributes());
|
||||
oos.flush();
|
||||
byte[] bytes = baos.toByteArray();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||
statement.setBinaryStream(7, bais, bytes.length);//attribute map as blob
|
||||
|
||||
if ((key.getCanonicalContextPath() == null || "".equals(key.getCanonicalContextPath())) && _dbAdaptor.isEmptyStringNull())
|
||||
{
|
||||
statement.setString(8, key.getId());
|
||||
statement.setString(9, key.getVhost());
|
||||
}
|
||||
else
|
||||
{
|
||||
statement.setString(8, key.getId());
|
||||
statement.setString(9, key.getCanonicalContextPath());
|
||||
statement.setString(10, key.getVhost());
|
||||
}
|
||||
|
||||
statement.executeUpdate();
|
||||
|
||||
data.setLastSaved(now);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Updated session "+data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -989,8 +1003,25 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore
|
|||
@Override
|
||||
public void scavenge()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Scavenge sweep started at "+System.currentTimeMillis());
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
//first time we're called, don't scavenge
|
||||
if (_lastScavengeTime == 0)
|
||||
{
|
||||
_lastScavengeTime = now;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*TODO
|
||||
* 1. Select sessions for our node and our context that have expired since our last pass, giving some leeway
|
||||
* 2. Select sessions for our node that have expired some time ago
|
||||
* 3. Select sessions for any node that have expired quite a while ago
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ public class MemorySessionStore extends AbstractSessionStore
|
|||
|
||||
if (isStale(session))
|
||||
{
|
||||
//delete from memory
|
||||
//delete from memory so should reload
|
||||
doDelete(key);
|
||||
return null;
|
||||
}
|
||||
|
@ -193,16 +193,4 @@ public class MemorySessionStore extends AbstractSessionStore
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.x.SessionStore#scavenge()
|
||||
*/
|
||||
@Override
|
||||
public void scavenge()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session.x;
|
||||
|
||||
/**
|
||||
* NeverStale
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class NeverStaleStrategy implements StalenessStrategy
|
||||
{
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.x.StalenessStrategy#isStale(org.eclipse.jetty.server.session.x.Session)
|
||||
*/
|
||||
@Override
|
||||
public boolean isStale(Session session)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.server.session.x;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -33,6 +34,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
*/
|
||||
public class SessionData implements Serializable
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String _id;
|
||||
|
||||
protected String _contextPath;
|
||||
|
@ -50,7 +54,7 @@ public class SessionData implements Serializable
|
|||
protected long _maxInactiveMs;
|
||||
protected Map<String,Object> _attributes = new ConcurrentHashMap<String, Object>();
|
||||
protected boolean _dirty;
|
||||
|
||||
protected long _lastSaved; //time in msec since last save
|
||||
|
||||
|
||||
public SessionData (String id, long created, long accessed, long lastAccessed, long maxInactiveMs)
|
||||
|
@ -61,6 +65,20 @@ public class SessionData implements Serializable
|
|||
_lastAccessed = lastAccessed;
|
||||
_maxInactiveMs = maxInactiveMs;
|
||||
}
|
||||
|
||||
|
||||
public long getLastSaved()
|
||||
{
|
||||
return _lastSaved;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setLastSaved(long lastSaved)
|
||||
{
|
||||
_lastSaved = lastSaved;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDirty()
|
||||
{
|
||||
|
@ -93,6 +111,16 @@ public class SessionData implements Serializable
|
|||
}
|
||||
|
||||
|
||||
public void putAllAttributes (Map<String,Object> attributes)
|
||||
{
|
||||
_attributes.putAll(attributes);
|
||||
}
|
||||
|
||||
public Map<String,Object> getAllAttributes()
|
||||
{
|
||||
return Collections.unmodifiableMap(_attributes);
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return _id;
|
||||
|
|
|
@ -764,11 +764,14 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
|||
Session session = _sessionStore.get(key);
|
||||
if (session != null)
|
||||
{
|
||||
//TODO consider not allowing load of expired sessions inside stores
|
||||
//if the session we loaded has expired
|
||||
//If the session we got back has expired
|
||||
if (session.isExpiredAt(System.currentTimeMillis()))
|
||||
{
|
||||
//Remove the expired session from cache and backing persistent store
|
||||
//Tell the id manager that this session id should not be used in case other threads
|
||||
//try to use the same session id in other contexts
|
||||
_sessionIdManager.removeId(id);
|
||||
|
||||
//Remove the expired session from cache and any backing persistent store
|
||||
try
|
||||
{
|
||||
_sessionStore.delete(key);
|
||||
|
@ -778,10 +781,6 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
|||
LOG.warn("Unable to delete expired session {}", key);
|
||||
}
|
||||
|
||||
//Tell the id manager that this session id should not be used in case other threads
|
||||
//try to use the same session id in other contexts
|
||||
_sessionIdManager.removeId(id);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -799,9 +798,9 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
|||
_sessionIdManager.removeId(id);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e1)
|
||||
catch (Exception other)
|
||||
{
|
||||
LOG.warn(e1);
|
||||
LOG.warn(other);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -992,26 +991,50 @@ public class SessionManager extends ContainerLifeCycle implements org.eclipse.je
|
|||
{
|
||||
_checkingRemoteSessionIdEncoding=remote;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Tell the HttpSessionIdListeners the id changed.
|
||||
* NOTE: this method must be called LAST in subclass overrides, after the session has been updated
|
||||
* with the new id.
|
||||
* @see org.eclipse.jetty.server.SessionManager#renewSessionId(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
|
||||
* Change the session id and tell the HttpSessionIdListeners the id changed.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId)
|
||||
public void renewSessionId(String oldId, String oldExtendedId, String newId, String newExtendedId)
|
||||
{
|
||||
if (!_sessionIdListeners.isEmpty())
|
||||
try
|
||||
{
|
||||
Session session = getSession(newClusterId);
|
||||
HttpSessionEvent event = new HttpSessionEvent(session);
|
||||
for (HttpSessionIdListener l:_sessionIdListeners)
|
||||
SessionKey oldKey = SessionKey.getKey(oldId, _context);
|
||||
SessionKey newKey = SessionKey.getKey(newId, _context);
|
||||
|
||||
Session session = _sessionStore.get(oldKey);
|
||||
if (session == null)
|
||||
{
|
||||
l.sessionIdChanged(event, oldClusterId);
|
||||
LOG.warn("Unable to renew id to "+newId+" for non-existant session "+oldId);
|
||||
return;
|
||||
}
|
||||
|
||||
//save session with new id
|
||||
session.getSessionData().setId(newId);
|
||||
session.setExtendedId(newExtendedId);
|
||||
session.getSessionData().setLastSaved(0); //forces an insert
|
||||
_sessionStore.put(newKey, session);
|
||||
|
||||
//remove session with old id
|
||||
_sessionStore.delete(oldKey);
|
||||
|
||||
//inform the listeners
|
||||
if (!_sessionIdListeners.isEmpty())
|
||||
{
|
||||
HttpSessionEvent event = new HttpSessionEvent(session);
|
||||
for (HttpSessionIdListener l:_sessionIdListeners)
|
||||
{
|
||||
l.sessionIdChanged(event, oldId);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session.x;
|
||||
|
||||
/**
|
||||
* StalePeriodStrategy
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class StalePeriodStrategy implements StalenessStrategy
|
||||
{
|
||||
protected long _staleMs = 0;
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.session.x.StalenessStrategy#isStale(org.eclipse.jetty.server.session.x.Session)
|
||||
*/
|
||||
@Override
|
||||
public boolean isStale (Session session)
|
||||
{
|
||||
if (session == null)
|
||||
return false;
|
||||
|
||||
//never persisted, must be fresh session
|
||||
if (session.getSessionData().getLastSaved() == 0)
|
||||
return false;
|
||||
|
||||
if (_staleMs <= 0)
|
||||
{
|
||||
//TODO always stale, never stale??
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (session.getSessionData().getAccessed() - session.getSessionData().getLastSaved() >= _staleMs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public long getStaleSec ()
|
||||
{
|
||||
return (_staleMs<=0?0L:_staleMs/1000L);
|
||||
}
|
||||
|
||||
public void setStaleSec (long sec)
|
||||
{
|
||||
if (sec == 0)
|
||||
_staleMs = 0L;
|
||||
else
|
||||
_staleMs = sec * 1000L;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server.session.x;
|
||||
|
||||
/**
|
||||
* StalenessStrategy
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface StalenessStrategy
|
||||
{
|
||||
boolean isStale (Session session);
|
||||
}
|
Loading…
Reference in New Issue