Package com.ericsson.otp.stdlib

Source Code of com.ericsson.otp.stdlib.OtpSysProcess

package com.ericsson.otp.stdlib;

import java.util.logging.Logger;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangException;
import com.ericsson.otp.erlang.OtpErlangExit;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangPid;
import com.ericsson.otp.erlang.OtpErlangRef;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.ericsson.otp.erlang.OtpMbox;
import com.ericsson.otp.erlang.OtpNode;

/**
* @author Fernando Benavides <elbrujohalcon@inaka.net>
*
*/
public abstract class OtpSysProcess {
  private static final Logger  jlog  = Logger.getLogger(OtpSysProcess.class
                        .getName());
  private OtpMbox        mbox;

  /**
   * Default anonymous constructor
   *
   * @param host
   *            Node where the gen_server will lives
   */
  protected OtpSysProcess(OtpNode host) {
    this.mbox = host.createMbox();
  }

  /**
   * Default named constructor
   *
   * @param host
   *            Node where the gen_server will lives
   * @param name
   *            Name to which the gen_server will be registered
   */
  protected OtpSysProcess(OtpNode host, String name) {
    this.mbox = host.createMbox(name);
  }

  protected final OtpErlangPid getSelf() {
    return mbox.self();
  }

  protected OtpMbox getMbox() {
    return this.mbox;
  }

  /**
   * Gets the process running
   */
  public final void start() {
    new Thread(this.mbox.getName()) {
      @Override
      public void run() {
        loop();
        jlog.fine("...leaving");
      }
    }.start();
  }

  /**
   * Gets the process running and links it to the caller
   *
   * @param caller
   *            Process that starts this one
   * @throws OtpErlangExit
   *             if this process can't be linked to the caller
   */
  public final void startLink(OtpErlangPid caller) throws OtpErlangExit {
    this.mbox.link(caller);
    start();
  }

  protected void handleSystemMessage(OtpErlangObject req, OtpErlangTuple from)
      throws OtpErlangException {
    if (req instanceof OtpErlangAtom) {
      String cmd = ((OtpErlangAtom) req).atomValue();
      if (cmd.equals("suspend")) {
        ok(from);
        suspendedLoop();
      } else if (cmd.equals("resume")) {
        ok(from);
      } else if (cmd.equals("get_status")) {
        reply(from, getStatus(true));
      } else {
        unknownSystemMsg(from, req);
      }
    } else {
      jlog.info("Ignored system message: " + req);
      unknownSystemMsg(from, req);
    }
  }

  private void suspendedLoop() throws OtpErlangException {
    boolean running = true;
    while (running) {
      OtpErlangObject message = mbox.receive();
      if (message instanceof OtpErlangTuple) {
        OtpErlangTuple msg = (OtpErlangTuple) message;
        OtpErlangAtom kind = (OtpErlangAtom) msg.elementAt(0);
        if (kind.atomValue().equals("system") && msg.arity() == 3) {
          OtpErlangTuple from = (OtpErlangTuple) msg.elementAt(1);
          OtpErlangObject req = msg.elementAt(2);
          running = handleSuspendedSystemMessage(req, from);
        } else {
          running = true;
        }
      }
    }
  }

  private boolean handleSuspendedSystemMessage(OtpErlangObject req,
      OtpErlangTuple from) {
    if (req instanceof OtpErlangAtom) {
      String cmd = ((OtpErlangAtom) req).atomValue();
      if (cmd.equals("suspend")) {
        ok(from);
      } else if (cmd.equals("resume")) {
        ok(from);
        return false;
      } else if (cmd.equals("get_status")) {
        reply(from, getStatus(false));
      } else {
        unknownSystemMsg(from, req);
      }
    } else {
      jlog.info("Ignored system message in suspended mode: " + req);
      unknownSystemMsg(from, req);
    }
    return true;
  }

  private OtpErlangObject getStatus(boolean running) {
    OtpErlangList internals = new OtpErlangList(new OtpErlangObject[] {
        new OtpErlangList(), // Process dictionary
        new OtpErlangAtom(running ? "running" : "suspended"),
        new OtpErlangAtom("undefined"), new OtpErlangList(),
        getMiscStatus() });
    OtpErlangTuple status = new OtpErlangTuple(new OtpErlangObject[] {
        new OtpErlangAtom("status"),
        getSelf(),
        new OtpErlangTuple(new OtpErlangObject[] {
            new OtpErlangAtom("class"),
            new OtpErlangAtom(this.getClass().getSimpleName()) }),
        internals });
    return status;
  }

  protected OtpErlangList getMiscStatus() {
    return new OtpErlangList();
  }

  private void unknownSystemMsg(OtpErlangTuple from, OtpErlangObject req) {
    reply(from, new OtpErlangTuple(new OtpErlangObject[] {
        new OtpErlangAtom("error"),
        new OtpErlangTuple(new OtpErlangObject[] {
            new OtpErlangAtom("unknown_system_msg"), req }) }));
  }

  private void ok(OtpErlangTuple from) {
    reply(from, new OtpErlangAtom("ok"));
  }

  /**
   * Returns a reply to the calling process
   *
   * @param from
   *            The calling process reference
   * @param reply
   *            Response to send
   */
  protected void reply(OtpErlangTuple from, OtpErlangObject reply) {
    OtpErlangPid to = (OtpErlangPid) from.elementAt(0);
    OtpErlangRef tag = (OtpErlangRef) from.elementAt(1);
    OtpErlangTuple tuple = new OtpErlangTuple((new OtpErlangObject[] { tag,
        reply }));
    getMbox().send(to, tuple);
  };

  /**********************************************************************************************/

  /**
   * To be overrided by OtpGen... processes
   */
  protected abstract void loop();

  /**
   * Override this function if you want to trap exits
   *
   * @param oee
   *            Exit reason
   * @throws OtpErlangExit
   *             If you want to re-throw the exception
   * @throws OtpStopException
   *             If you want to stop the server
   */
  protected void handleExit(OtpErlangExit oee) throws OtpErlangExit,
      OtpStopException {
    throw oee;
  }
}
TOP

Related Classes of com.ericsson.otp.stdlib.OtpSysProcess

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.