Java tutorial
/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.airavata.server; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.List; import org.apache.airavata.common.exception.ApplicationSettingsException; import org.apache.airavata.common.utils.AiravataUtils; import org.apache.airavata.common.utils.ApplicationSettings.ShutdownStrategy; import org.apache.airavata.common.utils.IServer; import org.apache.airavata.common.utils.IServer.ServerStatus; import org.apache.airavata.common.utils.ServerSettings; import org.apache.airavata.common.utils.StringUtil; import org.apache.airavata.common.utils.StringUtil.CommandLineParameters; import org.apache.commons.cli.ParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ServerMain { private static List<IServer> servers; private static final String SERVERS_KEY = "servers"; private final static Logger logger = LoggerFactory.getLogger(ServerMain.class); private static boolean serversLoaded = false; private static final String stopFileNamePrefix = "airavata-server-stop"; private static int serverPID = -1; private static final String serverStartedFileNamePrefix = "server-start"; private static boolean systemShutDown = false; private static String STOP_COMMAND_STR = "stop"; // private static boolean shutdownHookCalledBefore=false; static { servers = new ArrayList<IServer>(); } private static void loadServers() { try { String serversString = ServerSettings.getSetting(SERVERS_KEY); if (serversString != null) { String[] serversList = serversString.split(","); for (String serverString : serversList) { serverString = serverString.trim(); String serverClassName = ServerSettings.getSetting(serverString); Class<?> classInstance; try { classInstance = ServerMain.class.getClassLoader().loadClass(serverClassName); servers.add((IServer) classInstance.newInstance()); } catch (ClassNotFoundException e) { logger.error("Error while locating server implementation \"" + serverString + "\"!!!", e); } catch (InstantiationException e) { logger.error("Error while initiating server instance \"" + serverString + "\"!!!", e); } catch (IllegalAccessException e) { logger.error("Error while initiating server instance \"" + serverString + "\"!!!", e); } catch (ClassCastException e) { logger.error("Invalid server \"" + serverString + "\"!!!", e); } } } } catch (ApplicationSettingsException e) { logger.error("Error while retrieving server list!!!", e); } serversLoaded = true; Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { setSystemShutDown(true); stopAllServers(); } }); } // private static void addSecondaryShutdownHook(){ // Runtime.getRuntime().addShutdownHook(new Thread(){ // @Override // public void run() { // System.out.print("Graceful shutdown attempt is still active. Do you want to exit instead? (y/n)"); // String command=System.console().readLine().trim().toLowerCase(); // if (command.equals("yes") || command.equals("y")){ // System.exit(1); // } // } // }); // } public static void main(String args[]) throws ParseException, IOException { // Properties properties = System.getProperties(); // for (Object key : properties.keySet()) { // System.out.println(key.toString()+" = "+properties.get(key)); // } // Map<String, String> env = System.getenv(); // // for (Object key : env.keySet()) { // System.out.println(key.toString()+" = "+env.get(key)); // } // if (true){ // return; // } AiravataUtils.setExecutionAsServer(); CommandLineParameters commandLineParameters = StringUtil.getCommandLineParser(args); if (commandLineParameters.getArguments().contains(STOP_COMMAND_STR)) { performServerStopRequest(commandLineParameters); } else { performServerStart(args); } } private static void performServerStart(String[] args) { setServerStarted(); logger.info("Airavata server instance starting..."); ServerSettings.mergeSettingsCommandLineArgs(args); startAllServers(); while (!hasStopRequested()) { try { Thread.sleep(2000); } catch (InterruptedException e) { stopAllServers(); } } if (hasStopRequested()) { ServerSettings.setStopAllThreads(true); stopAllServers(); ShutdownStrategy shutdownStrategy; try { shutdownStrategy = ServerSettings.getShutdownStrategy(); } catch (Exception e) { String strategies = ""; for (ShutdownStrategy s : ShutdownStrategy.values()) { strategies += "/" + s.toString(); } logger.warn(e.getMessage()); logger.warn("Valid shutdown options are : " + strategies.substring(1)); shutdownStrategy = ShutdownStrategy.SELF_TERMINATE; } if (shutdownStrategy == ShutdownStrategy.SELF_TERMINATE) { System.exit(0); } } } private static void performServerStopRequest(CommandLineParameters commandLineParameters) throws IOException { // deleteOldStartRecords(); String serverIndexOption = "serverIndex"; if (commandLineParameters.getParameters().containsKey(serverIndexOption)) { serverPID = Integer.parseInt(commandLineParameters.getParameters().get(serverIndexOption)); } if (isServerRunning()) { logger.info("Requesting airavata server" + (serverPID == -1 ? "(s)" : " instance " + serverPID) + " to stop..."); requestStop(); while (isServerRunning()) { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } logger.info("Server" + (serverPID == -1 ? "(s)" : " instance " + serverPID) + " stopped!!!"); } else { logger.error("Server" + (serverPID == -1 ? "" : " instance " + serverPID) + " is not running!!!"); } } @SuppressWarnings("resource") private static void requestStop() throws IOException { File file = new File(getServerStopFileName()); file.createNewFile(); new RandomAccessFile(file, "rw").getChannel().lock(); file.deleteOnExit(); } private static boolean hasStopRequested() { return isSystemShutDown() || new File(getServerStopFileName()).exists() || new File(stopFileNamePrefix).exists(); } private static String getServerStopFileName() { return stopFileNamePrefix; } private static void deleteOldStopRequests() { File[] files = new File(".").listFiles(); for (File file : files) { if (file.getName().contains(stopFileNamePrefix)) { file.delete(); } } } // private static void deleteOldStartRecords(){ // File[] files = new File(".").listFiles(); // for (File file : files) { // if (file.getName().contains(serverStartedFileNamePrefix)){ // try { // new FileOutputStream(file); // file.delete(); // } catch (Exception e) { // //file is locked which means there's an active process using it // } // } // } // } private static boolean isServerRunning() { if (serverPID == -1) { String[] files = new File(".").list(); for (String file : files) { if (file.contains(serverStartedFileNamePrefix)) { return true; } } return false; } else { return new File(getServerStartedFileName()).exists(); } } @SuppressWarnings({ "resource" }) private static void setServerStarted() { try { serverPID = getPID(); deleteOldStopRequests(); File serverStartedFile = null; serverStartedFile = new File(getServerStartedFileName()); serverStartedFile.createNewFile(); serverStartedFile.deleteOnExit(); new RandomAccessFile(serverStartedFile, "rw").getChannel().lock(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static String getServerStartedFileName() { return new File(new File(System.getenv("AIRAVATA_HOME"), "bin"), serverStartedFileNamePrefix + "_" + Integer.toString(serverPID)).toString(); } public static void stopAllServers() { //stopping should be done in reverse order of starting the servers for (int i = servers.size() - 1; i >= 0; i--) { try { servers.get(i).stop(); waitForServerToStop(servers.get(i), null); } catch (Exception e) { logger.error("Server Stop Error:", e); } } } public static void startAllServers() { if (!serversLoaded) { loadServers(); } for (IServer server : servers) { try { server.configure(); server.start(); waitForServerToStart(server, null); } catch (Exception e) { logger.error("Server Start Error:", e); } } } private static final int SERVER_STATUS_CHANGE_WAIT_INTERVAL = 100; private static void waitForServerToStart(IServer server, Integer maxWait) throws Exception { int count = 0; // if (server.getStatus()==ServerStatus.STARTING) { // logger.info("Waiting for " + server.getName() + " to start..."); // } while (server.getStatus() == ServerStatus.STARTING && (maxWait == null || count < maxWait)) { Thread.sleep(SERVER_STATUS_CHANGE_WAIT_INTERVAL); count += SERVER_STATUS_CHANGE_WAIT_INTERVAL; } if (server.getStatus() != ServerStatus.STARTED) { throw new Exception("The " + server.getName() + " did not start!!!"); } } private static void waitForServerToStop(IServer server, Integer maxWait) throws Exception { int count = 0; if (server.getStatus() == ServerStatus.STOPING) { logger.info("Waiting for " + server.getName() + " to stop..."); } //we are doing hasStopRequested() check because while we are stuck in the loop to stop there could be a forceStop request while (server.getStatus() == ServerStatus.STOPING && (maxWait == null || count < maxWait)) { Thread.sleep(SERVER_STATUS_CHANGE_WAIT_INTERVAL); count += SERVER_STATUS_CHANGE_WAIT_INTERVAL; } if (server.getStatus() != ServerStatus.STOPPED) { throw new Exception("Error stopping the " + server.getName() + "!!!"); } } private static boolean isSystemShutDown() { return systemShutDown; } private static void setSystemShutDown(boolean systemShutDown) { ServerMain.systemShutDown = systemShutDown; } private static int getPID() { try { java.lang.management.RuntimeMXBean runtime = java.lang.management.ManagementFactory.getRuntimeMXBean(); java.lang.reflect.Field jvm = runtime.getClass().getDeclaredField("jvm"); jvm.setAccessible(true); sun.management.VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); java.lang.reflect.Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); pid_method.setAccessible(true); int pid = (Integer) pid_method.invoke(mgmt); return pid; } catch (Exception e) { return -1; } } }