package com.esri.geoevent.solutions.processor.evc;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.esri.geoevent.solutions.processor.evc.EVCProcessor.TrackRecord;
import com.esri.ges.core.component.ComponentException;
import com.esri.ges.core.geoevent.GeoEvent;
import com.esri.ges.core.property.Property;
import com.esri.ges.processor.GeoEventProcessorBase;
import com.esri.ges.processor.GeoEventProcessorDefinition;
public class EVCProcessor extends GeoEventProcessorBase {
private long eventsPerInterval;
private long intervalInMillis; // 1000 milliseconds is a second.
private static final Log LOG = LogFactory.getLog(EVCProcessor.class);
private Map<String, TrackRecord> trackCache = new ConcurrentHashMap<String, TrackRecord>();
//private Map<Long, String> timeCache = new HashMap<Long, String>();
private TrackRecord defaultTrack = new TrackRecord();
private long lastCleanup = System.currentTimeMillis();
class TrackRecord {
long count;
long lastTime = System.currentTimeMillis();
}
public EVCProcessor(GeoEventProcessorDefinition definition)
throws ComponentException {
super(definition);
}
@Override
public void afterPropertiesSet()
{
intervalInMillis = (Long) properties.get("interval").getValue();
eventsPerInterval = (Long) properties.get("epi").getValue();
}
@Override
public GeoEvent process(GeoEvent dataMessage) throws Exception {
String filter = properties.get("filterType").getValueAsString();
if(filter.equals("maxPerInterval"))
{
return filterMaxPerInterval(dataMessage);
}
else
{
return filterByInterval(dataMessage);
}
}
public GeoEvent filterMaxPerInterval(GeoEvent dataMessage) throws Exception {
try {
TrackRecord track = defaultTrack;
String trackID = dataMessage.getTrackId();
String guid = dataMessage.getGeoEventDefinition().getGuid();
if (trackID != null) {
String uid = guid + "_" + trackID;
if (!trackCache.containsKey(uid))
trackCache.put(uid, new TrackRecord());
track = trackCache.get(uid);
}
long now = System.currentTimeMillis();
if (now - track.lastTime < intervalInMillis) {
track.count++;
if (track.count > eventsPerInterval)
return null;
} else {
track.lastTime = now;
track.count = 1;
}
if (now - lastCleanup > 2 * intervalInMillis)
cleanup();
return dataMessage;
} catch (Exception e) {
LOG.error(e.getMessage());
LOG.error(e.getStackTrace());
throw (e);
}
}
private GeoEvent filterByInterval(GeoEvent dataMessage) throws Exception
{
try {
TrackRecord track = defaultTrack;
String trackID = dataMessage.getTrackId();
String guid = dataMessage.getGeoEventDefinition().getGuid();
if (trackID != null) {
String uid = guid + "_" + trackID;
if (!trackCache.containsKey(uid)) {
trackCache.put(uid, new TrackRecord());
return dataMessage;
}
track = trackCache.get(uid);
}
long now = System.currentTimeMillis();
if (now - track.lastTime >= intervalInMillis) {
track.lastTime = now;
} else {
return null;
}
if (now - lastCleanup > 2 * intervalInMillis)
cleanup();
return dataMessage;
} catch (Exception e) {
LOG.error(e.getMessage());
LOG.error(e.getStackTrace());
throw (e);
}
}
private void cleanup() {
try {
long now = System.currentTimeMillis();
/*for (String track : trackCache.keySet()) {
if (now - trackCache.get(track).lastTime > 4 * intervalInMillis)
trackCache.remove(track);
}*/
Iterator<Entry<String, TrackRecord>> it = trackCache.entrySet().iterator();
while (it.hasNext()){
@SuppressWarnings("rawtypes")
Map.Entry pair = (Map.Entry)it.next();
if (now - (((TrackRecord)pair.getValue()).lastTime) > 4 * intervalInMillis)
it.remove();
}
lastCleanup = System.currentTimeMillis();
} catch (Exception e) {
LOG.error(e.getMessage());
LOG.error(e.getStackTrace());
}
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(definition.getName());
sb.append("/");
sb.append(definition.getVersion());
sb.append("[");
for (Property p : getProperties()) {
sb.append(p.getDefinition().getPropertyName());
sb.append(":");
sb.append(p.getValue());
sb.append(" ");
}
sb.append("]");
return sb.toString();
}
}