package edu.colostate.vchill.cache;
import edu.colostate.vchill.ChillDefines;
import edu.colostate.vchill.ControlMessage;
import edu.colostate.vchill.ScaleManager;
import java.util.HashMap;
/**
* Implementation of a cyclic buffer.
* This type of cache should NOT be shared between connections.
*
* @author Jochen Deyke
* @version 2007-09-28
*/
public class CacheMainCyclic extends CacheMain {
protected ScaleManager sm = ScaleManager.getInstance();
/**
* The number of elements to store
*/
protected final int buffSize;
/**
* The actual storage
*/
protected final HashMap<String, Object>[] buffer;
/**
* Insertion point for new elements
*/
protected int[] index;
@SuppressWarnings("unchecked")
public CacheMainCyclic(final int size) {
this.buffSize = size;
this.buffer = new HashMap[size];
for (int i = 0; i < size; ++i) this.buffer[i] = new HashMap<String, Object>();
this.index = new int[ChillDefines.MAX_NUM_TYPES + 1]; //plus metadata
}
/**
* Retrieves data from the cache
*
* @param key ControlMessage containing type information of the desired data
* @param index the 0-based index of the desired data within the sweep/type
* @return the requested data
*/
@Override
public Object getData(final ControlMessage key, final String type, final int index) {
synchronized (this.buffer) {
return this.buffer[index % buffSize].get(type);
}
}
/**
* Retrieves data from the cache. If the data is not yet available, waits
* for the data to become available or the sweep to be marked complete.
*
* @param key ControlMessage containing type information of the desired data
* @param index the 0-based index of the desired data within the sweep/type
* @return the requested data
*/
@Override
public Object getDataWait(final ControlMessage key, final String type, final int index) {
synchronized (this.buffer) {
while (index > this.index[sm.getScale(type).fieldNumber])
try {
this.buffer.wait();
} catch (InterruptedException ie) {
}
return this.buffer[index % buffSize].get(type);
}
}
/**
* Retrieves data from the cache. If the data is not yet available, waits
* for the data to become available or the sweep to be marked complete.
*
* @param key ControlMessage containing type information of the desired data
* @param index the 0-based index of the desired data within the sweep/type
* @param timeout the maximum number of milliseconds to wait
* @return the requested data
*/
@Override
public Object getDataWait(final ControlMessage key, final String type, final int index, final long timeout) {
synchronized (this.buffer) {
if (index > this.index[sm.getScale(type).fieldNumber])
try {
this.buffer.wait(timeout);
} catch (InterruptedException ie) {
}
return this.buffer[index % buffSize].get(type);
}
}
/**
* Appends data to the cache
*
* @param key ControlMessage containing server, port, dir, file, sweep, and type information of the desired data
* @param data the data store
*/
@Override
public void addRay(final ControlMessage key, final String type, final Object data) {
synchronized (this.buffer) {
int fieldNum = type.equals(ChillDefines.META_TYPE) ? ChillDefines.MAX_NUM_TYPES : sm.getScale(type).fieldNumber;
this.buffer[this.index[fieldNum] % buffSize].put(type, data);
++this.index[fieldNum];
this.buffer.notifyAll();
}
}
@Override
public int getNumberOfRays(final ControlMessage key, final String type) {
synchronized (this.buffer) {
return this.index[sm.getScale(type).fieldNumber];
}
}
}