@@ -4,52 +4,27 @@ import lombok.Getter;
import lombok.Setter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.daemon.SimpleDaemon;
import org.cobbzilla.util.io.regex.MultiUnderflowException;
import org.cobbzilla.util.io.regex.MultiUnderflowException;
import java.io.IOException;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.util.UUID.randomUUID;
import static java.util.UUID.randomUUID;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.cobbzilla.util.daemon.ZillaRuntime.now;
import static org.cobbzilla.util.daemon.ZillaRuntime.now;
import static org.cobbzilla.util.daemon.ZillaRuntime.terminate;
import static org.cobbzilla.util.system.Sleep.sleep;
import static org.cobbzilla.util.system.Sleep.sleep;
@Slf4j @Accessors(chain=true)
@Slf4j @Accessors(chain=true)
public class MultiUnderflowHandler extends SimpleDaemon {
public class MultiUnderflowHandler {
private final static Map<String, MultiUnderflowHandler> handlers = new ConcurrentHashMap<>() ;
private final MultiUnderflowHandlerMonitor monitor ;
@Getter @Setter private static long checkInterval = SECONDS.toMillis(20);
private static final long TERMINATE_TIMEOUT = SECONDS.toMillis(2);
@Override protected long getSleepTime() { return checkInterval; }
@Override protected void process() {
if (log.isTraceEnabled()) log.trace("process: examining "+handlers.size()+" underflow handlers");
for (Iterator<MultiUnderflowHandler> iter = handlers.values().iterator(); iter.hasNext(); ) {
final MultiUnderflowHandler underflow = iter.next();
if (underflow.closed()) {
if (log.isDebugEnabled()) log.debug("process: removing closed handler: name="+underflow.getHandlerName()+" thread="+underflow.getThread());
iter.remove();
} else if (underflow.getLastRead() > 0 && !underflow.getThread().isAlive()) {
if (log.isDebugEnabled()) log.debug("process: removing dead thread: name="+underflow.getHandlerName()+" thread="+underflow.getThread());
iter.remove();
} else if (now() - underflow.getLastRead() > underflow.getUnderflowTimeout()) {
iter.remove();
if (log.isErrorEnabled()) log.error("process: underflow timed out, terminating: name="+underflow.getHandlerName()+" thread="+underflow.getThread());
terminate(underflow.getThread(), TERMINATE_TIMEOUT);
}
}
public MultiUnderflowHandler (MultiUnderflowHandlerMonitor m) {
this.monitor = m;
m.start();
}
}
public MultiUnderflowHandler () { start( ); }
public MultiUnderflowHandler () { this(MultiUnderflowHandlerMonitor.DEFAULT_UNDERFLOW_MONITOR); }
@Getter private final String id = randomUUID().toString();
@Getter private final String id = randomUUID().toString();
@Getter @Setter private String handlerName;
@Getter @Setter private String handlerName;
@@ -70,7 +45,7 @@ public class MultiUnderflowHandler extends SimpleDaemon {
if (thread == null) {
if (thread == null) {
thread = Thread.currentThread();
thread = Thread.currentThread();
lastRead = now();
lastRead = now();
handlers.put(id, this);
monitor.register( this);
}
}
if (firstUnderflow == 0) {
if (firstUnderflow == 0) {
if (log.isDebugEnabled()) log.debug(handlerName+": first data underflow");
if (log.isDebugEnabled()) log.debug(handlerName+": first data underflow");
@@ -89,7 +64,7 @@ public class MultiUnderflowHandler extends SimpleDaemon {
lastRead = now();
lastRead = now();
if (thread == null) {
if (thread == null) {
thread = Thread.currentThread();
thread = Thread.currentThread();
handlers.put(id, this);
monitor.register( this);
}
}
firstUnderflow = 0;
firstUnderflow = 0;
underflowSleep = minUnderflowSleep;
underflowSleep = minUnderflowSleep;
@@ -99,7 +74,7 @@ public class MultiUnderflowHandler extends SimpleDaemon {
if (!closed()) {
if (!closed()) {
closed.set(true);
closed.set(true);
if (log.isDebugEnabled()) log.debug(handlerName + ": closing");
if (log.isDebugEnabled()) log.debug(handlerName + ": closing");
handlers.remove(id );
monitor.unregister(this );
}
}
}
}