package org.erlide.backend.debug;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.erlide.backend.api.IBackend;
import org.erlide.backend.api.IBackendListener;
import org.erlide.backend.debug.model.ErlangDebugTarget;
import org.erlide.util.ErlLogger;
import com.ericsson.otp.erlang.OtpErlangDecodeException;
import com.ericsson.otp.erlang.OtpErlangExit;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangPid;
import com.ericsson.otp.erlang.OtpMbox;
import com.google.common.collect.Lists;
/**
* This daemon is almost a copy of ErlangEventPublisher, but accepts generic
* messages because the debugger can't be convinced to send erlide_jrpc events.
* The handler is also hardcoded.
*/
public class DebuggerEventDaemon implements IBackendListener {
private IBackend backend;
volatile boolean stopped = false;
private final DebugEventHandler handler;
private OtpMbox mbox;
final static boolean DEBUG = Boolean
.parseBoolean(System.getProperty("erlide.event.daemon"));
private final class HandlerJob implements Runnable {
private final IBackend myBackend;
public HandlerJob(final IBackend backend) {
myBackend = backend;
}
@Override
public void run() {
do {
try {
final List<OtpErlangObject> messages = receiveSomeMessages(mbox);
if (messages.size() != 0) {
if (DEBUG) {
for (final OtpErlangObject message : messages) {
ErlLogger.debug("MSG: %s", message);
}
}
handler.handleMessages(messages);
}
} catch (final OtpErlangExit e) {
if (myBackend.isRunning()) {
// backend crashed -- restart?
// also when it was closed... how do we tell difference?
// ErlLogger.warn(e);
}
} catch (final Exception e) {
ErlLogger.warn(e);
}
} while (!stopped);
}
private List<OtpErlangObject> receiveSomeMessages(final OtpMbox box)
throws OtpErlangExit, OtpErlangDecodeException {
final List<OtpErlangObject> messages = Lists.newArrayList();
OtpErlangObject msg = box.receive(200);
if (msg != null) {
messages.add(msg);
// if there are more queued events, retrieve not
// more than 10 of them
int count = 0;
do {
msg = box.receive(0);
if (msg != null) {
messages.add(msg);
count++;
}
} while (count < 10 && msg != null && !stopped);
}
return messages;
}
}
public DebuggerEventDaemon(final IBackend b, final ErlangDebugTarget target) {
backend = b;
handler = new DebugEventHandler(target);
}
public synchronized void start() {
stopped = false;
mbox = backend.getRuntime().createMbox();
new Thread(new HandlerJob(backend)).start();
}
public synchronized void stop() {
stopped = true;
}
@Override
public void runtimeAdded(final IBackend b) {
}
@Override
public void runtimeRemoved(final IBackend b) {
if (b == backend) {
stop();
backend = null;
}
}
@Override
public void moduleLoaded(final IBackend aBackend, final IProject project,
final String moduleName) {
}
public OtpErlangPid getMBox() {
return mbox.self();
}
}