package ibis.ipl.impl.stacking.lrmc; import ibis.ipl.AlreadyConnectedException; import ibis.ipl.ConnectionFailedException; import ibis.ipl.ConnectionsFailedException; import ibis.ipl.IbisIdentifier; import ibis.ipl.NoSuchPropertyException; import ibis.ipl.PortType; import ibis.ipl.ReceivePortIdentifier; import ibis.ipl.SendPort; import ibis.ipl.SendPortIdentifier; import ibis.ipl.WriteMessage; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Properties; public class LrmcSendPort implements SendPort { private final LrmcSendPortIdentifier identifier; private final Multicaster om; IbisIdentifier[] connectedTo = new IbisIdentifier[0]; HashSet<IbisIdentifier> connections = new HashSet<IbisIdentifier>(); boolean connectionsChanged = false; boolean closed = false; LrmcWriteMessage message = null; public LrmcSendPort(Multicaster om, LrmcIbis ibis, Properties props) { this.om = om; identifier = new LrmcSendPortIdentifier(ibis.identifier(), om.name); } public synchronized void close() throws IOException { closed = true; om.sendPort = null; connections.clear(); if (message != null) { throw new IOException("Close called while a message is alive"); } om.removeSendPort(); } public void connect(ReceivePortIdentifier receiver) throws ConnectionFailedException { connect(receiver, 0, true); } public synchronized void connect(ReceivePortIdentifier receiver, long timeoutMillis, boolean fillTimeout) throws ConnectionFailedException { if (closed) { throw new ConnectionFailedException("Sendport is closed", receiver); } if (!identifier.name.equals(receiver.name())) { throw new ConnectionFailedException( "LRMCIbis sendport connect requires that the " + "receiveport has the same name", receiver); } if (connections.contains(receiver.ibisIdentifier())) { throw new AlreadyConnectedException( "This connection already exists", receiver); } connections.add(receiver.ibisIdentifier()); connectionsChanged = true; } public ReceivePortIdentifier connect(IbisIdentifier ibisIdentifier, String receivePortName) throws ConnectionFailedException { ReceivePortIdentifier id = new LrmcReceivePortIdentifier( ibisIdentifier, receivePortName); connect(id, 0, true); return id; } public ReceivePortIdentifier connect(IbisIdentifier ibisIdentifier, String receivePortName, long timeoutMillis, boolean fillTimeout) throws ConnectionFailedException { ReceivePortIdentifier id = new LrmcReceivePortIdentifier( ibisIdentifier, receivePortName); connect(id, timeoutMillis, fillTimeout); return id; } public void connect(ReceivePortIdentifier[] receivePortIdentifiers) throws ConnectionsFailedException { connect(receivePortIdentifiers, 0, true); } public void connect(ReceivePortIdentifier[] receivePortIdentifiers, long timeoutMillis, boolean fillTimeout) throws ConnectionsFailedException { ArrayList<ReceivePortIdentifier> succes = new ArrayList<ReceivePortIdentifier>(); HashMap<ReceivePortIdentifier, Throwable> results = new HashMap<ReceivePortIdentifier, Throwable>(); for (ReceivePortIdentifier id : receivePortIdentifiers) { try { connect(id, 0, true); succes.add(id); } catch (Throwable e) { results.put(id, e); } } // We are done OR we ran out of time OR we tried everyone at once and // are not supposed to continue. if (succes.size() != receivePortIdentifiers.length) { // Some connections have failed. Throw a ConnectionsFailedException // to inform the user of this. // Gather all exceptions from the result map. Add new once for // targets that have not been tried at all. ConnectionsFailedException ex = new ConnectionsFailedException(); for (ReceivePortIdentifier rp : results.keySet()) { Throwable tmp = results.get(rp); if (tmp instanceof ConnectionFailedException) { ex.add((ConnectionFailedException) tmp); } else { ex.add(new ConnectionFailedException("Connection failed", rp, tmp)); } } // Add a list of connections that were successful. ex .setObtainedConnections(succes .toArray(new ibis.ipl.ReceivePortIdentifier[succes .size()])); throw ex; } } public ReceivePortIdentifier[] connect(Map<IbisIdentifier, String> ports) throws ConnectionsFailedException { return connect(ports, 0, true); } public ReceivePortIdentifier[] connect(Map<IbisIdentifier, String> ports, long timeoutMillis, boolean fillTimeout) throws ConnectionsFailedException { ibis.ipl.ReceivePortIdentifier[] ids = new ibis.ipl.ReceivePortIdentifier[ports .size()]; int index = 0; for (Map.Entry<ibis.ipl.IbisIdentifier, String> entry : ports .entrySet()) { ids[index++] = new LrmcReceivePortIdentifier(entry.getKey(), entry .getValue()); } connect(ids, timeoutMillis, fillTimeout); // may throw an exception return ids; } public ReceivePortIdentifier[] connectedTo() { // Not supported. return null; } public void disconnect(ReceivePortIdentifier receiver) throws IOException { if (closed) { throw new IOException("Sendport is closed"); } if (!identifier.name.equals(receiver.name())) { throw new IOException( "LRMCIbis sendport disconnect requires that the " + "receiveport has the same name"); } if (!connections.contains(receiver.ibisIdentifier())) { throw new IOException("This connection does not exists"); } connections.remove(receiver.ibisIdentifier()); connectionsChanged = true; } public void disconnect(IbisIdentifier ibisIdentifier, String receivePortName) throws IOException { disconnect(new LrmcReceivePortIdentifier(ibisIdentifier, receivePortName)); } public PortType getPortType() { return om.portType; } public SendPortIdentifier identifier() { return identifier; } public ReceivePortIdentifier[] lostConnections() { // not supported return null; } public String name() { return identifier.name; } public synchronized WriteMessage newMessage() throws IOException { if (closed) { throw new IOException("Sendport is closed"); } while (message != null) { try { wait(); } catch (Throwable e) { // ignored } } if (connectionsChanged) { connectionsChanged = false; connectedTo = connections.toArray(new IbisIdentifier[connections .size()]); } message = new LrmcWriteMessage(this, om, connectedTo); return message; } public String getManagementProperty(String key) throws NoSuchPropertyException { throw new NoSuchPropertyException("No properties in LRMCRSendPort"); } public Map<String, String> managementProperties() { return new HashMap<String, String>(); } public void printManagementProperties(PrintStream stream) { } public void setManagementProperties(Map<String, String> properties) throws NoSuchPropertyException { throw new NoSuchPropertyException("No properties in LRMCSendPort"); } public void setManagementProperty(String key, String value) throws NoSuchPropertyException { throw new NoSuchPropertyException("No properties in LRMCSendPort"); } }