/** * Send a pre-encoded message to a process on a remote node. */ protected void SendBuf(OtpErlangPid from, OtpErlangPid dest, OtpOutputStream payload) { if (!Connected) { throw new IOException("Not connected"); } OtpOutputStream header = new OtpOutputStream(headerLen); // preamble: 4 byte length + "passthrough" tag + version header.Write4BE(0); // reserve space for length header.Write1(passThrough); header.Write1(version); // header info header.WriteTupleHead(3); header.WriteLong(sendTag); if (sendCookie) { header.WriteAtom(Local.Cookie); } else { header.WriteAtom(""); } header.WriteAny(dest); // version for payload header.Write1(version); // fix up length in preamble header.Poke4BE(0, header.Length + payload.Length - 4); DoSend(header, payload); }
public bool exists(OtpErlangPid local, OtpErlangPid remote) { lock (this) { return(find(local, remote) != -1); } }
public int compareTo(Object o) { if (!(o is OtpErlangPid)) { return(-1); } OtpErlangPid pid = (OtpErlangPid)o; if (creation == pid.creation) { if (serial == pid.serial) { if (id == pid.id) { return(node.CompareTo(pid.node)); } else { return(id - pid.id); } } else { return(serial - pid.serial); } } else { return(creation - pid.creation); } }
// this function used internally when "process" dies // since Erlang discerns between exit and exit/2. private void exit(int arity, OtpErlangPid to, OtpErlangObject reason) { try { String node = to.Node; if (node.Equals(home.Node)) { home.deliver(new OtpMsg(OtpMsg.exitTag, self, to, reason)); } else { OtpCookedConnection conn = home.getConnection(node); if (conn == null) { return; } switch (arity) { case 1: conn.exit(self, to, reason); break; case 2: conn.exit2(self, to, reason); break; } } } catch (Exception) { } }
/** * Send an exit signal to a remote process. * Used internally when "processes" terminate */ private void SendExit(int tag, OtpErlangPid from, OtpErlangPid dest, IOtpErlangObject reason) { if (!Connected) { throw new IOException("Not connected"); } OtpOutputStream header = new OtpOutputStream(headerLen); // preamble: 4 byte length + "passthrough" tag header.Write4BE(0); // reserve space for length header.Write1(passThrough); header.Write1(version); // header header.WriteTupleHead(4); header.WriteLong(tag); header.WriteAny(from); header.WriteAny(dest); header.WriteAny(reason); // fix up length in preamble header.Poke4BE(0, header.Length - 4); DoSend(header); }
/** * Link to a remote mailbox or Erlang process. Links are idempotent, calling * this method multiple times will not result in more than one link being * created. * * If the remote process subsequently exits or the mailbox is closed, a * subsequent attempt to retrieve a message through this mailbox will cause * an {@link OtpErlangExit OtpErlangExit} exception to be raised. Similarly, * if the sending mailbox is closed, the linked mailbox or process will * receive an exit signal. * * If the remote process cannot be reached in order to set the link, the * exception is raised immediately. */ public void Link(OtpErlangPid to) { try { string node = to.Node; if (node.Equals(home.Node)) { if (!home.Deliver(new OtpMsg(OtpMsg.linkTag, Self, to))) { throw new OtpExit("noproc", to); } } else { OtpCookedConnection conn = home.GetConnection(node); if (conn == null) { throw new OtpExit("noproc", to); } conn.Link(Self, to); } } catch (Exception) { } links.AddLink(Self, to); }
/** * package constructor: called by OtpNode:createMbox(name) to create a named mbox */ internal OtpMbox(OtpNode home, OtpErlangPid self, string name) { Name = name; Self = self; this.home = home; links = new Links(10); }
// this function used internally when "process" dies // since Erlang discerns between exit and exit/2. private void Exit(int arity, OtpErlangPid to, IOtpErlangObject reason) { try { string node = to.Node; if (node.Equals(home.Node)) { home.Deliver(new OtpMsg(OtpMsg.exitTag, Self, to, reason)); return; } OtpCookedConnection conn = home.GetConnection(node); if (conn == null) { return; } switch (arity) { case 1: conn.Exit(Self, to, reason); break; case 2: conn.Exit2(Self, to, reason); break; } } catch (Exception) { } }
/* * this method simulates net_kernel only for the purpose of replying to * pings. */ private bool netKernel(OtpMsg m) { OtpMbox mbox = null; try { OtpErlangTuple t = (OtpErlangTuple)m.getMsg(); OtpErlangTuple req = (OtpErlangTuple)t.elementAt(1); // actual // request OtpErlangPid pid = (OtpErlangPid)req.elementAt(0); // originating // pid OtpErlangObject[] pong = new OtpErlangObject[2]; pong[0] = req.elementAt(1); // his #Ref pong[1] = new OtpErlangAtom("yes"); mbox = createMbox(true); mbox.send(pid, new OtpErlangTuple(pong)); return(true); } catch (Exception) { } finally { closeMbox(mbox); } return(false); }
/** * <p> * Link to a remote mailbox or Erlang process. Links are idempotent, calling * this method multiple times will not result in more than one link being * created. * </p> * * <p> * If the remote process subsequently exits or the mailbox is closed, a * subsequent attempt to retrieve a message through this mailbox will cause * an {@link OtpErlangExit OtpErlangExit} exception to be raised. Similarly, * if the sending mailbox is closed, the linked mailbox or process will * receive an exit signal. * </p> * * <p> * If the remote process cannot be reached in order to set the link, the * exception is raised immediately. * </p> * * @param to * the {@link OtpErlangPid pid} representing the object to * link to. * * @exception OtpErlangExit * if the {@link OtpErlangPid pid} referred to does not * exist or could not be reached. * */ public void link(OtpErlangPid to) { try { String node = to.Node; if (node.Equals(home.Node)) { if (!home.deliver(new OtpMsg(OtpMsg.linkTag, self, to))) { throw new OtpErlangExit("noproc", to); } } else { OtpCookedConnection conn = home.getConnection(node); if (conn != null) { conn.link(self, to); } else { throw new OtpErlangExit("noproc", to); } } } catch (OtpErlangExit e) { throw e; } catch (Exception) { } links.addLink(self, to); }
/* * snoop for outgoing unlinks and update own table */ public void Unlink(OtpErlangPid from, OtpErlangPid to) { lock (lockObj) links.RemoveLink(from, to); try { SendUnlink(from, to); } catch (IOException) { } }
// package constructor: called by OtpNode:createMbox(name) // to create a named mbox internal OtpMbox(OtpNode home, OtpErlangPid self, String name) { this.self = self; this.home = home; this.name = name; queue = new GenericQueue(); links = new Links(10); }
/** * Write an Erlang PID to the stream. */ public void WritePid(OtpErlangPid pid) { Write1(OtpExternal.newPidTag); WriteAtom(pid.Node); Write4BE(pid.Id); Write4BE(pid.Serial); Write4BE(pid.Creation); }
// exit (etc) has from, to, reason internal OtpMsg(int tag, OtpErlangPid from, OtpErlangPid to, OtpErlangObject reason) { this.tag = tag; this.from = from; this.to = to; paybuf = null; payload = reason; }
// special case when reason is an atom (i.e. most of the time) internal OtpMsg(int tag, OtpErlangPid from, OtpErlangPid to, String reason) { this.tag = tag; this.from = from; this.to = to; paybuf = null; payload = new OtpErlangAtom(reason); }
// send_reg has sender pid and receiver name internal OtpMsg(OtpErlangPid from, String toName, OtpInputStream paybuf) { tag = regSendTag; this.from = from; this.toName = toName; to = null; this.paybuf = paybuf; payload = null; }
public OtpErlangPid(OtpLocalNode self) { OtpErlangPid p = self.createPid(); id = p.id; serial = p.serial; creation = p.creation; node = p.node; }
/** * Create an Erlang PID from a stream containing a PID encoded in Erlang * external format. * * @param buf * the stream containing the encoded PID. * * @exception OtpErlangDecodeException * if the buffer does not contain a valid external * representation of an Erlang PID. */ public OtpErlangPid(OtpInputStream buf) { OtpErlangPid p = buf.read_pid(); node = p.Node; id = p.Id; serial = p.Serial; creation = p.Creation; }
// send has receiver pid but no sender information internal OtpMsg(OtpErlangPid to, OtpErlangObject payload) { tag = sendTag; from = null; this.to = to; toName = null; paybuf = null; this.payload = payload; }
// send_reg has sender pid and receiver name internal OtpMsg(OtpErlangPid from, String toName, OtpErlangObject payload) { tag = regSendTag; this.from = from; this.toName = toName; to = null; paybuf = null; this.payload = payload; }
// send has receiver pid but no sender information internal OtpMsg(OtpErlangPid to, OtpInputStream paybuf) { tag = sendTag; from = null; this.to = to; toName = null; this.paybuf = paybuf; payload = null; }
/* * this one called explicitely by user code => use exit2 */ public void exit2(OtpErlangPid from, OtpErlangPid to, OtpErlangObject reason) { try { base.sendExit2(from, to, reason); } catch (Exception) { } }
public void AddLink(OtpErlangPid local, OtpErlangPid remote) { lock (lockObj) { Link l = Find(local, remote); if (l == null) { links.Add(new Link(local, remote)); } } }
public void RemoveLink(OtpErlangPid local, OtpErlangPid remote) { lock (lockObj) { Link l = Find(local, remote); if (l != null) { links.Remove(l); } } }
public OtpErlangFun(OtpErlangPid pid, string module, long index, long uniq, IOtpErlangObject[] freeVars) { Pid = pid; Module = module; Arity = -1; Md5 = null; Index = index; OldIndex = 0; Uniq = uniq; FreeVars = freeVars; }
public OtpErlangFun(OtpErlangPid pid, string module, int arity, byte[] md5, long index, long old_index, long uniq, IOtpErlangObject[] freeVars) { Pid = pid; Module = module; Arity = arity; Md5 = md5; Index = index; OldIndex = old_index; Uniq = uniq; FreeVars = freeVars; }
public OtpMbox create(bool sync) { OtpErlangPid pid = node.createPid(); OtpMbox m = sync ? new OtpMbox(node, pid) : new OtpActorMbox(sched, node, pid); lock (this) { byPid.Add(pid, new WeakReference(m)); } return(m); }
// other message types (link, unlink) internal OtpMsg(int tag, OtpErlangPid from, OtpErlangPid to) { // convert TT-tags to equiv non-TT versions if (tag > 10) { tag -= 10; } this.tag = tag; this.from = from; this.to = to; }
public OtpErlangFun(OtpInputStream buf) { OtpErlangFun f = buf.read_fun(); pid = f.pid; module = f.module; arity = f.arity; md5 = f.md5; index = f.index; old_index = f.old_index; uniq = f.uniq; freeVars = f.freeVars; }
public OtpErlangFun(OtpErlangPid pid, String module, long index, long uniq, OtpErlangObject[] freeVars) { this.pid = pid; this.module = module; arity = -1; md5 = null; this.index = index; old_index = 0; this.uniq = uniq; this.freeVars = freeVars; }
/** * Determine if two PIDs are equal. PIDs are equal if their components are * equal. * * @param port * the other PID to compare to. * * @return true if the PIDs are equal, false otherwise. */ public override bool Equals(Object o) { if (!(o is OtpErlangPid)) { return(false); } OtpErlangPid pid = (OtpErlangPid)o; return(creation == pid.creation && serial == pid.serial && id == pid.id && node == pid.node); }
public OtpErlangFun(OtpErlangPid pid, String module, int arity, byte[] md5, int index, long old_index, long uniq, OtpErlangObject[] freeVars) { this.pid = pid; this.module = module; this.arity = arity; this.md5 = md5; this.index = index; this.old_index = old_index; this.uniq = uniq; this.freeVars = freeVars; }
public void addLink(OtpErlangPid local, OtpErlangPid remote) { lock (this) { if (find(local, remote) == -1) { if (count >= links.Length) { Link[] tmp = new Link[count * 2]; Array.Copy(links, 0, tmp, 0, count); links = tmp; } links[count++] = new Link(local, remote); } } }
public int find(OtpErlangPid local, OtpErlangPid remote) { lock (this) { for (int i = 0; i < count; i++) { if (links[i].equals(local, remote)) { return i; } } return -1; } }
public bool exists(OtpErlangPid local, OtpErlangPid remote) { lock (this) { return find(local, remote) != -1; } }
public void write_fun(OtpErlangPid pid, String module, long old_index, int arity, byte[] md5, long index, long uniq, OtpErlangObject[] freeVars) { if (arity == -1) { write1(OtpExternal.funTag); write4BE(freeVars.Length); pid.encode(this); write_atom(module); write_long(index); write_long(uniq); foreach (OtpErlangObject fv in freeVars) { fv.encode(this); } } else { write1(OtpExternal.newFunTag); int saveSizePos = getPos(); write4BE(0); // this is where we patch in the size write1(arity); writeN(md5); write4BE(index); write4BE(freeVars.Length); write_atom(module); write_long(old_index); write_long(uniq); pid.encode(this); foreach (OtpErlangObject fv in freeVars) { fv.encode(this); } poke4BE(saveSizePos, getPos() - saveSizePos); } }
/** * Send a pre-encoded message to a process on a remote node. * * @param dest * the Erlang PID of the remote process. * @param msg * the encoded message to send. * * @exception java.io.IOException * if the connection is not active or a communication error * occurs. */ protected void sendBuf(OtpErlangPid from, OtpErlangPid dest, OtpOutputStream payload) { if (!connected) { throw new IOException("Not connected"); } OtpOutputStream header = new OtpOutputStream(headerLen); // preamble: 4 byte length + "passthrough" tag + version header.write4BE(0); // reserve space for length header.write1(passThrough); header.write1(version); // header info header.write_tuple_head(3); header.write_long(sendTag); if (sendCookie) { header.write_atom(self.Cookie); } else { header.write_atom(""); } header.write_any(dest); // version for payload header.write1(version); // fix up length in preamble header.poke4BE(0, header.size() + payload.size() - 4); do_send(header, payload); }
/** * Create an OtpErlangExit exception with the given reason and sender pid. * * @param reason * the reason this exit signal has been sent. * * @param pid * the pid that sent this exit. */ public OtpErlangExit(OtpErlangObject reason, OtpErlangPid pid) : base(reason.ToString()) { this.reason = reason; this.pid = pid; }
/* all remote pids get notified about failed pid */ public OtpErlangPid[] remotePids() { lock (this) { OtpErlangPid[] ret = null; if (count != 0) { ret = new OtpErlangPid[count]; for (int i = 0; i < count; i++) { ret[i] = links[i].Remote; } } return ret; } }
public void removeLink(OtpErlangPid local, OtpErlangPid remote) { lock (this) { int i; if ((i = find(local, remote)) != -1) { count--; links[i] = links[count]; links[count] = null; } } }
/* * snoop for outgoing unlinks and update own table */ public void unlink(OtpErlangPid from, OtpErlangPid to) { lock (this) { links.removeLink(from, to); try { base.sendUnlink(from, to); } catch (IOException) { } } }
/** * <p> * Equivalent to <code>OtpErlangExit(new OtpErlangAtom(reason), * pid)</code>. * </p> * * @param reason * the reason this exit signal has been sent. * * @param pid * the pid that sent this exit. * * @see #OtpErlangExit(OtpErlangObject, OtpErlangPid) */ public OtpErlangExit(String reason, OtpErlangPid pid) : this(new OtpErlangAtom(reason), pid) { }
/** * Create an Erlang {@link OtpErlangPid pid}. Erlang pids are based upon * some node specific information; this method creates a pid using the * information in this node. Each call to this method produces a unique pid. * * @return an Erlang pid. */ public OtpErlangPid createPid() { lock (this) { OtpErlangPid p = new OtpErlangPid(base.Node, pidCount, serial, base.Creation); pidCount++; if (pidCount > 0x7fff) { pidCount = 0; serial++; if (serial > 0x1fff) /* 13 bits */ { serial = 0; } } return p; } }
/* * look up a mailbox based on its pid. If the mailbox has gone out of * scope we also remove the reference from the hashtable so we don't * find it again. */ public OtpMbox get(OtpErlangPid pid) { lock (this) { if (byPid.ContainsKey(pid)) { WeakReference wr = byPid[pid]; OtpMbox m = (OtpMbox)wr.Target; if (m != null) { return m; } byPid.Remove(pid); } return null; } }
/* * send to remote name dest is recipient's registered name, the nodename is * implied by the choice of connection. */ public void send(OtpErlangPid from, String dest, OtpErlangObject msg) { // encode and send the message sendBuf(from, dest, new OtpOutputStream(msg)); }
/** * Send an exit signal to a remote process. * * @param dest * the Erlang PID of the remote process. * @param reason * an Erlang term describing the exit reason. * * @exception java.io.IOException * if the connection is not active or a communication error * occurs. */ protected void sendExit2(OtpErlangPid from, OtpErlangPid dest, OtpErlangObject reason) { sendExit(exit2Tag, from, dest, reason); }
/* * snoop for outgoing links and update own table */ public void link(OtpErlangPid from, OtpErlangPid to) { lock (this) { try { base.sendLink(from, to); links.addLink(from, to); } catch (IOException) { throw new OtpErlangExit("noproc", to); } } }
private void sendExit(int tag, OtpErlangPid from, OtpErlangPid dest, OtpErlangObject reason) { if (!connected) { throw new IOException("Not connected"); } OtpOutputStream header = new OtpOutputStream(headerLen); // preamble: 4 byte length + "passthrough" tag header.write4BE(0); // reserve space for length header.write1(passThrough); header.write1(version); // header header.write_tuple_head(4); header.write_long(tag); header.write_any(from); header.write_any(dest); header.write_any(reason); // fix up length in preamble header.poke4BE(0, header.size() - 4); do_send(header); }
public static OtpErlangTuple Load(OtpMbox mbox, OtpErlangPid pid, string script) { OtpErlangObject body; OtpErlangBoolean debug = new OtpErlangBoolean(false); OtpErlangObject message; if (script.Length <= 65535) { body = new OtpErlangString(script); } else { body = new OtpErlangBinary(System.Text.Encoding.GetEncoding("iso-8859-1").GetBytes(script)); } message = new OtpErlangTuple(new OtpErlangObject[] { mbox.Self, new OtpErlangAtom("load"), body, debug }); mbox.send(pid, message); OtpErlangTuple reply = (OtpErlangTuple)mbox.receive(); Console.WriteLine("Load: {0}", reply); return reply; }
public OtpSelf(String node, String cookie, int port) : base(node, cookie) { sock = new TcpListener(new IPEndPoint(IPAddress.Any, port)); sock.Start(); if (port != 0) { this.port = port; } else { this.port = ((IPEndPoint)sock.LocalEndpoint).Port; } pid = createPid(); }