![JAR search and dependency download from the Maven repository](/logo.png)
de.tsl2.nano.network.JobServer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tsl2.nano.vnet Show documentation
Show all versions of tsl2.nano.vnet Show documentation
TSL2 Framework VirtualNetwork (Generic parallelized Network-Mechanism providing implementations for: NeuronalNetwork, Routing, Workflow)
The newest version!
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Tom, Thomas Schneider
* created on: 28.11.2013
*
* Copyright: (c) Thomas Schneider 2013, all rights reserved
*/
package de.tsl2.nano.network;
import java.io.Closeable;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import javax.net.ServerSocketFactory;
import org.apache.commons.logging.Log;
import de.tsl2.nano.core.ManagedException;
import de.tsl2.nano.core.log.LogFactory;
/**
* Provides a mechanism to distribute jobs to other hosts - without manual installation of new classes and jars.
*
* @author Tom, Thomas Schneider
* @version $Revision$
*/
public class JobServer implements Runnable, Closeable {
/** local thread pool */
private transient ExecutorService localExecutorService = Executors.newCachedThreadPool();
/** ip adresses of registered workstations */
private Collection availableWorkstations;
/**
* current connections. key: ip adress of a connected workstation (see {@link #availableWorkstations}. response:
* current connection.
*/
transient private Map connections;
transient private Map>> loadedCommands;
/** port, used for all connections */
private int port;
private static final Log LOG = LogFactory.getLog(JobServer.class);
/**
* constructor
*/
public JobServer() {
this(Executors.newCachedThreadPool(), Arrays.asList("127.0.0.1"), 9876, true);
}
public JobServer(int port) {
this(Executors.newCachedThreadPool(), Arrays.asList("127.0.0.1"), port, true);
}
/**
* constructor
*/
public JobServer(ExecutorService executorService,
Collection availableWorkstations,
int port,
boolean isWorker) {
super();
this.localExecutorService = executorService;
this.availableWorkstations = availableWorkstations;
this.connections = new HashMap();
loadedCommands = new HashMap>>();
this.port = port;
if (isWorker) {
localExecutorService.execute(this);
}
}
private Socket newConnection() {
if (connections.size() == availableWorkstations.size()) {
return null;
}
Set ips = connections.keySet();
for (String ip : availableWorkstations) {
if (!ips.contains(ip)) {
try {
Socket socket = new Socket(ip, port);
connections.put(ip, socket);
return socket;
} catch (Exception e) {
ManagedException.forward(e);
}
}
}
return null;
}
private Socket getConnection() {
Socket socket = newConnection();
return socket != null ? socket : getMostAvailableConnection();
}
private Socket getMostAvailableConnection() {
Collection sockets = connections.values();
for (Socket socket : sockets) {
//TODO: how to check availability?
if (!socket.isConnected()) {
return socket;
}
}
throw new IllegalStateException("all registered workstations are in use! no more connections available");
}
private boolean isLoaded(String ip, Class> command) {
return loadedCommands.containsKey(ip) && loadedCommands.get(ip).contains(command);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Future execute(String name, Callable command) {
Socket connection = getConnection();
LOG.info("distributing new job '" + command + "' on target " + connection);
ObjectOutputStream o;
ClassLoader cl = null;
try {
//don't send class (use urlclassloader on the other side) but send object to the remote host
//TODO: perhaps, send current classloader? the urlclassloader would have to know, which jars and pathes to load!
if (!isLoaded(connection.getInetAddress().getHostAddress(), command.getClass())) {
//TODO: don't use classloader but provide jars/directories in url-parameter of JobContext!
cl = new SerializableClassLoader(command.getClass().getClassLoader());
}
o = new ObjectOutputStream(connection.getOutputStream());
o.writeObject(new JobContext(name, command, cl, null));
return new Work(name, connection);
} catch (Exception e) {
ManagedException.forward(e);
FutureTask futureTask = new FutureTask(command);
return futureTask;
}
}
/**
* waits for the given execution to be done.
* @param name job name
* @param command execution logic
* @param timeout max time to wait
* @return result of given job
*/
public CONTEXT executeWait(String name, Callable command, long timeout) {
try {
return execute(name, command).get(timeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
ManagedException.forward(e);
return null;
}
}
/**
* waits for remote requests to do some work.
*/
@Override
public void run() {
ServerSocket serverSocket = null;
try {
//create a socket, waiting for a connection to get a working job
serverSocket = ServerSocketFactory.getDefault().createServerSocket(port);
while (port > 0) {
new Worker(localExecutorService, serverSocket.accept());
}
} catch (Exception e) {
ManagedException.forward(e);
} finally {
if (serverSocket != null)
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void close() throws IOException {
port = 0;
Collection c = connections.values();
for (Socket socket : c) {
socket.close();
}
}
}
class SerializableClassLoader extends ClassLoader implements Serializable {
private static final long serialVersionUID = -2466479262962610559L;
public SerializableClassLoader() {
super();
}
public SerializableClassLoader(ClassLoader parent) {
super(parent);
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
//TODO: howto read ClassLoader.classes: out.writeObject(classes);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
//TODO: howto store ClassLoader.classes: out.writeObject(classes);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy