/* * Created by Andrey Cherkashin (acherkashin) * http://acherkashin.me * * License * Copyright (c) 2015 Andrey Cherkashin * The project released under the MIT license: http://opensource.org/licenses/MIT */ package ragefist.core.distribution; import com.juniform.JUniform; import com.juniform.JUniformMutableObject; import com.juniform.JUniformObject; import java.net.ConnectException; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import ragefist.core.Processor; import ragefist.core.ProcessorTask; import ragefist.core.ProcessorTask.IProcessorTaskDelegate; import ragefist.core.network.Client; import ragefist.core.network.ClientProcessor; import ragefist.core.network.ClientProcessor.ClientProcessorTask; import ragefist.core.network.Server; /** * * @author acherkashin */ public class DistributedServerConnector extends Processor implements Runnable, IProcessorTaskDelegate { // ---------------------------------------------------------------------- // // TASKS MANAGEMENTS // ---------------------------------------------------------------------- // public static class DistributedServerConnectorTask extends ProcessorTask { private final String _serverGroupName; private final int _serverId; private final JUniformMutableObject _packet; public DistributedServerConnectorTask(String groupName, int serverId, JUniformMutableObject packet) { _serverGroupName = groupName; _serverId = serverId; _packet = packet; setAsync(true); } @Override protected boolean _executeImpl(Processor processor) { DistributedServerConnector target = (DistributedServerConnector)processor; Client client; try { client = target._getRemoteServerSocket(_serverGroupName, _serverId); } catch (IllegalArgumentException | ConnectException ex) { Logger.getLogger(DistributedServerConnector.class.getName()).log(Level.SEVERE, "failed to connect to a remote server", ex); this.failWithError("Failed to connect to a remote server: "+ex.getMessage()); return false; } if (client == null) { this.failWithError("Failed to connect to a remote server: unknown reason"); return false; } ClientProcessorTask sendTask = new ClientProcessorTask(client, _packet); sendTask.setDelegate(target); sendTask.setAttachment(this); target._clientProcessor.addTask(sendTask); return true; } } @Override public void whenTaskIsFinished(ProcessorTask task) { DistributedServerConnectorTask parentTask = (DistributedServerConnectorTask) task.getAttachment(); JUniformObject resp = (JUniformObject) task.getData(); Long rs = resp.getProperty("rs").toLong(); JUniformObject data = null; if (resp.getProperty("data").isNotNull()) { data = resp.getProperty("data"); } String error = null; if (resp.getProperty("error").isNotNull()) { error = resp.getProperty("error").toString(); } if (rs == 1) { if (data != null) { parentTask.completeWithData(data); } else { parentTask.complete(); } } else { parentTask.failWithError(error); } } // ---------------------------------------------------------------------- // // PRIVATE // ---------------------------------------------------------------------- // private final Map<String,Map<Integer,Client>> _connectorHash = new HashMap<>(); private final Map<String,DistributedServerGroup> _serverGroups; private final ClientProcessor _clientProcessor; public DistributedServerConnector(Map<String,DistributedServerGroup> serverGroups) { _serverGroups = serverGroups; _clientProcessor = new ClientProcessor(); } @Override public void run() { while(true) { this.processTasks(); _clientProcessor.processTasks(); try { Thread.sleep(1); } catch (InterruptedException ex) { Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); } } } private Client _getRemoteServerSocket(String groupName, int serverId) throws IllegalArgumentException, ConnectException { if (_connectorHash.containsKey(groupName)) { Map<Integer,Client> socketMap = _connectorHash.get(groupName); if (socketMap.containsKey(serverId)) { return socketMap.get(serverId); } } // Getting a server's info if (!_serverGroups.containsKey(groupName)) { throw new IllegalArgumentException("Failed to find server group with name "+groupName); } DistributedServerGroup serverGroup = _serverGroups.get(groupName); DistributedServer server; try { server = serverGroup.getServers().get(serverId); } catch (IndexOutOfBoundsException ex) { throw new IllegalArgumentException("Failed to find server "+serverId+" in group with name "+groupName); } // Creating a socket Client socket = _clientProcessor.getClientForHostPort(server.getRPCHost(), server.getRPCPort()); socket.setPacketPacker(JUniform.getPackerInstance(server.getRPCPacketFormat())); // Save Map<Integer,Client> socketMap; if (!_connectorHash.containsKey(groupName)) { socketMap = new HashMap<>(); _connectorHash.put(groupName, socketMap); } else { socketMap = _connectorHash.get(groupName); } socketMap.put(serverId, socket); return socket; } }