package com.aol.micro.server.events;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Deque;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicInteger;
import com.aol.micro.server.rest.jackson.JacksonUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
public class ActiveEvents<T extends BaseEventInfo> {
private final Map<String, T> active = new ConcurrentHashMap<>();
private final Deque<Map> recentlyFinished = new ConcurrentLinkedDeque<>();
private final AtomicInteger events = new AtomicInteger(0);
private final AtomicInteger added = new AtomicInteger(0);
private final AtomicInteger removed = new AtomicInteger(0);
public void active(String key, T data) {
active.put(key, data);
events.incrementAndGet();
added.incrementAndGet();
}
public void finished(String key) {
finished(key, ImmutableMap.of());
}
public void finished(String key, ImmutableMap data) {
recentlyFinished.push(wrapInMap(active.get(key), data));
active.remove(key);
removed.incrementAndGet();
if (recentlyFinished.size() > 10)
synchronized (this) {
if (recentlyFinished.size() > 10)
recentlyFinished.pollFirst();
}
}
private Map wrapInMap(T event, ImmutableMap data) {
Long time = System.currentTimeMillis();
DateFormat format = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss z");
String formatted = format.format(time);
String change = Optional.ofNullable(event)
.map(e -> Long.toString(Runtime.getRuntime().freeMemory() - e.getFreeMemory())).orElse("unknown");
ImmutableMap map = ImmutableMap.of("completed", time, "completed-formated", formatted, "memory-change", change);
ImmutableMap.Builder builder = ImmutableMap.builder().putAll(data).putAll(map);
if (event != null) {
builder.put("event", event);
builder.put("time-taken", time - event.getStartedAt());
}
return builder.build();
}
/*
* We don't want to expose the active map externally as access would not be
* thread safe
*
*/
@Override
public String toString() {
Map result = toMap();
return JacksonUtil.serializeToJson(result);
}
Map toMap() {
Map result = Maps.newHashMap();
result.put("events", events.get());
result.put("active", active);
result.put("added", added.get());
result.put("removed", removed.get());
result.put("recently-finished", recentlyFinished);
return result;
}
public int events() {
return events.get();
}
public int size() {
return active.size();
}
}