package ibis.ipl.registry.central.client;
import ibis.ipl.RegistryEventHandler;
import ibis.ipl.registry.central.Event;
import ibis.util.ThreadPool;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final class Upcaller implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(Upcaller.class);
private RegistryEventHandler handler;
private final List<Event> pendingEvents;
/** Set when registry upcalls are enabled. */
private boolean registryUpcallerEnabled = false;
/** Set when processing a registry upcall. */
private boolean busyUpcaller = false;
Upcaller(RegistryEventHandler handler) {
this.handler = handler;
pendingEvents = new LinkedList<Event>();
ThreadPool.createNew(this, "upcaller");
}
synchronized void enableEvents() {
registryUpcallerEnabled = true;
notifyAll();
}
synchronized void disableEvents() {
registryUpcallerEnabled = false;
while (busyUpcaller) {
try {
wait();
} catch (Exception e) {
// nothing
}
}
}
private synchronized void setBusyUpcaller() {
busyUpcaller = true;
}
private synchronized void clearBusyUpcaller() {
busyUpcaller = false;
notifyAll();
}
private synchronized Event waitForEvent() {
while (!(registryUpcallerEnabled && !pendingEvents.isEmpty())) {
try {
wait();
} catch (Exception e) {
// nothing
}
}
return pendingEvents.remove(0);
}
synchronized void newEvent(Event event) {
logger.debug("newEvent: " + event);
pendingEvents.add(event);
notifyAll();
}
synchronized void stop() {
pendingEvents.add(null);
notifyAll();
}
public void run() {
while (true) {
Event event = waitForEvent();
if (event == null) {
// registry stopped
return;
}
logger.debug("doing upcall for event: " + event);
setBusyUpcaller();
try {
switch (event.getType()) {
case Event.JOIN:
handler.joined(event.getIbis());
break;
case Event.LEAVE:
handler.left(event.getIbis());
break;
case Event.DIED:
handler.died(event.getIbis());
break;
case Event.SIGNAL:
handler.gotSignal(event.getDescription(), event.getIbis());
break;
case Event.ELECT:
handler.electionResult(event.getDescription(), event
.getIbis());
break;
case Event.UN_ELECT:
handler.electionResult(event.getDescription(), null);
break;
case Event.POOL_CLOSED:
handler.poolClosed();
break;
case Event.POOL_TERMINATED:
handler.poolTerminated(event.getIbis());
break;
default:
logger.error("unknown event type: " + event.getType());
}
} catch (Throwable t) {
logger.error("error on handling event", t);
}
logger.debug("upcall for event " + event + " done");
clearBusyUpcaller();
}
}
}