Implement session scavenge for FileSessionDataStore

This commit is contained in:
Jan Bartel 2016-03-11 13:12:10 +11:00
parent 8a24798fa4
commit 54a5631462
2 changed files with 117 additions and 12 deletions

View File

@ -24,12 +24,14 @@ import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -98,11 +100,10 @@ public class FileSessionDataStore extends AbstractSessionDataStore
File file = null;
if (_storeDir != null)
{
file = new File(_storeDir, getFileName(id));
if (file.exists() && file.getParentFile().equals(_storeDir))
file = getFile(_storeDir, id);
if (file != null && file.exists() && file.getParentFile().equals(_storeDir))
{
file.delete();
return true;
return file.delete();
}
}
@ -114,12 +115,55 @@ public class FileSessionDataStore extends AbstractSessionDataStore
* @see org.eclipse.jetty.server.session.SessionDataStore#getExpired(Set, int)
*/
@Override
public Set<String> doGetExpired(Set<String> candidates, int expiryTimeoutSec)
public Set<String> doGetExpired(final Set<String> candidates, final int expiryTimeoutSec)
{
//we don't want to open up each file and check, so just leave it up to the SessionStore
//TODO as the session manager is likely to be a lazy loader, if a session is never requested, its
//file will stay forever after a restart
return candidates;
final long now = System.currentTimeMillis();
HashSet<String> expired = new HashSet<String>();
File[] files = _storeDir.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File dir, String name)
{
if (dir != _storeDir)
return false;
String s = name.substring(0, name.indexOf('_'));
long expiry = (s==null?0:Long.parseLong(s));
if (expiry > 0 && expiry < now)
return true;
else
return false;
}
});
if (files != null)
{
for (File f:files)
{
expired.add(getIdFromFile(f));
}
}
//check candidates that were not found to be expired, perhaps they no
//longer exist and they should be expired
for (String c:candidates)
{
if (!expired.contains(c))
{
//check if the file exists
File f = getFile(_storeDir, c);
if (f == null || !f.exists())
expired.add(c);
}
}
return expired;
}
@ -136,9 +180,9 @@ public class FileSessionDataStore extends AbstractSessionDataStore
{
public void run ()
{
File file = new File(_storeDir,getFileName(id));
File file = getFile(_storeDir,id);
if (!file.exists())
if (file == null || !file.exists())
{
if (LOG.isDebugEnabled())
LOG.debug("No file: {}",file);
@ -187,9 +231,13 @@ public class FileSessionDataStore extends AbstractSessionDataStore
File file = null;
if (_storeDir != null)
{
file = new File(_storeDir, getFileName(id));
if (file.exists())
//remove any existing file for the session
file = getFile(_storeDir, id);
if (file != null && file.exists())
file.delete();
//make a fresh file using the latest session expiry
file = new File(_storeDir, getFileNameWithExpiry(data));
try(FileOutputStream fos = new FileOutputStream(file,false))
{
@ -264,7 +312,50 @@ public class FileSessionDataStore extends AbstractSessionDataStore
{
return _context.getCanonicalContextPath()+"_"+_context.getVhost()+"_"+id;
}
private String getFileNameWithExpiry (SessionData data)
{
return ""+data.getExpiry()+"_"+getFileName(data.getId());
}
private String getIdFromFile (File file)
{
if (file == null)
return null;
String name = file.getName();
return name.substring(name.lastIndexOf('_')+1);
}
/**
* Find a File for the session id for the current context.
*
* @param storeDir
* @param id
* @return
*/
private File getFile (final File storeDir, final String id)
{
File[] files = storeDir.listFiles (new FilenameFilter() {
/**
* @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
*/
@Override
public boolean accept(File dir, String name)
{
if (dir != storeDir)
return false;
return (name.contains(getFileName(id)));
}
});
if (files == null || files.length < 1)
return null;
return files[0];
}
/**
* @param is inputstream containing session data

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.server.session;
import java.io.File;
import java.io.FilenameFilter;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
@ -153,9 +154,22 @@ public class FileSessionManagerTest
manager.setMaxInactiveInterval(30); // change max inactive interval for *new* sessions
manager.stop();
String expectedFilename = "_0.0.0.0_"+session.getId();
Assert.assertTrue("File should exist!", new File(testDir, expectedFilename).exists());
final String expectedFilename = "_0.0.0.0_"+session.getId();
File[] files = testDir.listFiles(new FilenameFilter(){
@Override
public boolean accept(File dir, String name)
{
return name.contains(expectedFilename);
}
});
Assert.assertNotNull(files);
Assert.assertEquals(1, files.length);
Assert.assertTrue("File should exist!", files[0].exists());
manager.start();