+ public static class MemoryStorage extends BaseStorage {
+ private final Map<Long, MemorySession> sessions = new HashMap<Long, MemorySession>();
+ private static long lastclean = 0;
+
+ private class MemorySession extends Session {
+ private final long id = BaseStorage.prng.nextLong();
+
+ private MemorySession(Request req) {
+ super(req);
+ }
+
+ public void destroy() {
+ synchronized(sessions) {
+ sessions.remove(id);
+ }
+ super.destroy();
+ }
+
+ private void expire() {
+ super.destroy();
+ }
+
+ public String id() {
+ return(Long.toString(id));
+ }
+ }
+
+ public int num() {
+ synchronized(sessions) {
+ return(sessions.size());
+ }
+ }
+
+ public Session get(String id) {
+ long idl;
+ try {
+ idl = Long.parseLong(id);
+ } catch(NumberFormatException e) {
+ return(null);
+ }
+ synchronized(sessions) {
+ return(sessions.get(idl));
+ }
+ }
+
+ public synchronized Session create(Request req) {
+ MemorySession sess = new MemorySession(req);
+ synchronized(sessions) {
+ sessions.put(sess.id, sess);
+ }
+ return(sess);
+ }
+
+ private void clean() {
+ long now = System.currentTimeMillis();
+ synchronized(sessions) {
+ for(Iterator<MemorySession> i = sessions.values().iterator(); i.hasNext();) {
+ MemorySession sess = i.next();
+ if(now > sess.atime + sess.etime) {
+ i.remove();
+ sess.expire();
+ }
+ }
+ }
+ }
+
+ public Session get(Request req) {
+ long now = System.currentTimeMillis();
+ if(now - lastclean > 3600 * 1000) {
+ clean();
+ lastclean = now;
+ }
+
+ return(super.get(req));
+ }
+ }
+
+ protected Session(Request req) {
+ int ct;
+ ct = Integer.parseInt(req.ctx().libconfig("jsvc.session.expire", "0"));
+ if(ct > 0)
+ etime = ct;
+ ct = Integer.parseInt(req.ctx().sysconfig("jsvc.session.expire", "0"));
+ if(ct > 0)
+ etime = ct;