package org.openpixi.pixi.distributed.ibis; import ibis.ipl.*; import org.openpixi.pixi.distributed.util.IncomingCellsHandler; import org.openpixi.pixi.distributed.util.IncomingParticlesHandler; import org.openpixi.pixi.distributed.util.IncomingPointsHandler; import org.openpixi.pixi.physics.particles.Particle; import org.openpixi.pixi.physics.grid.Cell; import org.openpixi.pixi.physics.util.Point; import java.io.IOException; import java.util.List; /** * Handles the exchange of shared data during the simulation. */ public class WorkerToWorker { /* The following constants identify the incoming message. */ private static final int ARRIVING_PARTICLES_MSG = 0; private static final int GHOST_PARTICLES_MSG = 1; private static final int GHOST_CELLS_MSG = 2; private static final int GHOST_CELLS_INDEXES_MSG = 3; private IbisRegistry registry; private ReceivePort recvPort; private SendPort sendPort; /** ID of the neighbor with whom this communicator communicates. */ private int neighborID; /* Handlers of upcalls for higher level classes. */ private IncomingPointsHandler ghostCellsIndexesHandler; private IncomingCellsHandler ghostCellsHandler; private IncomingParticlesHandler ghostParticlesHandler; private IncomingParticlesHandler arrivingParticlesHandler; public void setGhostCellsHandler(IncomingCellsHandler ghostCellsHandler) { this.ghostCellsHandler = ghostCellsHandler; } public void setGhostParticlesHandler(IncomingParticlesHandler ghostParticlesHandler) { this.ghostParticlesHandler = ghostParticlesHandler; } public void setArrivingParticlesHandler(IncomingParticlesHandler arrivingParticlesHandler) { this.arrivingParticlesHandler = arrivingParticlesHandler; } public void setGhostCellsIndexesHandler(IncomingPointsHandler ghostCellsIndexesHandler) { this.ghostCellsIndexesHandler = ghostCellsIndexesHandler; } public WorkerToWorker(IbisRegistry registry, int neighborID) { this.registry = registry; this.neighborID = neighborID; // One ibis instance can not have 2 receive ports with the same ID; thus, // we need to number the receive ports according to the neighbors they are connected to. try { recvPort = registry.getIbis().createReceivePort( PixiPorts.ONE_TO_ONE_PORT, PixiPorts.EXCHANGE_PORT_ID + neighborID, new IncomingMessageHandler()); recvPort.enableConnections(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * To avoid deadlock the send ports should be connected after all the receive ports are created. * Furthermore, we enable upcalls here to avoid upcalls being called to early. */ public void initializeConnection() { recvPort.enableMessageUpcalls(); try { sendPort = registry.getIbis().createSendPort(PixiPorts.ONE_TO_ONE_PORT); int myID = registry.convertIbisIDToWorkerID(registry.getIbis().identifier()); sendPort.connect( registry.convertWorkerIDToIbisID(neighborID), PixiPorts.EXCHANGE_PORT_ID + myID); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } public void sendLeavingParticles(List<Particle> leavingParticles) { try { WriteMessage wm = sendPort.newMessage(); wm.writeInt(ARRIVING_PARTICLES_MSG); wm.writeObject(leavingParticles); wm.finish(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public void sendBorderParticles(List<Particle> borderParticles) { try { WriteMessage wm = sendPort.newMessage(); wm.writeInt(GHOST_PARTICLES_MSG); wm.writeObject(borderParticles); wm.finish(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public void sendBorderCells(List<Cell> borderCells) { try { WriteMessage wm = sendPort.newMessage(); wm.writeInt(GHOST_CELLS_MSG); wm.writeObject(borderCells); wm.finish(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public void closeSendPorts() { try { sendPort.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public void closeReceivePorts() { try { recvPort.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public void sendBorderCellsMap(List<Point> borderCellsMap) { try { WriteMessage wm = sendPort.newMessage(); wm.writeInt(GHOST_CELLS_INDEXES_MSG); wm.writeObject(borderCellsMap); wm.finish(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } private class IncomingMessageHandler implements MessageUpcall { public void upcall(ReadMessage readMessage) throws IOException, ClassNotFoundException { int msgType = readMessage.readInt(); switch (msgType) { case GHOST_CELLS_INDEXES_MSG: List<Point> indexes = (List<Point>)readMessage.readObject(); ghostCellsIndexesHandler.handle(indexes); return; case ARRIVING_PARTICLES_MSG: List<Particle> particles = (List<Particle>)readMessage.readObject(); arrivingParticlesHandler.handle(particles); return; case GHOST_PARTICLES_MSG: particles = (List<Particle>)readMessage.readObject(); ghostParticlesHandler.handle(particles); return; case GHOST_CELLS_MSG: List<Cell> cells = (List<Cell>)readMessage.readObject(); ghostCellsHandler.handle(cells); return; default: assert false: "Unreachable code detected!"; } } } }