sunlabs.brazil.session.CacheManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sunlabs.brazil Show documentation
Show all versions of sunlabs.brazil Show documentation
Extremely small footprint Java HTTP stack.
The newest version!
/*
* CacheManager.java
*
* Brazil project web application toolkit,
* export version: 2.3
* Copyright (c) 2000-2004 Sun Microsystems, Inc.
*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is included as the file "license.terms",
* and also available at http://www.sun.com/
*
* The Original Code is from:
* Brazil project web application toolkit release 2.3.
* The Initial Developer of the Original Code is: suhler.
* Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
* All Rights Reserved.
*
* Contributor(s): suhler.
*
* Version: 2.2
* Created by suhler on 00/08/25
* Last modified by suhler on 04/04/05 14:44:45
*
* Version Histories:
*
* 2.2 04/04/05-14:44:45 (suhler)
*
* 2.1 02/10/01-16:39:08 (suhler)
* version change
*
* 1.8 02/06/05-16:15:40 (suhler)
* un privatize makeKey
*
* 1.7 01/05/01-11:02:39 (suhler)
* update for new sessionmanager api's
*
* 1.6 00/12/11-13:32:27 (suhler)
* add class=props for automatic property extraction
*
* 1.5 00/11/16-10:35:47 (suhler)
* change key representation for string keys, make internal methods
* accessable by subclasses
*
* 1.4 00/10/31-10:20:27 (suhler)
* doc fixes
*
* 1.3 00/10/06-10:44:39 (suhler)
* remove debug prints
*
* 1.2 00/08/25-14:38:10 (suhler)
* added docs
*
* 1.2 00/08/25-11:47:46 (Codemgr)
* SunPro Code Manager data about conflicts, renames, etc...
* Name history : 1 0 session/CacheManager.java
*
* 1.1 00/08/25-11:47:45 (suhler)
* date and time created 00/08/25 11:47:45 by suhler
*
*/
package sunlabs.brazil.session;
import sunlabs.brazil.server.Handler;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import java.util.Hashtable;
/**
* This SessionManager
associates an object with a Session ID
* to give Handlers the ability to maintain state that lasts for the
* duration of a session instead of just for the duration of a request.
* It should be installed as a handler, whoses init method will replace
* the default session manager.
*
* This version maintains a pool of hashtables. Once they all
* fill up - one of them gets tossed, causing any session info in it
* to be lost. It uses a simplified approximate LRU scheme.
* The default session manager doesn't loose any session information,
* but grows the heap without bound as the number of sessions increase.
*
* properties:
*
* - tables
- The number of Hashtables in the pool (defaults to 6)
*
- size
- The max number of entries in each table (defaults to 1000).
*
*
* @author Stephen Uhler ([email protected])
* @version %V% CacheManager.java
*/
public class CacheManager extends SessionManager implements Handler {
ScoredHashtable[] pool; // pool of hashtables
int active; // active hashtable for insertions
int maxElements; // max elements allowed per table
int maxTables; // number of tables in the pool
String prefix; // Pattern matching url to do statistics
/**
* Install this class as the session manager.
* Get the number of tables, and the max size per table.
*/
public boolean
init(Server server, String prefix) {
sessions=null; // don't use table in parent class;
this.prefix = prefix;
try {
String str = server.props.getProperty(prefix + "tables");
maxTables = Integer.decode(str).intValue();
} catch (Exception e) {
maxTables = 6;
}
try {
String str = server.props.getProperty(prefix + "size");
maxElements = Integer.decode(str).intValue();
} catch (Exception e) {
maxElements = 1000;
}
if (maxTables < 2) {
maxTables = 2;
}
if (maxElements < 1) {
maxElements = 1;
}
server.log(Server.LOG_DIAGNOSTIC, prefix, "\n pool=" + maxTables +
"\n size=" + maxElements);
active=0;
pool = new ScoredHashtable[maxTables];
pool[active] = new ScoredHashtable();
SessionManager.setSessionManager(this);
return true;
}
/**
* Don't handle any URL requests (yet)
*/
public boolean
respond(Request request) {
return false;
}
protected Object
getObj(Object session, Object ident) {
String key = makeKey(session, ident);
Object result = pool[active].get(key);
for (int i=0; result == null && i < maxTables; i++) {
if (pool[i] != null && i != active) {
result = pool[i].get(key);
}
}
return result;
}
protected void
putObj(String key, Object value) {
if ((pool[active].size()) >= maxElements) {
flush(); // this changes "active" as a side effect
}
pool[active].put(key, value);
/* System.out.println(" Inserting into " + active +
" " + pool[active].size() + "/" + maxElements);
*/
}
protected void
putObj(Object session, Object ident, Object value) {
putObj(makeKey(session, ident), value);
}
/**
* Remove an object from a session table.
* Don't bother to remove the table if its empty
*/
public void
removeObj(Object session, Object ident) {
String key = makeKey(session, ident);
for (int i=0; i < maxTables; i++) {
if (pool[i] != null && pool[i].containsKey(key)) {
pool[i].remove(key);
return;
}
}
return;
}
/**
* The active hashtable is too big, find the hashtable
* with the worst Score, clear it, and set it as the active table.
*/
protected void flush() {
int worst = -1; // score of worst table
// System.out.println("Table " + active + " is full");
for (int i = 0; i < maxTables; i++) {
if (i == active) {
continue; // never flush "newest" table
}
if (pool[i] == null) {
active = i;
pool[i] = new ScoredHashtable();
System.out.println(" Created new table: " + active +
"/" + maxTables);
return;
}
int check = pool[i].score();
if (worst == -1 || check < worst) {
worst = check;
active = i;
}
}
pool[active].clear();
// System.out.println(" clearing " + active + " score: " + worst);
}
/**
* Invent a single key from the 2 separate ones
*/
protected String
makeKey(Object session, Object ident) {
if (ident == null) {
ident = "null";
}
if (session == null) {
session = this.getClass();
}
if (session instanceof String && ident instanceof String) {
return session + "-" + ident;
} else {
return "" + session.hashCode() + "-" + ident.hashCode();
}
}
/**
* Hashtable that counts successful get requests.
* We use this to keep "score".
*/
static class ScoredHashtable extends Hashtable {
int hits = 0;
public ScoredHashtable() {
super();
}
public Object get(Object key) {
Object result = super.get(key);
if (result != null) {
hits++;
}
return result;
}
/**
* return the "score" of a hashtable. Higher numbers represent
* "better" tables to keep.
*/
public int score() {
return hits;
}
public void clear() {
hits=0;
super.clear();
}
}
}