/* * Copyright 2012, Facebook, Inc. * * Licensed 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 com.facebook.LinkBench; import java.io.File; import java.io.IOException; import java.util.Properties; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.EnhancedPatternLayout; import org.apache.log4j.FileAppender; import org.apache.log4j.Layout; import org.apache.log4j.Level; import org.apache.log4j.Logger; public class ConfigUtil { public static final String linkbenchHomeEnvVar = "LINKBENCH_HOME"; public static final String LINKBENCH_LOGGER = "com.facebook.linkbench"; /** * @return null if not set, or if not valid path */ public static String findLinkBenchHome() { String linkBenchHome = System.getenv("LINKBENCH_HOME"); if (linkBenchHome != null && linkBenchHome.length() > 0) { File dir = new File(linkBenchHome); if (dir.exists() && dir.isDirectory()) { return linkBenchHome; } } return null; } public static Level getDebugLevel(Properties props) throws LinkBenchConfigError { if (props == null) { return Level.DEBUG; } String levStr = props.getProperty(Config.DEBUGLEVEL); if (levStr == null) { return Level.DEBUG; } try { int level = Integer.parseInt(levStr); if (level <= 0) { return Level.INFO; } else if (level == 1) { return Level.DEBUG; } else { return Level.TRACE; } } catch (NumberFormatException e) { Level lev = Level.toLevel(levStr, null); if (lev != null) { return lev; } else { throw new LinkBenchConfigError("Invalid setting for debug level: " + levStr); } } } /** * Setup log4j to log to stderr with a timestamp and thread id * Could add in configuration from file later if it was really necessary * @param props * @param logFile if not null, info logging will be diverted to this file * @throws IOException * @throws Exception */ public static void setupLogging(Properties props, String logFile) throws LinkBenchConfigError, IOException { Layout fmt = new EnhancedPatternLayout("%p %d [%t]: %m%n%throwable{30}"); Level logLevel = ConfigUtil.getDebugLevel(props); Logger.getRootLogger().removeAllAppenders(); Logger lbLogger = Logger.getLogger(LINKBENCH_LOGGER); lbLogger.setLevel(logLevel); ConsoleAppender console = new ConsoleAppender(fmt, "System.err"); /* If logfile is specified, put full stream in logfile and only * print important messages to terminal */ if (logFile != null) { console.setThreshold(Level.WARN); // Only print salient messages lbLogger.addAppender(new FileAppender(fmt, logFile)); } lbLogger.addAppender(console); } /** * Look up key in props, failing if not present * @param props * @param key * @return * @throws LinkBenchConfigError thrown if key not present */ public static String getPropertyRequired(Properties props, String key) throws LinkBenchConfigError { String v = props.getProperty(key); if (v == null) { throw new LinkBenchConfigError("Expected configuration key " + key + " to be defined"); } return v; } public static int getInt(Properties props, String key) throws LinkBenchConfigError { return getInt(props, key, null); } /** * Retrieve a config key and convert to integer * @param props * @param key * @return a non-null string value * @throws LinkBenchConfigError if not present or not integer */ public static int getInt(Properties props, String key, Integer defaultVal) throws LinkBenchConfigError { if (defaultVal != null && !props.containsKey(key)) { return defaultVal; } String v = getPropertyRequired(props, key); try { return Integer.parseInt(v); } catch (NumberFormatException e) { throw new LinkBenchConfigError("Expected configuration key " + key + " to be integer, but was '" + v + "'"); } } public static long getLong(Properties props, String key) throws LinkBenchConfigError { return getLong(props, key, null); } /** * Retrieve a config key and convert to long integer * @param props * @param key * @param defaultVal default value if key not present * @return * @throws LinkBenchConfigError if not present or not integer */ public static long getLong(Properties props, String key, Long defaultVal) throws LinkBenchConfigError { if (defaultVal != null && !props.containsKey(key)) { return defaultVal; } String v = getPropertyRequired(props, key); try { return Long.parseLong(v); } catch (NumberFormatException e) { throw new LinkBenchConfigError("Expected configuration key " + key + " to be long integer, but was '" + v + "'"); } } public static double getDouble(Properties props, String key) throws LinkBenchConfigError { return getDouble(props, key, null); } /** * Retrieve a config key and convert to double * @param props * @param key * @param defaultVal default value if key not present * @return * @throws LinkBenchConfigError if not present or not double */ public static double getDouble(Properties props, String key, Double defaultVal) throws LinkBenchConfigError { if (defaultVal != null && !props.containsKey(key)) { return defaultVal; } String v = getPropertyRequired(props, key); try { return Double.parseDouble(v); } catch (NumberFormatException e) { throw new LinkBenchConfigError("Expected configuration key " + key + " to be double, but was '" + v + "'"); } } /** * Retrieve a config key and convert to boolean. * Valid boolean strings are "true" or "false", case insensitive * @param props * @param key * @return * @throws LinkBenchConfigError if not present or not boolean */ public static boolean getBool(Properties props, String key) throws LinkBenchConfigError { return getBool(props, key, null); } public static boolean getBool(Properties props, String key, Boolean defaultVal) throws LinkBenchConfigError { if (defaultVal != null && !props.containsKey(key)) { return defaultVal; } String v = getPropertyRequired(props, key).trim().toLowerCase(); // Parse manually since parseBoolean accepts many things as "false" if (v.equals("true")) { return true; } else if (v.equals("false")) { return false; } else { throw new LinkBenchConfigError("Expected configuration key " + key + " to be true or false, but was '" + v + "'"); } } }