/* * this method simulates net_kernel only for * the purpose of replying to pings. */ private bool netKernel(OtpMsg m) { OtpMbox mbox = null; try { Erlang.Tuple t = (Erlang.Tuple)(m.getMsg()); Erlang.Tuple req = (Erlang.Tuple)t.elementAt(1); // actual request Erlang.Pid pid = (Erlang.Pid)req.elementAt(0); // originating pid Erlang.Object[] pong = new Erlang.Object[2]; pong[0] = req.elementAt(1); // his #Ref pong[1] = new Erlang.Atom("yes"); mbox = createMbox(); mbox.send(pid, new Erlang.Tuple(pong)); return(true); } catch (System.Exception) { } finally { closeMbox(mbox); } return(false); }
// this function used internally when "process" dies // since Erlang discerns between exit and exit/2. private void exit(int arity, Erlang.Pid to, System.String reason) { try { System.String node = to.node(); if (node.Equals(home.node())) { home.deliver(new OtpMsg(OtpMsg.Tag.exitTag, _self, to, reason)); } else { OtpCookedConnection conn = home.connection(node); if (conn == null) { return; } switch (arity) { case 1: conn.exit(_self, to, reason); break; case 2: conn.exit2(_self, to, reason); break; } } } catch (System.Exception) { } }
internal virtual bool exists(Erlang.Pid local, Erlang.Pid remote) { lock (this) { return(find(local, remote) != -1); } }
/* * <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 Exit Exit} * 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 Pid pid} representing the object to * link to. * * @exception Exit if the {@link Pid pid} referred * to does not exist or could not be reached. * **/ public virtual void link(Erlang.Pid to) { try { System.String node = to.node(); if (node.Equals(home.node())) { if (!home.deliver(new OtpMsg(OtpMsg.Tag.linkTag, _self, to))) { throw new Erlang.Exit("noproc", to); } } else { OtpCookedConnection conn = home.connection(node); if (conn != null) { conn.link(_self, to); } else { throw new Erlang.Exit("noproc", to); } } } catch (Erlang.Exit e) { throw e; } catch (System.Exception) { } links.addLink(_self, to); }
public virtual OtpMbox create() { Erlang.Pid pid = enclosingInstance.createPid(); OtpMbox m = new OtpMbox(enclosingInstance, pid); byPid[pid] = new WeakReference(m); return(m); }
// send has receiver pid but no sender information internal OtpMsg(Erlang.Pid to, OtpInputStream paybuf) { this.tag = sendTag; this.from = null; this.to = to; this.toName = null; this.paybuf = paybuf; this.payload = null; }
/* * Create a unique Erlang PID belonging to the local node. * * @param self the local node. * * @deprecated use OtpLocalNode:createPid() instead **/ public Pid(OtpLocalNode self) { Pid p = self.createPid(); this._id = p._id; this._serial = p._serial; this._creation = p._creation; this._node = p._node; }
// package constructor: called by OtpNode:createMbox(name) // to create a named mbox internal OtpMbox(OtpNode home, Erlang.Pid self, System.String name) { this._self = self; this.home = home; this.name = name; this.queue = new GenericQueue(); this.links = new Links(10); this.monitors = new System.Collections.Hashtable(49, (float)0.95); }
/* * Create an Erlang PID from a stream containing a PID encoded in * Erlang external format. * * @param buf the stream containing the encoded PID. * * @exception DecodeException if the buffer does not * contain a valid external representation of an Erlang PID. **/ public Pid(OtpInputStream buf) { Pid p = buf.read_pid(); this._node = p.node(); this._id = p.id(); this._serial = p.serial(); this._creation = p.creation(); }
/* * this one called explicitely by user code => use exit2 */ internal virtual void exit2(Erlang.Pid from, Erlang.Pid to, System.String reason) { try { base.sendExit2(from, to, reason); } catch (System.Exception) { } }
// special case when reason is an atom (i.e. most of the time) private OtpMsg(Tag tag, Erlang.Pid from, Object /* Pid or string */ to, Erlang.Ref eref, System.String reason, OtpInputStream paybuf) { this.tag = tag; this.from = from; this.to = (Erlang.Pid)(to is Erlang.Pid ? to : null); this.toName = (string)(to is string?to : null); this.paybuf = paybuf; this.payload = new Erlang.Atom(reason); this.eref = eref; }
/* * 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(System.Object o) { if (!(o is Pid)) { return(false); } Pid pid = (Pid)o; return((this._creation == pid._creation) && (this._serial == pid._serial) && (this._id == pid._id) && (_node.CompareTo(pid._node) == 0)); }
internal virtual void removeLink(Erlang.Pid local, Erlang.Pid 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 */ internal virtual void unlink(Erlang.Pid from, Erlang.Pid to) { lock (this) { links.removeLink(from, to); try { base.sendUnlink(from, to); } catch (System.IO.IOException) { } } }
internal virtual int find(Erlang.Pid local, Erlang.Pid remote) { lock (this) { for (int i = 0; i < _count; i++) { if (_links[i].equals(local, remote)) { return(i); } } return(-1); } }
/* * snoop for outgoing links and update own table */ internal virtual void link(Erlang.Pid from, Erlang.Pid to) { lock (this) { try { base.sendLink(from, to); links.addLink(from, to); } catch (System.IO.IOException) { throw new Erlang.Exit("noproc", to); } } }
/*all remote pids get notified about failed pid */ internal virtual Erlang.Pid[] remotePids() { lock (this) { Erlang.Pid[] ret = null; if (_count != 0) { ret = new Erlang.Pid[_count]; for (int i = 0; i < _count; i++) { ret[i] = _links[i].remote(); } } return(ret); } }
/*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 virtual OtpMbox get(Erlang.Pid pid) { WeakReference wr = (WeakReference)byPid[pid]; if (wr != null) { OtpMbox m = (OtpMbox)wr.Target; if (m != null) { return(m); } byPid.Remove(pid); } return(null); }
public virtual OtpMbox create(System.String name) { OtpMbox m = null; lock (byName) { if (get(name) != null) { return(null); } Erlang.Pid pid = enclosingInstance.createPid(); m = new OtpMbox(enclosingInstance, pid, name); byPid[pid] = new WeakReference(m); byName[name] = new WeakReference(m); } return(m); }
internal virtual void addLink(Erlang.Pid local, Erlang.Pid remote) { lock (this) { int i; if ((i = 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 OtpSelf(System.String node, System.String cookie, int port) : base(node, cookie) { System.Net.Sockets.TcpListener temp_tcplistener; //UPGRADE_NOTE: This code will be optimized in the future; temp_tcplistener = new System.Net.Sockets.TcpListener(System.Net.Dns.GetHostEntry("localhost").AddressList[0], port); temp_tcplistener.Start(); sock = temp_tcplistener; if (port != 0) { this._port = port; } else { this._port = ((System.Net.IPEndPoint)sock.LocalEndpoint).Port; } this._pid = createPid(); }
// other message types (link, unlink) internal OtpMsg(Tag tag, Erlang.Pid from, Erlang.Pid to) { // convert TT-tags to equiv non-TT versions switch (tag) { case Tag.sendTTTag: tag = Tag.sendTag; break; case Tag.exitTTTag: tag = Tag.exitTag; break; case Tag.regSendTTTag: tag = Tag.regSendTag; break; case Tag.exit2TTTag: tag = Tag.exit2Tag; break; default: break; } this.tag = tag; this.from = from; this.to = to; }
/* * Create an Erlang {@link Pid 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 virtual Erlang.Pid createPid() { lock(this) { Erlang.Pid p = new Erlang.Pid(_node, pidCount, serial, _creation); pidCount++; if (pidCount > 0x7fff) { pidCount = 0; serial++; if (serial > 0x07) { serial = 0; } } return p; } }
/* * Create an Erlang {@link Pid 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 virtual Erlang.Pid createPid() { lock (this) { Erlang.Pid p = new Erlang.Pid(_node, pidCount, serial, _creation); pidCount++; if (pidCount > 0x7fff) { pidCount = 0; serial++; if (serial > 0x07) { serial = 0; } } return(p); } }
/* * Send a message to a remote {@link Pid pid}, representing * either another {@link OtpMbox mailbox} or an Erlang process. * * @param to the {@link Pid pid} identifying the intended * recipient of the message. * * @param msg the body of the message to send. * **/ public void send(Erlang.Pid to, Erlang.Object msg) { try { System.String node = to.node(); if (node.Equals(home.node())) { home.deliver(new OtpMsg(to, (Erlang.Object)(msg.clone()))); } else { OtpCookedConnection conn = home.connection(node); if (conn == null) { return; } conn.send(_self, to, msg); } } catch (System.Exception) { } }
/* * <p> Remove a link to a remote mailbox or Erlang process. This * method removes a link created with {@link #link link()}. * Links are idempotent; calling this method once will remove all * links between this mailbox and the remote {@link Pid * pid}. </p> * * @param to the {@link Pid pid} representing the object to * unlink from. * **/ public virtual void unlink(Erlang.Pid to) { links.removeLink(_self, to); try { System.String node = to.node(); if (node.Equals(home.node())) { home.deliver(new OtpMsg(OtpMsg.Tag.unlinkTag, _self, to)); } else { OtpCookedConnection conn = home.connection(node); if (conn != null) { conn.unlink(_self, to); } } } catch (System.Exception) { } }
public virtual bool equals(Erlang.Pid local, Erlang.Pid remote) { return((this._local.Equals(local) && this._remote.Equals(remote)) || (this._local.Equals(remote) && this._remote.Equals(local))); }
public virtual bool contains(Erlang.Pid pid) { return(this._local.Equals(pid) || this._remote.Equals(pid)); }
public Link(Erlang.Pid local, Erlang.Pid remote) { this._local = local; this._remote = remote; }
/* * Send an exit signal to a remote process. * * @param dest the Erlang PID of the remote process. * @param reason a string describing the exit reason. * * @exception C#.io.IOException if the connection is not active or * a communication error occurs. **/ public virtual void exit(Erlang.Pid dest, System.String reason) { base.sendExit2(this._self.pid(), dest, reason); }
/* * Remove a link between the local node and the specified process on * the remote node. This method deactivates links created with * {@link #link link()}. * * @param dest the Erlang PID of the remote process. * * @exception C#.io.IOException if the connection is not active or * a communication error occurs. **/ public virtual void unlink(Erlang.Pid dest) { base.sendUnlink(this._self.pid(), dest); }
/* * Create an Exit 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 Exit(System.String reason, Pid pid) : base(reason) { this.pid = pid; }
// send_reg has sender pid and receiver name internal OtpMsg(Erlang.Pid from, System.String toName, OtpInputStream paybuf) { this.tag = regSendTag; this.from = from; this.toName = toName; this.to = null; this.paybuf = paybuf; this.payload = null; }
// send has receiver pid but no sender information internal OtpMsg(Erlang.Pid to, Erlang.Object payload) { this.tag = sendTag; this.from = null; this.to = to; this.toName = null; this.paybuf = null; this.payload = payload; }
public OtpSelf(System.String node, System.String cookie, int port) : base(node, cookie) { System.Net.Sockets.TcpListener temp_tcplistener; //UPGRADE_NOTE: This code will be optimized in the future; temp_tcplistener = new System.Net.Sockets.TcpListener(System.Net.Dns.GetHostEntry("localhost").AddressList[0], port); temp_tcplistener.Start(); sock = temp_tcplistener; if (port != 0) this._port = port; else { this._port = ((System.Net.IPEndPoint)sock.LocalEndpoint).Port; } this._pid = createPid(); }
// other message types (link, unlink) internal OtpMsg(int tag, Erlang.Pid from, Erlang.Pid to) { // convert TT-tags to equiv non-TT versions if (tag > 10) tag -= 10; this.tag = tag; this.from = from; this.to = to; }
/*all remote pids get notified about failed pid */ internal virtual Erlang.Pid[] remotePids() { lock(this) { Erlang.Pid[] ret = null; if (_count != 0) { ret = new Erlang.Pid[_count]; for (int i = 0; i < _count; i++) { ret[i] = _links[i].remote(); } } return ret; } }
// package constructor: called by OtpNode:createMbox(name) // to create a named mbox internal OtpMbox(OtpNode home, Erlang.Pid self, System.String name) { this._self = self; this.home = home; this.name = name; this.queue = new GenericQueue(); this.links = new Links(10); }
// send_reg has sender pid and receiver name internal OtpMsg(Erlang.Pid from, System.String toName, Erlang.Object payload) { this.tag = regSendTag; this.from = from; this.toName = toName; this.to = null; this.paybuf = null; this.payload = payload; }
public int encode_size(Erlang.Object o) { if (o is Erlang.Atom) { return(1 + 2 + o.atomValue().Length); } else if (o is Erlang.Boolean) { return(1 + 2 + (o.boolValue() ? Erlang.Boolean.s_true.atomValue().Length : Erlang.Boolean.s_false.atomValue().Length)); } else if (o is Erlang.Binary) { return(5 + o.binaryValue().Length); } else if (o is Erlang.Long) { long l = o.longValue(); if ((l & 0xff) == l) { return(2); } else if ((l <= OtpExternal.erlMax) && (l >= OtpExternal.erlMin)) { return(5); } return(long_arity(l)); } else if (o is Erlang.Byte) { return(1 + 1); } else if (o is Erlang.Double) { return(9); } else if (o is Erlang.String) { string l = o.stringValue(); if (l.Length == 0) { return(1); } if (l.Length < 0xffff) { return(2 + l.Length); } return(1 + 4 + 2 * l.Length); } else if (o is Erlang.List) { Erlang.List l = o.listValue(); if (l.arity() == 0) { return(1); } int sz = 5; for (int i = 0; i < l.arity(); i++) { sz += encode_size(l[i]); } return(sz); } else if (o is Erlang.Tuple) { Erlang.Tuple l = o.tupleValue(); int sz = 1 + (l.arity() < 0xff ? 1 : 4); for (int i = 0; i < l.arity(); i++) { sz += encode_size(l[i]); } return(sz); } else if (o is Erlang.Pid) { Erlang.Pid p = o.pidValue(); return(1 + (1 + 2 + p.node().Length) + 4 + 4 + 1); } else if (o is Erlang.Ref) { Erlang.Ref p = o.refValue(); int[] ids = p.ids(); return(1 + (1 + 2 + p.node().Length) + 1 + 4 * ids.Length); } else if (o is Erlang.Port) { Erlang.Port p = o.portValue(); return(1 + (1 + 2 + p.node().Length) + 4 + 1); } else { throw new Erlang.Exception("Unknown encode size for object: " + o.ToString()); } }
// exit (etc) has from, to, reason internal OtpMsg(int tag, Erlang.Pid from, Erlang.Pid to, Erlang.Object reason) { this.tag = tag; this.from = from; this.to = to; this.paybuf = null; this.payload = reason; }
// special case when reason is an atom (i.e. most of the time) private OtpMsg(Tag tag, Erlang.Pid from, Object /* Pid or string */ to, Erlang.Ref eref, System.String reason, OtpInputStream paybuf) { this.tag = tag; this.from = from; this.to = (Erlang.Pid)(to is Erlang.Pid ? to : null); this.toName = (string)(to is string ? to : null); this.paybuf = paybuf; this.payload = new Erlang.Atom(reason); this.eref = eref; }
// special case when reason is an atom (i.e. most of the time) internal OtpMsg(int tag, Erlang.Pid from, Erlang.Pid to, System.String reason) { this.tag = tag; this.from = from; this.to = to; this.paybuf = null; this.payload = new Erlang.Atom(reason); }