package org.radargun.utils; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; import org.radargun.RemoteSlaveConnection; import org.radargun.ShutDownHook; import org.radargun.logging.Log; import org.radargun.logging.LogFactory; /** * <p>Holder for input arguments of {@link org.radargun.LaunchMaster} and {@link org.radargun.Slave}.</p> * * <p>Supported arguments - {@link org.radargun.Slave}: * <ul><li>Master host (required) & port (optional, defaults to 2103): -master 127.0.0.1:2101</li> * <li>Slave index (optional): -slaveIndex 1</li></ul></p> * * <p>Supported arguments - {@link org.radargun.LaunchMaster}: * <ul><li>Benchmark's config file (required): -config /path/to/config.xml</li> * <li>Location of reporter's dir (optional): --add-reporter=/path/to/custom-reporter</li></ul></p> * * <p>Supported arguments - applicable for {@link org.radargun.Slave} (clustered mode) * and {@link org.radargun.LaunchMaster} (local mode): * <ul><li>Location of plugin dir (containing conf and lib folders, optional): --add-plugin=/path/to/custom-plugin</li> * <li>Location of configuration file (optional): --add-config=custom-plugin:/path/to/custom-plugin.xml</li></ul></p> * * * @author Matej Cimbora <mcimbora@redhat.com> */ public class ArgsHolder { private static Log log = LogFactory.getLog(ArgsHolder.class); protected static final String CONFIG = "--config"; protected static final String ADD_REPORTER = "--add-reporter"; protected static final String ADD_PLUGIN = "--add-plugin"; protected static final String ADD_CONFIG = "--add-config"; protected static final String DEFAULT_VM_ARG = "--default-vm-arg"; protected static final String TEMP_CONFIG_DIR = "--temp-config-dir"; protected static final String UUID = "--uuid"; protected static final String CURRENT_PLUGIN = "--current-plugin"; protected static final String SLAVE_INDEX = "--slaveIndex"; protected static final String MASTER = "--master"; private static String configFile; private static String masterHost; private static int masterPort = RemoteSlaveConnection.DEFAULT_PORT; private static int slaveIndex = -1; private static UUID uuid; private static String tempConfigDir; private static String currentPlugin; private static List<String> defaultVmArgs = new ArrayList<>(); private static Map<String, PluginParam> pluginParams = new HashMap<>(); private static List<String> reporterPaths = new ArrayList<>(); private ArgsHolder() { } /** * Initializes ArgsHolder * * @param args input arguments * @param type type of argument (LAUNCH_MASTER, SLAVE) */ public static void init(String[] args, ArgType type) { LinkedList<String> argList = new LinkedList<>(Arrays.asList(args)); while (!argList.isEmpty()) { String arg = argList.removeFirst(); // change --foo=bar into --foo bar int index = arg.indexOf('='); if (index >= 0) { argList.addFirst(arg.substring(index + 1)); arg = arg.substring(0, index); } String param; if (ArgType.SLAVE == type) { switch (arg) { case "-master": log.warn("Switch -master is deprecated. Use --master instead."); case MASTER: param = nextArg(arg, argList); if (param.contains(":")) { masterHost = param.substring(0, param.indexOf(":")); try { masterPort = Integer.parseInt(param.substring(param.indexOf(":") + 1)); } catch (NumberFormatException nfe) { log.error("Unable to parse port part of the master! Failing!"); ShutDownHook.exit(127); } } else { masterHost = param; } break; case "-slaveIndex": log.warn("Switch -slaveIndex is deprecated. Use --slaveIndex instead."); case SLAVE_INDEX: param = nextArg(arg, argList); try { slaveIndex = Integer.parseInt(param); } catch (NumberFormatException nfe) { log.errorf("Unable to parse slaveIndex! Failing!"); ShutDownHook.exit(127); } break; case UUID: param = nextArg(arg, argList); try { uuid = java.util.UUID.fromString(param); } catch (IllegalArgumentException nfe) { log.errorf("Unable to parse UUID %s! Failing!", param); ShutDownHook.exit(127); } break; case TEMP_CONFIG_DIR: tempConfigDir = nextArg(arg, argList); break; case CURRENT_PLUGIN: currentPlugin = nextArg(arg, argList); break; case DEFAULT_VM_ARG: defaultVmArgs.add(nextArg(arg, argList)); break; default: processCommonArgs(arg, argList, type); } } if (ArgType.LAUNCH_MASTER == type) { switch (arg) { case "-config": log.warn("Switch -config is deprecated. Use --config instead."); case CONFIG: configFile = nextArg(arg, argList); break; case ADD_REPORTER: reporterPaths.add(nextArg(arg, argList)); break; default: processCommonArgs(arg, argList, type); } } } // when no default VM arguments are specified, we take all arguments assigned to VM // as default ones if (defaultVmArgs.isEmpty()) { defaultVmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments(); } } private static String nextArg(String arg, LinkedList<String> argList) { if (argList.isEmpty()) { log.errorf("%s requires an argument!", arg); ShutDownHook.exit(127); } return argList.removeFirst(); } private static void processCommonArgs(String arg, LinkedList<String> argList, ArgType type) { String param, pluginName; PluginParam pluginParam; switch (arg) { case ADD_PLUGIN: param = Utils.sanitizePath(nextArg(arg, argList)); pluginName = param.substring(param.lastIndexOf("/") + 1, param.length()); pluginParam = pluginParams.get(pluginName); if (pluginParam == null) { pluginParams.put(pluginName, pluginParam = new PluginParam()); } pluginParam.setPath(param); break; case ADD_CONFIG: param = nextArg(arg, argList); pluginName = param.substring(0, param.indexOf(":")); String configPath = param.substring(param.indexOf(":") + 1, param.length()); configPath = Utils.sanitizePath(configPath); pluginParam = pluginParams.get(pluginName); if (pluginParam == null) { pluginParams.put(pluginName, pluginParam = new PluginParam()); } pluginParam.getConfigFiles().add(configPath); break; default: printUsageAndExit(type); } } public static void printUsageAndExit(ArgType type) { if (ArgType.SLAVE == type) { printSlaveUsageAndExit(); } else if (ArgType.LAUNCH_MASTER == type) { printMasterUsageAndExit(); } } private static void printMasterUsageAndExit() { System.out.println("Usage: master.sh --config <config-file.xml>"); System.out.println(" --config : xml file containing benchmark's configuration"); ShutDownHook.exit(127); } private static void printSlaveUsageAndExit() { System.out.println("Usage: slave.sh --master <host>:port"); System.out.println(" --master: The host(and optional port) on which the master resides. If port is missing it defaults to " + RemoteSlaveConnection.DEFAULT_PORT); ShutDownHook.exit(127); } public static enum ArgType { LAUNCH_MASTER, SLAVE } public static class PluginParam { private String path; private List<String> configFiles = new ArrayList<>(); public String getPath() { return path; } public void setPath(String path) { this.path = path; } public List<String> getConfigFiles() { return configFiles; } } public static String getConfigFile() { return configFile; } public static String getMasterHost() { return masterHost; } public static int getMasterPort() { return masterPort; } public static int getSlaveIndex() { return slaveIndex; } public static UUID getUuid() { return uuid; } public static Map<String, PluginParam> getPluginParams() { return Collections.unmodifiableMap(pluginParams); } public static List<String> getReporterPaths() { return Collections.unmodifiableList(reporterPaths); } public static String getTempConfigDir() { return tempConfigDir; } public static String getCurrentPlugin() { return currentPlugin; } public static void setCurrentPlugin(String currentPlugin) { ArgsHolder.currentPlugin = currentPlugin; } public static List<String> getDefaultVmArgs() { return defaultVmArgs; } }