package com.alipay.bluewhale.core.stats.RollingWindow;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.alipay.bluewhale.core.callback.RunnableCallback;
import com.alipay.bluewhale.core.utils.TimeUtils;
public class RollingWindowStat {
public static Integer curr_time_bucket(Integer time_secs,
Integer bucket_size_secs) {
return (Integer) (bucket_size_secs * (time_secs / bucket_size_secs));
}
public static RollingWindow rolling_window(RunnableCallback updater,
RunnableCallback merger, RunnableCallback extractor,
Integer bucket_size_secs, Integer num_buckets) {
RollingWindow rtn = new RollingWindow();
rtn.updater = updater;
rtn.merger = merger;
rtn.extractor = extractor;
rtn.bucket_size_secs = bucket_size_secs;
rtn.buckets = new HashMap<Integer, Object>();
rtn.num_buckets = num_buckets;
return rtn;
}
public static RollingWindow update_rolling_window(RollingWindow rw,
Integer time_secs, Object[] args) {
synchronized (rw) {
Integer time_bucket = curr_time_bucket(time_secs,
rw.bucket_size_secs);
Map<Integer, Object> buckets = rw.buckets;
Object curr = buckets.get(time_bucket);
UpdateParams p = new UpdateParams();
p.args = args;
p.curr = curr;
curr = rw.updater.execute(p);
buckets.put(time_bucket, curr);
return rw;
}
}
public static Object value_rolling_window(RollingWindow rw) {
synchronized (rw) {
List<Object> values = new ArrayList<Object>();
for (Entry<Integer, Object> entry : rw.buckets.entrySet()) {
values.add(entry.getValue());
}
Object result = rw.merger.execute(values);
return rw.extractor.execute(result);
}
}
public static RollingWindow cleanup_rolling_window(int cutoff,
RollingWindow rw) {
synchronized (rw) {
Map<Integer, Object> buckets = rw.buckets;
List<Integer> toremove = new ArrayList<Integer>();
for (Entry<Integer, Object> entry : rw.buckets.entrySet()) {
Integer key = entry.getKey();
if (key < cutoff) {
toremove.add(key);
}
}
for (Integer i : toremove) {
buckets.remove(i);
}
rw.buckets = buckets;
return rw;
}
}
public static RollingWindow cleanup_rolling_window(RollingWindow rw) {
int cutoff = TimeUtils.current_time_secs() - rolling_window_size(rw);
return cleanup_rolling_window(cutoff, rw);
}
public static int rolling_window_size(RollingWindow rw) {
return rw.bucket_size_secs * rw.num_buckets;
}
}