/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.storage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class DOReaderCache
extends Thread {
private final int m_maxReaders;
private final int m_maxCachedSeconds;
private final Map m_readers;
private final List m_pidList;
private boolean m_stopRequested;
public DOReaderCache(int maxReaders, int maxCachedSeconds) {
m_maxReaders = maxReaders;
m_maxCachedSeconds = maxCachedSeconds;
m_readers = new HashMap();
m_pidList = new ArrayList();
m_stopRequested = false;
start();
}
/**
* Until closed, check for and remove any expired entries every second.
*/
@Override
public void run() {
while (!m_stopRequested) {
removeExpired();
if (!m_stopRequested) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
}
private void removeExpired() {
long cutoffTime =
System.currentTimeMillis() - 1000 * m_maxCachedSeconds;
synchronized (m_readers) {
if (m_pidList.size() > 0) {
boolean done = false;
List expiredList = new ArrayList();
Iterator pids = m_pidList.iterator();
while (pids.hasNext() && !done) {
String pid = (String) pids.next();
List l = (List) m_readers.get(pid);
long cachedTime = ((Long) l.get(1)).longValue();
if (cachedTime < cutoffTime) {
expiredList.add(pid);
} else {
done = true;
}
}
pids = expiredList.iterator();
while (pids.hasNext()) {
remove((String) pids.next());
}
}
}
}
/**
* Remove a DOReader from the cache. If it doesn't exist in the cache, do
* nothing.
*/
public void remove(String pid) {
synchronized (m_readers) {
if (m_readers.remove(pid) != null) {
m_pidList.remove(pid);
}
}
}
/**
* Add a DOReader to the cache. If it already exists in the cache, refresh
* the DOReader in the cache.
*/
public void put(DOReader reader) {
String pid = null;
try {
pid = reader.GetObjectPID();
} catch (Exception e) {
}
Long time = new Long(System.currentTimeMillis());
List l = new ArrayList();
l.add(reader);
l.add(time);
synchronized (m_readers) {
m_readers.put(pid, l);
if (m_pidList.contains(pid)) {
// ensure it only appears in the list once, at the end
m_pidList.remove(pid);
}
m_pidList.add(pid);
if (m_readers.size() > m_maxReaders) {
Object overflowPid = m_pidList.remove(0);
m_readers.remove(overflowPid);
}
}
}
/**
* Get a DOReader from the cache. If it doesn't exist in the cache, return
* null. If it does exist, set its time to the current time and return it.
*/
public DOReader get(String pid) {
DOReader reader = null;
synchronized (m_readers) {
List l = (List) m_readers.get(pid);
if (l != null) {
reader = (DOReader) l.get(0);
l.remove(1);
l.add(new Long(System.currentTimeMillis()));
// move it to the end of the list so the list stays sorted
m_pidList.remove(pid);
m_pidList.add(pid);
}
}
return reader;
}
public void close() {
// make sure the thread finishes
m_stopRequested = true;
}
}