package uk.ac.imperial.lsds.streamsql.windows;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import uk.ac.imperial.lsds.seep.comm.serialization.DataTuple;
import uk.ac.imperial.lsds.streamsql.expressions.Constants;
import uk.ac.imperial.lsds.streamsql.operator.WindowOperator;
public class RangeWindow implements Window {
/*
* Size of the window in terms of timestamp units, i.e.,
* what is the time span considered for selecting tuples into the window?
*/
private int size = 1;
/*
* Slide of the window in terms of timestamp units, i.e.,
* what is the time span after which we trigger operator evaluation?
*/
private int slide = 1;
private long currentTime = 0;
private long lastTriggerTime = 0;
private Queue<DataTuple> state;
private Set<WindowOperator> callBacks;
public RangeWindow(int size, int slide) {
assert(size >= slide);
this.size = size;
this.slide = slide;
this.state = new LinkedList<>();
this.callBacks = new HashSet<>();
}
public RangeWindow(int size) {
this(size, size);
}
public RangeWindow() {
this(1);
}
@Override
public void updateWindow(DataTuple tuple) {
/*
* Update the window with a new tuple
*/
this.state.add(tuple);
this.currentTime = tuple.getLong(Constants.TIMESTAMP);
DataTuple head = this.state.peek();
if (head != null) {
long headTime = head.getLong(Constants.TIMESTAMP);
while ((head != null)
&& (this.size >= this.currentTime - headTime)) {
this.state.remove();
head = this.state.peek();
headTime = head.getLong(Constants.TIMESTAMP);
}
}
/*
* Check whether operator evaluation shall be triggered
*/
if (this.currentTime - this.lastTriggerTime >= slide) {
for (WindowOperator op : this.callBacks)
op.evaluateWindow(this.state);
this.lastTriggerTime = this.currentTime;
}
}
@Override
public void updateWindow(List<DataTuple> tuples) {
for (DataTuple tuple : tuples)
updateWindow(tuple);
}
@Override
public void registerCallback(WindowOperator operator) {
this.callBacks.add(operator);
}
}