/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-07 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.http;
import org.apache.log4j.Logger;
import org.exist.scheduler.JobException;
import org.exist.scheduler.JobException.JobExceptionAction;
import org.exist.scheduler.UserJavaJob;
import org.exist.storage.BrokerPool;
import org.exist.xquery.value.Sequence;
import java.util.Map;
import java.util.Properties;
public class SessionManager {
public final static long TIMEOUT = 120000;
public final static long TIMEOUT_CHECK_PERIOD = 2000;
public final static int NO_SESSION = -1;
private final static Logger LOG = Logger.getLogger(SessionManager.class);
private class QueryResult {
long lastAccess;
String queryString;
Sequence sequence;
private QueryResult(String query, Sequence sequence) {
this.queryString = query;
this.sequence = sequence;
this.lastAccess = System.currentTimeMillis();
}
protected Sequence sequence() {
lastAccess = System.currentTimeMillis();
return sequence;
}
}
public static class TimeoutCheck extends UserJavaJob {
public TimeoutCheck() {
}
public String getName() {
return "REST_TimeoutCheck";
}
public void setName(String name) {
}
public void execute(final BrokerPool brokerpool, final Map<String, ?> params) throws JobException {
final SessionManager manager = (SessionManager)params.get("session-manager");
if (manager == null) {
throw new JobException(JobExceptionAction.JOB_ABORT, "parameter 'session-manager' is not set");
}
manager.timeoutCheck();
}
}
private QueryResult[] slots = new QueryResult[32];
public SessionManager(BrokerPool pool) {
final Properties props = new Properties();
props.put("session-manager", this);
pool.getScheduler().createPeriodicJob(TIMEOUT_CHECK_PERIOD, new TimeoutCheck(), 2000, props);
}
public int add(String query, Sequence sequence) {
final int len = slots.length;
for (int i = 0; i < len; i++) {
if (slots[i] == null) {
slots[i] = new QueryResult(query, sequence);
return i;
}
}
// no free slots, resize
QueryResult[] t = new QueryResult[(len * 3) / 2];
System.arraycopy(slots, 0, t, 0, len);
t[len] = new QueryResult(query, sequence);
slots = t;
return len;
}
public Sequence get(String query, int sessionId) {
if (sessionId < 0 || sessionId >= slots.length)
{return null;} // out of scope
final QueryResult cached = slots[sessionId];
if (cached == null)
{return null;}
if (cached.queryString.equals(query))
{return cached.sequence();}
// wrong query
return null;
}
public void release(int sessionId) {
if (sessionId < 0 || sessionId >= slots.length)
{return;} // out of scope
slots[sessionId] = null;
}
protected void timeoutCheck() {
final long now = System.currentTimeMillis();
for (int i = 0; i < slots.length; i++) {
if (slots[i] != null && now - slots[i].lastAccess > TIMEOUT) {
LOG.debug("Removing cached query result for session " + i);
slots[i] = null;
}
}
}
}