Package org.intellij.erlang.debugger.node

Source Code of org.intellij.erlang.debugger.node.ErlangDebuggerNode

/*
* Copyright 2012-2014 Sergey Ignatov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.intellij.erlang.debugger.node;

import com.ericsson.otp.erlang.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import org.intellij.erlang.debugger.node.commands.ErlangDebuggerCommandsProducer;
import org.intellij.erlang.debugger.node.events.ErlangDebuggerEvent;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicBoolean;

public class ErlangDebuggerNode {
  private static final Logger LOG = Logger.getInstance(ErlangDebuggerNode.class);
  private static final String MESSAGE_BOX_NAME = "idea_dbg_box";
  private static final int RECEIVE_TIMEOUT = 50;

  private OtpNode myOtpNode;
  @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
  private OtpMbox myMessageBox;
  private AtomicBoolean myStopped = new AtomicBoolean(false);
  @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
  private OtpErlangPid myRemoteCommandListener;
  private OtpErlangPid myLastSuspendedPid;

  private final Queue<ErlangDebuggerCommandsProducer.ErlangDebuggerCommand> myCommandsQueue = new LinkedList<ErlangDebuggerCommandsProducer.ErlangDebuggerCommand>();
  private ErlangDebuggerEventListener myEventsListener;

  public void startNode() throws ErlangDebuggerNodeException {
    if (myOtpNode != null) return;
    try {
      myOtpNode = new OtpNode("idea_dbg_" + System.currentTimeMillis());
      myMessageBox = myOtpNode.createMbox(MESSAGE_BOX_NAME);
      assert myMessageBox != null;
    } catch (IOException e) {
      String failedToConnectMessage = "Failed to connect to epmd.";
      LOG.debug(failedToConnectMessage, e);
      throw new ErlangDebuggerNodeException(failedToConnectMessage, e);
    }
    ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
      @Override
      public void run() {
        loop();
      }
    });
  }

  public String getName() {
    return myOtpNode.alive();
  }

  public String getMessageBoxName() {
    return myMessageBox.getName();
  }

  public void stop() {
    myStopped.set(true);
  }

  public boolean isStopped() {
    return myStopped.get();
  }

  public void setRemoteCommandListener(OtpErlangPid pid) throws OtpErlangExit {
    myMessageBox.link(pid);
    myRemoteCommandListener = pid;
  }

  public void processSuspended(OtpErlangPid pid) {
    myLastSuspendedPid = pid;
  }

  public void setListener(ErlangDebuggerEventListener listener) {
    myEventsListener = listener;
  }

  public void setBreakpoint(String module, int line) {
    addCommand(ErlangDebuggerCommandsProducer.getSetBreakpointCommand(module, line));
  }

  public void removeBreakpoint(String module, int line) {
    addCommand(ErlangDebuggerCommandsProducer.getRemoveBreakpointCommand(module, line));
  }

  public void interpretModules(List<String> moduleNames) {
    addCommand(ErlangDebuggerCommandsProducer.getInterpretModulesCommand(moduleNames));
  }

  public void runDebugger(String module, String function, List<String> args) {
    addCommand(ErlangDebuggerCommandsProducer.getRunDebuggerCommand(module, function, args));
  }

  public void debugRemoteNode(String nodeName, String cookie) {
    addCommand(ErlangDebuggerCommandsProducer.getDebugRemoteNodeCommand(nodeName, cookie));
  }

  public void stepInto() {
    addCommand(ErlangDebuggerCommandsProducer.getStepIntoCommand(myLastSuspendedPid));
  }

  public void stepOver() {
    addCommand(ErlangDebuggerCommandsProducer.getStepOverCommand(myLastSuspendedPid));
  }

  public void stepOut() {
    addCommand(ErlangDebuggerCommandsProducer.getStepOutCommand(myLastSuspendedPid));
  }

  public void resume() {
    addCommand(ErlangDebuggerCommandsProducer.getContinueCommand(myLastSuspendedPid));
  }

  private void addCommand(ErlangDebuggerCommandsProducer.ErlangDebuggerCommand command) {
    synchronized (myCommandsQueue) {
      myCommandsQueue.add(command);
    }
  }

  private void loop() {
    while (!isStopped()) {
      if (!isStopped()) {
        receiveMessage();
      }
      if (!isStopped()) {
        sendMessages();
      }
    }
    myOtpNode.close();
  }

  private void receiveMessage() {
    try {
      OtpErlangObject receivedMessage = myMessageBox.receive(RECEIVE_TIMEOUT);
      ErlangDebuggerEvent event = ErlangDebuggerEvent.create(receivedMessage);
      if (event != null && myEventsListener != null) {
        event.process(this, myEventsListener);
      } else if (receivedMessage != null) {
        unsupportedMessage(receivedMessage);
      }
    } catch (OtpErlangExit otpErlangExit) {
      if (myEventsListener != null) {
        ErlangDebuggerEvent.create(otpErlangExit).process(this, myEventsListener);
      }
      LOG.info("Erlang node exited.", otpErlangExit);
    } catch (OtpErlangDecodeException e) {
      LOG.debug("Failed to decode received message.", e);
    }
  }

  private void sendMessages() {
    if (myRemoteCommandListener == null) return;
    synchronized (myCommandsQueue) {
      while (!myCommandsQueue.isEmpty()) {
        myMessageBox.send(myRemoteCommandListener, myCommandsQueue.remove().toMessage());
      }
    }
  }

  private static void unsupportedMessage(OtpErlangObject message) {
    LOG.debug("Unsupported message: " + message.toString());
  }
}
TOP

Related Classes of org.intellij.erlang.debugger.node.ErlangDebuggerNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.