From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- .../ericsson/otp/erlang/OtpCookedConnection.java | 244 +++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java (limited to 'lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java') diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java new file mode 100644 index 0000000000..5abf6e33f7 --- /dev/null +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpCookedConnection.java @@ -0,0 +1,244 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2000-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ +package com.ericsson.otp.erlang; + +import java.io.IOException; +import java.net.Socket; + +/** + *

+ * Maintains a connection between a Java process and a remote Erlang, Java or C + * node. The object maintains connection state and allows data to be sent to and + * received from the peer. + *

+ * + *

+ * Once a connection is established between the local node and a remote node, + * the connection object can be used to send and receive messages between the + * nodes. + *

+ * + *

+ * The various receive methods are all blocking and will return only when a + * valid message has been received or an exception is raised. + *

+ * + *

+ * If an exception occurs in any of the methods in this class, the connection + * will be closed and must be reopened in order to resume communication with the + * peer. + *

+ * + *

+ * The message delivery methods in this class deliver directly to + * {@link OtpMbox mailboxes} in the {@link OtpNode OtpNode} class. + *

+ * + *

+ * It is not possible to create an instance of this class directly. + * OtpCookedConnection objects are created as needed by the underlying mailbox + * mechanism. + *

+ */ +public class OtpCookedConnection extends AbstractConnection { + protected OtpNode self; + + /* + * The connection needs to know which local pids have links that pass + * through here, so that they can be notified in case of connection failure + */ + protected Links links = null; + + /* + * Accept an incoming connection from a remote node. Used by {@link + * OtpSelf#accept() OtpSelf.accept()} to create a connection based on data + * received when handshaking with the peer node, when the remote node is the + * connection intitiator. + * + * @exception java.io.IOException if it was not possible to connect to the + * peer. + * + * @exception OtpAuthException if handshake resulted in an authentication + * error + */ + // package scope + OtpCookedConnection(final OtpNode self, final Socket s) throws IOException, + OtpAuthException { + super(self, s); + this.self = self; + links = new Links(25); + start(); + } + + /* + * Intiate and open a connection to a remote node. + * + * @exception java.io.IOException if it was not possible to connect to the + * peer. + * + * @exception OtpAuthException if handshake resulted in an authentication + * error. + */ + // package scope + OtpCookedConnection(final OtpNode self, final OtpPeer other) + throws IOException, OtpAuthException { + super(self, other); + this.self = self; + links = new Links(25); + start(); + } + + // pass the error to the node + @Override + public void deliver(final Exception e) { + self.deliverError(this, e); + return; + } + + /* + * pass the message to the node for final delivery. Note that the connection + * itself needs to know about links (in case of connection failure), so we + * snoop for link/unlink too here. + */ + @Override + public void deliver(final OtpMsg msg) { + final boolean delivered = self.deliver(msg); + + switch (msg.type()) { + case OtpMsg.linkTag: + if (delivered) { + links.addLink(msg.getRecipientPid(), msg.getSenderPid()); + } else { + try { + // no such pid - send exit to sender + super.sendExit(msg.getRecipientPid(), msg.getSenderPid(), + new OtpErlangAtom("noproc")); + } catch (final IOException e) { + } + } + break; + + case OtpMsg.unlinkTag: + case OtpMsg.exitTag: + links.removeLink(msg.getRecipientPid(), msg.getSenderPid()); + break; + + case OtpMsg.exit2Tag: + break; + } + + return; + } + + /* + * send to pid + */ + void send(final OtpErlangPid from, final OtpErlangPid dest, + final OtpErlangObject msg) throws IOException { + // encode and send the message + sendBuf(from, dest, new OtpOutputStream(msg)); + } + + /* + * send to remote name dest is recipient's registered name, the nodename is + * implied by the choice of connection. + */ + void send(final OtpErlangPid from, final String dest, + final OtpErlangObject msg) throws IOException { + // encode and send the message + sendBuf(from, dest, new OtpOutputStream(msg)); + } + + @Override + public void close() { + super.close(); + breakLinks(); + } + + @Override + protected void finalize() { + close(); + } + + /* + * this one called by dying/killed process + */ + void exit(final OtpErlangPid from, final OtpErlangPid to, + final OtpErlangObject reason) { + try { + super.sendExit(from, to, reason); + } catch (final Exception e) { + } + } + + /* + * this one called explicitely by user code => use exit2 + */ + void exit2(final OtpErlangPid from, final OtpErlangPid to, + final OtpErlangObject reason) { + try { + super.sendExit2(from, to, reason); + } catch (final Exception e) { + } + } + + /* + * snoop for outgoing links and update own table + */ + synchronized void link(final OtpErlangPid from, final OtpErlangPid to) + throws OtpErlangExit { + try { + super.sendLink(from, to); + links.addLink(from, to); + } catch (final IOException e) { + throw new OtpErlangExit("noproc", to); + } + } + + /* + * snoop for outgoing unlinks and update own table + */ + synchronized void unlink(final OtpErlangPid from, final OtpErlangPid to) { + links.removeLink(from, to); + try { + super.sendUnlink(from, to); + } catch (final IOException e) { + } + } + + /* + * When the connection fails - send exit to all local pids with links + * through this connection + */ + synchronized void breakLinks() { + if (links != null) { + final Link[] l = links.clearLinks(); + + if (l != null) { + final int len = l.length; + + for (int i = 0; i < len; i++) { + // send exit "from" remote pids to local ones + self.deliver(new OtpMsg(OtpMsg.exitTag, l[i].remote(), l[i] + .local(), new OtpErlangAtom("noconnection"))); + } + } + } + } +} -- cgit v1.2.3