|
What this is
Other links
The source code
/* CVS ID: $Id: ExpireableCache.java,v 1.1.1.1 2002/10/02 18:42:48 wastl Exp $ */
package net.wastl.webmail.misc;
import java.util.*;
/*
* ExpireableCache.java
*
* Created: Fri Sep 17 09:43:10 1999
*
* Copyright (C) 2000 Sebastian Schaffert
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**
* This class represents a cache that automatically expires objects when a certain fillness
* factor is reached.
*
* @author Sebastian Schaffert
* @version
*/
public class ExpireableCache extends Thread {
protected Hashtable cache;
protected MyHeap timestamps;
protected int capacity;
protected float expire_factor;
protected int hits=0;
protected int misses=0;
protected boolean shutdown=false;
public ExpireableCache(int capacity, float expire_factor) {
super("ExpireableCache");
setPriority(MIN_PRIORITY);
cache=new Hashtable(capacity);
timestamps=new MyHeap(capacity);
this.capacity=capacity;
this.expire_factor=expire_factor;
}
public ExpireableCache(int capacity) {
this(capacity,(float).90);
}
/*
* Insert an element into the cache
*/
public synchronized void put(Object key, Object value) {
/* When the absolute capacity is exceeded, we must clean up */
if(cache.size()+1 >= capacity) {
expireOver();
}
long l=System.currentTimeMillis();
cache.put(key,value);
timestamps.remove(key);
timestamps.insert(key,l);
expireOver();
}
public Object get(Object key) {
long l=System.currentTimeMillis();
timestamps.remove(key);
timestamps.insert(key,l);
return cache.get(key);
}
public synchronized void remove(Object key) {
cache.remove(key);
timestamps.remove(key);
notifyAll();
}
protected synchronized void expireOver() {
while(cache.size()>=(capacity*expire_factor)) {
String nk=(String)timestamps.next();
cache.remove(nk);
}
}
public void setCapacity(int size) {
capacity=size;
}
public int getCapacity() {
return capacity;
}
public int getUsage() {
return cache.size();
}
public int getHits() {
return hits;
}
public int getMisses() {
return misses;
}
public void hit() {
hits++;
}
public void miss() {
misses++;
}
public void shutdown() {
shutdown=true;
}
public void run() {
while(!shutdown) {
try {
wait(10000);
} catch(InterruptedException e) {}
expireOver();
}
}
/**
* Implement a simple heap that just returns the smallest long variable/Object key pair.
*/
protected class MyHeap {
int num_entries;
long[] values;
Object[] keys;
MyHeap(int capacity) {
values=new long[capacity+1];
keys=new Object[capacity+1];
num_entries=0;
}
/**
* Insert a key/value pair
* Reorganize Heap afterwards
*/
public void insert(Object key, long value) {
keys[num_entries]=key;
values[num_entries]=value;
num_entries++;
increase(num_entries);
}
/**
* Return and delete the key with the lowest long value. Reorganize Heap.
*/
public Object next() {
Object ret=keys[0];
keys[0]=keys[num_entries-1];
values[0]=values[num_entries-1];
num_entries--;
decrease(1);
return ret;
}
/**
* Remove an Object from the Heap.
* Unfortunately not (yet) of very good complexity since we are doing
* a simple linear search here.
* @param key The key to remove from the heap
*/
public void remove(Object key) {
for(int i=0;i<num_entries;i++) {
if(key.equals(keys[i])) {
num_entries--;
int cur_pos=i+1;
keys[i]=keys[num_entries];
decrease(cur_pos);
break;
}
}
}
/**
* Lift an element in the heap structure
* Note that the cur_pos is actually one larger than the position in the array!
*/
protected void increase(int cur_pos) {
while(cur_pos > 1 && values[cur_pos-1] < values[cur_pos/2-1]) {
Object tmp1=keys[cur_pos/2-1];keys[cur_pos/2-1]=keys[cur_pos-1];keys[cur_pos-1]=tmp1;
long tmp2=values[cur_pos/2-1];values[cur_pos/2-1]=values[cur_pos-1];values[cur_pos-1]=tmp2;
cur_pos /= 2;
}
}
/**
* Lower an element in the heap structure
* Note that the cur_pos is actually one larger than the position in the array!
*/
protected void decrease(int cur_pos) {
while((cur_pos*2 <= num_entries && values[cur_pos-1] > values[cur_pos*2-1]) ||
(cur_pos*2+1 <=num_entries && values[cur_pos-1] > values[cur_pos*2])) {
int lesser_son;
if(cur_pos*2+1 <= num_entries) {
lesser_son=values[cur_pos*2-1]<values[cur_pos*2]?cur_pos*2:cur_pos*2+1;
} else {
lesser_son=cur_pos*2;
}
Object tmp1=keys[cur_pos-1];keys[cur_pos-1]=keys[lesser_son-1];keys[lesser_son-1]=tmp1;
long tmp2=values[cur_pos-1];values[cur_pos-1]=values[lesser_son-1];values[lesser_son-1]=tmp2;
cur_pos=lesser_son;
}
}
}
} // ExpireableCache
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.