package hu.u_szeged.nbo.server;
import hu.u_szeged.nbo.common.Result;
import hu.u_szeged.nbo.server.plugins.GEOMSolver;
import hu.u_szeged.nbo.server.plugins.MILPSolver;
import hu.u_szeged.nbo.server.plugins.NBOPlugin;
import hu.u_szeged.nbo.server.plugins.ResourceAllocationSolver;
import hu.u_szeged.nbo.server.plugins.SimpleMPSSolver;
import hu.u_szeged.nbo.server.threads.SSLRMIRegistry;
import java.io.File;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.SimpleTimeZone;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
/**
* <p>
* Main server class to handle SSL connection, login and
* threads for running computations. Quite basic right now.
* </p>
*
* @author Dömötör Gyimesi mailto:dgyimesi@gmail.com
*
*/
public class NBOServer extends UnicastRemoteObject implements NBOServerIF {
/** <p>
* Check out <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/io/Serializable.html">
* the API documentation</a> for more details.
* </p>
*/
private static final long serialVersionUID = 3182194951661914226L;
/** <p> Thread running the registry, currently not in use </p> */
// TODO: fix registry failure when running in separate thread
private static Thread sslRmiRegistry;
/** <p> Registry's availablity </p> */
private Registry registry;
/** <p> Reference to the registry, currently not in use, see TODOlist </p> */
private static boolean sslRmiRegistryIsAlive = false;
/** <p> Repository of authorized users </p> */
private HashMap<String, User> users = new HashMap<String, User>();
private static Logger logger = Logger.getLogger(NBOServer.class.getName());
private static FileHandler fileHandler;
public NBOServer() throws java.rmi.RemoteException {
super(43001, new SslRMIClientSocketFactory(),
new SslRMIServerSocketFactory(
new String[] { "SSL_RSA_WITH_RC4_128_MD5" },
new String[] { "TLSv1" }, true)
);
users.put("gabesz", new User("gabesz"));
users.put("kovacsz", new User("kovacsz"));
users.put("dgyimesi", new User("dgyimesi"));
users.put("testuser", new User("testuser"));
}
/** <p> Check for user <code>username</code> in </code>users</code> for access control. </p> */
public boolean login(String username) throws java.rmi.RemoteException {
String clientHost = "";
try {
clientHost = getClientHost();
logger.info("CONNECTION of user " + username + " was successful from address " + clientHost);
}
catch (Exception e) {
logger.warning("EXCEPTION during NBOClient lookup: \n" + e.getStackTrace());
}
if (users.get(username) == null) {
logger.warning("LOGIN of " + username + "from address "+ clientHost + " was failed. User not registered!");
return false;
}
return true;
}
/** <p> Create an <code>SimpleMPSSolver</code> as a solver thread and starts it. </p> */
public void compute(String username, String problemName, HashMap<String, String> inputFiles, int inputType) throws java.rmi.RemoteException {
HashMap<String, NBOPlugin> threads = (users.get(username).getThreads());
NBOPlugin thread = null;
int uniqueHash = Integer.parseInt(inputFiles.get("properties.txt").split("hashcode: ")[1].split("\n")[0]);
if (inputType == NBOPlugin.LP)
thread = new SimpleMPSSolver(users.get(username), problemName, inputFiles);
if (inputType == NBOPlugin.MILP)
thread = new MILPSolver(users.get(username), problemName, inputFiles);
if (inputType == NBOPlugin.GEOM)
thread = new GEOMSolver(users.get(username), problemName, inputFiles);
if (inputType == NBOPlugin.RES_ALLOC)
thread = new ResourceAllocationSolver(users.get(username), problemName, inputFiles);
if (thread != null) {
thread.setName("ServerThread of " + username + "_" + uniqueHash);
threads.put(problemName, thread);
(threads.get(problemName)).start();
}
logger.info("THREAD (" + thread.getName() + ") started for " + username + "'s problem " + problemName + ".");
return;
}
/** <p> Give state information about <code>username</code>'s <code>problem</code>. */
public HashMap<Integer, Result> isReady(String username, String problem, int uniqueHash) throws java.rmi.RemoteException {
User user = users.get(username);
boolean isAlive = user.getThreads().get(problem).isAlive();
HashMap<Integer, Result> newResults = (users.get(username)).getNewResults();
if (!isAlive) {
logger.info("THREAD (" + user.getThreads().get(problem).getName() + ") ended.");
return newResults;
}
return null;
}
/** <p> Give information about <code>username</code>'s <code>problem</code>. */
public HashMap<Integer, String> getLog(String username, String problem, int uniqueHash) throws java.rmi.RemoteException {
User user = users.get(username);
boolean isAlive = user.getThreads().get(problem).isAlive();
HashMap<Integer, String> newLogs = (users.get(username)).getLogs();
if (!isAlive) {
return newLogs;
}
return null;
}
public String echo(String message) throws java.rmi.RemoteException {
return message;
}
public static boolean getSslRmiRegistyIsAlive() {
return NBOServer.sslRmiRegistryIsAlive;
}
public static void setSslRmiRegistryIsAlive(boolean bol) {
sslRmiRegistryIsAlive = bol;
}
public ArrayList<String> getSolvers() {
ArrayList<String> solvers = new ArrayList<String>();
String curDir = System.getProperty("user.dir");
File dir = new File(curDir + File.separator + "hu" + File.separator +
"u_szeged" + File.separator + "nbo" + File.separator + "server" +
File.separator + "plugins");
String[] children = dir.list();
if (children == null) {
return null;
}
else {
for (int i = 0; i < children.length; i++) {
String filename = children[i];
if (filename.endsWith("Solver.class")) {
solvers.add(filename);
}
}
}
return solvers;
}
public void manage(String command) {
System.out.println("Not implemented yet!");
}
public static void log(String msg, int type) {
switch(type){
case 1:
logger.info(msg);
break;
case 2:
logger.severe(msg);
}
}
public static void main(String[] args) {
try {
String systemLogPath = "log/system/";
SimpleTimeZone ect = new SimpleTimeZone(1, "ECT");
ect.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
ect.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
Calendar calendar = new GregorianCalendar(ect);
Date date = new Date();
calendar.setTime(date);
systemLogPath += ((calendar.get(Calendar.MONTH) + 1) < 10 ? "0" + (calendar.get(Calendar.MONTH) + 1)
: (calendar.get(Calendar.MONTH) + 1)) + "" + (calendar.get(Calendar.DATE) < 10 ? "0" +
calendar.get(Calendar.DATE) : calendar.get(Calendar.DATE)) + "" + calendar.get(Calendar.YEAR) +
"_" + (calendar.get(Calendar.HOUR_OF_DAY) + 1) + "-" + calendar.get(Calendar.MINUTE) +
"-" + calendar.get(Calendar.SECOND) + ".log";
System.out.println("LOG directed to " + systemLogPath);
fileHandler = new FileHandler(systemLogPath);
fileHandler.setFormatter(new SimpleFormatter());
logger.addHandler(fileHandler);
if (args.length == 0) {
logger.severe("HOST is missing. Please specify host! Exiting...");
System.exit(0);
}
NBOServer server = new NBOServer();
String host = args[0];
// this thread provides the registry service
sslRmiRegistry = new SSLRMIRegistry();
sslRmiRegistry.start();
// wait until SslRmiregistry creates the registry
while (!getSslRmiRegistyIsAlive()) { }
server.registry = LocateRegistry.getRegistry(host, 43000, new SslRMIClientSocketFactory());
server.registry.rebind("NBOServer", server);
logger.info("SERVER (NBOServer) started.");
}
catch(Exception e) {
logger.severe("Faliure in main! \nThe server terminated with exception:\n" + e);
}
}
}