package io.vivarium.server; import java.util.HashMap; import java.util.Map; import org.java_websocket.WebSocket; import com.google.common.base.Preconditions; import io.vivarium.util.UUID; import io.vivarium.util.concurrency.StartableStoppable; public class ClientConnectionManager implements StartableStoppable { public static final int DUPLICATE_CONNECTION = 2127; public static final int SERVER_SHUTDOWN = 2128; // Dependencies private final ClientConnectionFactory _clientConnectionFactory; // Internal state private Map<WebSocket, UUID> _webSocketToWorkerID = new HashMap<>(); private Map<UUID, ClientConnection> _workerIDToConnection = new HashMap<>(); public ClientConnectionManager(ClientConnectionFactory clientConnectionFactory) { this._clientConnectionFactory = clientConnectionFactory; } public synchronized ClientConnection registerWorker(UUID workerID, WebSocket workerSocket) { Preconditions.checkNotNull(workerID); Preconditions.checkNotNull(workerSocket); if (_workerIDToConnection.containsKey(workerID)) { ClientConnection connection = _workerIDToConnection.get(workerID); connection.setWebSocket(workerSocket); // Update the uuid <-> socket maps internalDeregisterWorker(workerID, workerSocket); internalRegisterWorker(workerID, workerSocket); } else { ClientConnection connection = _clientConnectionFactory.make(workerID, workerSocket); _workerIDToConnection.put(workerID, connection); // Update the uuid <-> socket maps internalRegisterWorker(workerID, workerSocket); } return _workerIDToConnection.get(workerID); } @Override public void start() { // Nothing required to start } @Override public synchronized void stop() { _webSocketToWorkerID.clear(); for (UUID uuid : _workerIDToConnection.keySet()) { _workerIDToConnection.remove(uuid).stop(); } } private void internalDeregisterWorker(UUID workerID, WebSocket workerSocket) { _webSocketToWorkerID.remove(workerSocket); } private void internalRegisterWorker(UUID workerID, WebSocket workerSocket) { _webSocketToWorkerID.put(workerSocket, workerID); } public synchronized void socketClosed(WebSocket closedSocket) { Preconditions.checkNotNull(closedSocket); if (_webSocketToWorkerID.containsKey(closedSocket)) { UUID workerID = _webSocketToWorkerID.remove(closedSocket); _workerIDToConnection.get(workerID).socketClosed(closedSocket); } } public synchronized ClientConnection getConnectionForWorker(UUID workerID) { Preconditions.checkNotNull(workerID); if (_workerIDToConnection.containsKey(workerID)) { return _workerIDToConnection.get(workerID); } else { throw new IllegalStateException("Worker " + workerID + " is not known."); } } }