/** * 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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.alibaba.jstorm.yarn.utils; import org.apache.commons.exec.*; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.thrift.TFieldIdEnum; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.management.ObjectName; import java.io.*; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * JStorm utility * * @author yannian/Longda/Xin.Zhou/Xin.Li */ public class JStormUtils { private static final Logger LOG = LoggerFactory.getLogger(JStormUtils.class); public static long SIZE_1_K = 1024; public static long SIZE_1_M = SIZE_1_K * 1024; public static long SIZE_1_G = SIZE_1_M * 1024; public static long SIZE_1_T = SIZE_1_G * 1024; public static long SIZE_1_P = SIZE_1_T * 1024; public static final int MIN_1 = 60; public static final int MIN_30 = MIN_1 * 30; public static final int HOUR_1 = MIN_30 * 2; public static final int DAY_1 = HOUR_1 * 24; public static String getErrorInfo(String baseInfo, Exception e) { try { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); return baseInfo + "\r\n" + sw.toString() + "\r\n"; } catch (Exception e2) { return baseInfo; } } public static String getErrorInfo(Throwable error) { try { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); error.printStackTrace(pw); return sw.toString(); } catch (Exception e1) { return ""; } } /** * filter the map * * @param filter * @param all * @return */ public static <K, V> Map<K, V> select_keys_pred(Set<K> filter, Map<K, V> all) { Map<K, V> filterMap = new HashMap<K, V>(); for (Entry<K, V> entry : all.entrySet()) { if (!filter.contains(entry.getKey())) { filterMap.put(entry.getKey(), entry.getValue()); } } return filterMap; } public static byte[] barr(byte v) { byte[] byteArray = new byte[1]; byteArray[0] = v; return byteArray; } public static byte[] barr(Short v) { byte[] byteArray = new byte[Short.SIZE / 8]; for (int i = 0; i < byteArray.length; i++) { int off = (byteArray.length - 1 - i) * 8; byteArray[i] = (byte) ((v >> off) & 0xFF); } return byteArray; } public static byte[] barr(Integer v) { byte[] byteArray = new byte[Integer.SIZE / 8]; for (int i = 0; i < byteArray.length; i++) { int off = (byteArray.length - 1 - i) * 8; byteArray[i] = (byte) ((v >> off) & 0xFF); } return byteArray; } // for test public static int byteToInt2(byte[] b) { int iOutcome = 0; byte bLoop; for (int i = 0; i < 4; i++) { bLoop = b[i]; int off = (b.length - 1 - i) * 8; iOutcome += (bLoop & 0xFF) << off; } return iOutcome; } /** * LocalMode variable isn't clean, it make the JStormUtils ugly */ public static boolean localMode = false; public static boolean isLocalMode() { return localMode; } public static void setLocalMode(boolean localMode) { JStormUtils.localMode = localMode; } public static void haltProcess(int val) { Runtime.getRuntime().halt(val); } public static void halt_process(int val, String msg) { LOG.info("Halting process: " + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { } if (localMode && val == 0) { // throw new RuntimeException(msg); } else { haltProcess(val); } } /** * "{:a 1 :b 1 :c 2} -> {1 [:a :b] 2 :c}" * * @param map * @return */ public static <K, V> HashMap<V, List<K>> reverse_map(Map<K, V> map) { HashMap<V, List<K>> rtn = new HashMap<V, List<K>>(); if (map == null) { return rtn; } for (Entry<K, V> entry : map.entrySet()) { K key = entry.getKey(); V val = entry.getValue(); List<K> list = rtn.get(val); if (list == null) { list = new ArrayList<K>(); rtn.put(entry.getValue(), list); } list.add(key); } return rtn; } /** * Gets the pid of this JVM, because Java doesn't provide a real way to do this. * * @return */ public static String process_pid() { String name = ManagementFactory.getRuntimeMXBean().getName(); String[] split = name.split("@"); if (split.length != 2) { throw new RuntimeException("Got unexpected process name: " + name); } return split[0]; } /** * All exe command will go launchProcess * * @param command * @throws ExecuteException * @throws IOException */ public static void exec_command(String command) throws ExecuteException, IOException { launchProcess(command, new HashMap<String, String>(), false); } /** * Extra dir from the jar to destdir * * @param jarpath * @param dir * @param destdir */ public static void extractDirFromJar(String jarpath, String dir, String destdir) { ZipFile zipFile = null; try { zipFile = new ZipFile(jarpath); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries != null && entries.hasMoreElements()) { ZipEntry ze = entries.nextElement(); if (!ze.isDirectory() && ze.getName().startsWith(dir)) { InputStream in = zipFile.getInputStream(ze); try { File file = new File(destdir, ze.getName()); if (!file.getParentFile().mkdirs()) { if (!file.getParentFile().isDirectory()) { throw new IOException("Mkdirs failed to create " + file.getParentFile().toString()); } } OutputStream out = new FileOutputStream(file); try { byte[] buffer = new byte[8192]; int i; while ((i = in.read(buffer)) != -1) { out.write(buffer, 0, i); } } finally { out.close(); } } finally { if (in != null) in.close(); } } } } catch (Exception e) { LOG.warn("No " + dir + " from " + jarpath + "!\n" + e.getMessage()); } finally { if (zipFile != null) try { zipFile.close(); } catch (Exception e) { LOG.warn(e.getMessage()); } } } public static void ensure_process_killed(Integer pid) { // in this function, just kill the process 5 times // make sure the process be killed definitely for (int i = 0; i < 5; i++) { try { exec_command("kill -9 " + pid); LOG.info("kill -9 process " + pid); sleepMs(100); } catch (ExecuteException e) { LOG.info("Error when trying to kill " + pid + ". Process has been killed"); } catch (Exception e) { LOG.info("Error when trying to kill " + pid + ".Exception ", e); } } } public static void process_killed(Integer pid) { try { exec_command("kill " + pid); LOG.info("kill process " + pid); } catch (ExecuteException e) { LOG.info("Error when trying to kill " + pid + ". Process has been killed. "); } catch (Exception e) { LOG.info("Error when trying to kill " + pid + ".Exception ", e); } } public static void kill(Integer pid) { process_killed(pid); sleepMs(5 * 1000); ensure_process_killed(pid); } public static void kill_signal(Integer pid, String signal) { String cmd = "kill " + signal + " " + pid; try { exec_command(cmd); LOG.info(cmd); } catch (ExecuteException e) { LOG.info("Error when run " + cmd + ". Process has been killed. "); } catch (Exception e) { LOG.info("Error when run " + cmd + ". Exception ", e); } } /** * This function is only for linux * * @param pid * @return */ public static boolean isProcDead(String pid) { if (OSInfo.isLinux() == false) { return false; } String path = "/proc/" + pid; File file = new File(path); if (file.exists() == false) { LOG.info("Process " + pid + " is dead"); return true; } return false; } /** * If it is backend, please set resultHandler, such as DefaultExecuteResultHandler If it is frontend, ByteArrayOutputStream.toString get the result * <p/> * This function don't care whether the command is successfully or not * * @param command * @param environment * @param workDir * @param resultHandler * @return * @throws IOException */ @Deprecated public static ByteArrayOutputStream launchProcess(String command, final Map environment, final String workDir, ExecuteResultHandler resultHandler) throws IOException { String[] cmdlist = command.split(" "); CommandLine cmd = new CommandLine(cmdlist[0]); for (String cmdItem : cmdlist) { if (StringUtils.isBlank(cmdItem) == false) { cmd.addArgument(cmdItem); } } DefaultExecutor executor = new DefaultExecutor(); executor.setExitValue(0); if (StringUtils.isBlank(workDir) == false) { executor.setWorkingDirectory(new File(workDir)); } ByteArrayOutputStream out = new ByteArrayOutputStream(); PumpStreamHandler streamHandler = new PumpStreamHandler(out, out); if (streamHandler != null) { executor.setStreamHandler(streamHandler); } try { if (resultHandler == null) { executor.execute(cmd, environment); } else { executor.execute(cmd, environment, resultHandler); } } catch (ExecuteException e) { // @@@@ // failed to run command } return out; } protected static Process launchProcess(final List<String> cmdlist, final Map<String, String> environment) throws IOException { ProcessBuilder builder = new ProcessBuilder(cmdlist); builder.redirectErrorStream(true); Map<String, String> process_evn = builder.environment(); for (Entry<String, String> entry : environment.entrySet()) { process_evn.put(entry.getKey(), entry.getValue()); } return builder.start(); } public static String getOutput(InputStream input) { BufferedReader in = new BufferedReader(new InputStreamReader(input)); StringBuilder sb = new StringBuilder(); String line; try { while ((line = in.readLine()) != null) { sb.append(line).append("\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } public static String launchProcess(final String command, final List<String> cmdlist, final Map<String, String> environment, boolean backend) throws IOException { if (backend) { new Thread(new Runnable() { @Override public void run() { List<String> cmdWrapper = new ArrayList<String>(); cmdWrapper.add("nohup"); cmdWrapper.addAll(cmdlist); cmdWrapper.add("&"); try { launchProcess(cmdWrapper, environment); } catch (IOException e) { LOG.error("Failed to run nohup " + command + " &," + e.getCause(), e); } } }).start(); return null; } else { try { Process process = launchProcess(cmdlist, environment); StringBuilder sb = new StringBuilder(); String output = JStormUtils.getOutput(process.getInputStream()); String errorOutput = JStormUtils.getOutput(process.getErrorStream()); sb.append(output); sb.append("\n"); sb.append(errorOutput); int ret = process.waitFor(); if (ret != 0) { LOG.warn(command + " is terminated abnormally. ret={}, str={}", ret, sb.toString()); } return sb.toString(); } catch (Throwable e) { LOG.error("Failed to run " + command + ", " + e.getCause(), e); } return ""; } } /** * Attention * * All launchProcess should go this function * * it should use DefaultExecutor to start a process, * but some little problem have been found, * such as exitCode/output string so still use the old method to start process * * @param command * @param environment * @param backend * @return outputString * @throws IOException */ public static String launchProcess(final String command, final Map<String, String> environment, boolean backend) throws IOException { String[] cmds = command.split(" "); ArrayList<String> cmdList = new ArrayList<String>(); for (String tok : cmds) { if (!StringUtils.isBlank(tok)) { cmdList.add(tok); } } return launchProcess(command, cmdList, environment, backend); } public static String current_classpath() { return System.getProperty("java.class.path"); } public static <V> HashMap<V, Integer> multi_set(List<V> list) { HashMap<V, Integer> rtn = new HashMap<V, Integer>(); for (V v : list) { int cnt = 1; if (rtn.containsKey(v)) { cnt += rtn.get(v); } rtn.put(v, cnt); } return rtn; } /** * if the list exist repeat string, return the repeated string * <p/> * this function will be used to check wheter bolt or spout exist same id */ public static List<String> getRepeat(List<String> list) { List<String> rtn = new ArrayList<String>(); Set<String> idSet = new HashSet<String>(); for (String id : list) { if (idSet.contains(id)) { rtn.add(id); } else { idSet.add(id); } } return rtn; } /** * balance all T * * @param <T> * @param splitup * @return */ public static <T> List<T> interleave_all(List<List<T>> splitup) { ArrayList<T> rtn = new ArrayList<T>(); int maxLength = 0; for (List<T> e : splitup) { int len = e.size(); if (maxLength < len) { maxLength = len; } } for (int i = 0; i < maxLength; i++) { for (List<T> e : splitup) { if (e.size() > i) { rtn.add(e.get(i)); } } } return rtn; } public static long bit_xor_vals(Object... vals) { long rtn = 0l; for (Object n : vals) { rtn = bit_xor(rtn, n); } return rtn; } public static <T> long bit_xor_vals(List<T> vals) { long rtn = 0l; for (T n : vals) { rtn = bit_xor(rtn, n); } return rtn; } public static <T> long bit_xor_vals_sets(Set<T> vals) { long rtn = 0l; for (T n : vals) { rtn = bit_xor(rtn, n); } return rtn; } public static long bit_xor(Object a, Object b) { long rtn; if (a instanceof Long && b instanceof Long) { rtn = ((Long) a) ^ ((Long) b); return rtn; } else if (b instanceof Set) { long bs = bit_xor_vals_sets((Set) b); return bit_xor(a, bs); } else if (a instanceof Set) { long as = bit_xor_vals_sets((Set) a); return bit_xor(as, b); } else { long ai = Long.parseLong(String.valueOf(a)); long bi = Long.parseLong(String.valueOf(b)); rtn = ai ^ bi; return rtn; } } public static <V> List<V> mk_list(V... args) { ArrayList<V> rtn = new ArrayList<V>(); for (V o : args) { rtn.add(o); } return rtn; } public static <V> List<V> mk_list(Set<V> args) { ArrayList<V> rtn = new ArrayList<V>(); if (args != null) { for (V o : args) { rtn.add(o); } } return rtn; } public static <V> List<V> mk_list(Collection<V> args) { ArrayList<V> rtn = new ArrayList<V>(); if (args != null) { for (V o : args) { rtn.add(o); } } return rtn; } public static <V> V[] mk_arr(V... args) { return args; } public static Long parseLong(Object o) { if (o == null) { return null; } if (o instanceof String) { return Long.valueOf(String.valueOf(o)); } else if (o instanceof Integer) { Integer value = (Integer) o; return Long.valueOf(value); } else if (o instanceof Long) { return (Long) o; } else { throw new RuntimeException("Invalid value " + o.getClass().getName() + " " + o); } } public static Double parseDouble(Object o) { if (o == null) { return null; } if (o instanceof String) { return Double.valueOf(String.valueOf(o)); } else if (o instanceof Integer) { Number value = (Integer) o; return value.doubleValue(); } else if (o instanceof Long) { Number value = (Long) o; return value.doubleValue(); } else if (o instanceof Double) { return (Double) o; } else { throw new RuntimeException("Invalid value " + o.getClass().getName() + " " + o); } } public static Double parseDouble(Object o, double defaultValue) { if (o == null) { return defaultValue; } try { return parseDouble(o); } catch (Exception ignored) { return defaultValue; } } public static Long parseLong(Object o, long defaultValue) { if (o == null) { return defaultValue; } if (o instanceof String) { return Long.valueOf(String.valueOf(o)); } else if (o instanceof Integer) { Integer value = (Integer) o; return Long.valueOf((Integer) value); } else if (o instanceof Long) { return (Long) o; } else { return defaultValue; } } public static Integer parseInt(Object o) { if (o == null) { return null; } if (o instanceof String) { return Integer.parseInt(String.valueOf(o)); } else if (o instanceof Long) { long value = (Long) o; return (int) value; } else if (o instanceof Integer) { return (Integer) o; } else { throw new RuntimeException("Invalid value " + o.getClass().getName() + " " + o); } } public static Integer parseInt(Object o, int defaultValue) { if (o == null) { return defaultValue; } if (o instanceof String) { return Integer.parseInt(String.valueOf(o)); } else if (o instanceof Long) { long value = (Long) o; return (int) value; } else if (o instanceof Integer) { return (Integer) o; } else { return defaultValue; } } public static Boolean parseBoolean(Object o) { if (o == null) { return null; } if (o instanceof String) { return Boolean.valueOf((String) o); } else if (o instanceof Boolean) { return (Boolean) o; } else { throw new RuntimeException("Invalid value " + o.getClass().getName() + " " + o); } } public static boolean parseBoolean(Object o, boolean defaultValue) { if (o == null) { return defaultValue; } if (o instanceof String) { return Boolean.valueOf((String) o); } else if (o instanceof Boolean) { return (Boolean) o; } else { return defaultValue; } } public static <V> Set<V> listToSet(List<V> list) { if (list == null) { return null; } Set<V> set = new HashSet<V>(); set.addAll(list); return set; } /** * Check whether the zipfile contain the resources * * @param zipfile * @param resources * @return */ public static boolean zipContainsDir(String zipfile, String resources) { Enumeration<? extends ZipEntry> entries = null; try { entries = (new ZipFile(zipfile)).entries(); while (entries != null && entries.hasMoreElements()) { ZipEntry ze = entries.nextElement(); String name = ze.getName(); if (name.startsWith(resources + "/")) { return true; } } } catch (IOException e) { // TODO Auto-generated catch block // e.printStackTrace(); LOG.error(e + "zipContainsDir error"); } return false; } public static Object add(Object oldValue, Object newValue) { if (oldValue == null) { return newValue; } else if (newValue == null) { return oldValue; } if (oldValue instanceof Long) { return (Long) oldValue + (Long) newValue; } else if (oldValue instanceof Double) { return (Double) oldValue + (Double) newValue; } else if (oldValue instanceof Integer) { return (Integer) oldValue + (Integer) newValue; } else if (oldValue instanceof Float) { return (Float) oldValue + (Float) newValue; } else if (oldValue instanceof Short) { return (Short) oldValue + (Short) newValue; } else if (oldValue instanceof BigInteger) { return ((BigInteger) oldValue).add((BigInteger) newValue); } else if (oldValue instanceof Number) { return ((Number) oldValue).doubleValue() + ((Number) newValue).doubleValue(); } else { return null; } } public static Object mergeList(List<Object> list) { Object ret = null; for (Object value : list) { ret = add(ret, value); } return ret; } public static List<Object> mergeList(List<Object> result, Object add) { if (add instanceof Collection) { for (Object o : (Collection) add) { result.add(o); } } else if (add instanceof Set) { for (Object o : (Collection) add) { result.add(o); } } else { result.add(add); } return result; } public static List<Object> distinctList(List<Object> input) { List<Object> retList = new ArrayList<Object>(); for (Object object : input) { if (retList.contains(object)) { continue; } else { retList.add(object); } } return retList; } public static <K, V> Map<K, V> mergeMapList(List<Map<K, V>> list) { Map<K, V> ret = new HashMap<K, V>(); for (Map<K, V> listEntry : list) { if (listEntry == null) { continue; } for (Entry<K, V> mapEntry : listEntry.entrySet()) { K key = mapEntry.getKey(); V value = mapEntry.getValue(); V retValue = (V) add(ret.get(key), value); ret.put(key, retValue); } } return ret; } public static String formatSimpleDouble(Double value) { try { java.text.DecimalFormat form = new java.text.DecimalFormat("##0.000"); String s = form.format(value); return s; } catch (Exception e) { return "0.000"; } } public static double formatDoubleDecPoint2(Double value) { try { java.text.DecimalFormat form = new java.text.DecimalFormat("##.00"); String s = form.format(value); return Double.valueOf(s); } catch (Exception e) { return 0.0; } } public static double formatDoubleDecPoint4(Double value) { try { java.text.DecimalFormat form = new java.text.DecimalFormat("###.0000"); String s = form.format(value); return Double.valueOf(s); } catch (Exception e) { return 0.0; } } public static Double convertToDouble(Object value) { Double ret; if (value == null) { ret = null; } else { if (value instanceof Integer) { ret = ((Integer) value).doubleValue(); } else if (value instanceof Long) { ret = ((Long) value).doubleValue(); } else if (value instanceof Float) { ret = ((Float) value).doubleValue(); } else if (value instanceof Double) { ret = (Double) value; } else { ret = null; } } return ret; } public static String formatValue(Object value) { if (value == null) { return "0"; } if (value instanceof Long) { return String.valueOf((Long) value); } else if (value instanceof Double) { return formatSimpleDouble((Double) value); } else { return String.valueOf(value); } } public static void sleepMs(long ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { } } public static void sleepNs(int ns) { try { Thread.sleep(0, ns); } catch (InterruptedException e) { } } public static String HEXES = "0123456789ABCDEF"; public static String toPrintableString(byte[] buf) { if (buf == null) { return null; } StringBuilder sb = new StringBuilder(); int index = 0; for (byte b : buf) { if (index % 10 == 0) { sb.append("\n"); } index++; sb.append(HEXES.charAt((b & 0xF0) >> 4)); sb.append(HEXES.charAt((b & 0x0F))); sb.append(" "); } return sb.toString(); } /** * @return * @@@ Todo */ public static Long getPhysicMemorySize() { Object object; try { object = ManagementFactory.getPlatformMBeanServer().getAttribute( new ObjectName("java.lang", "type", "OperatingSystem"), "TotalPhysicalMemorySize"); } catch (Exception e) { LOG.warn("Failed to get system physical memory size,", e); return null; } Long ret = (Long) object; return ret; } public static String genLogName(String topology, Integer port) { return topology + "-worker-" + port + ".log"; } public static byte[] longToBytes(long x) { ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE); buffer.putLong(x); return buffer.array(); } public static long bytesToLong(byte[] bytes) { ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE); buffer.put(bytes); buffer.flip();// need flip return buffer.getLong(); } public static long halfValueOfSum(long v1, long v2, boolean increment) { long ret = (v1 + v2) / 2; if (increment) { ret += (v1 + v2) % 2; } return ret; } public static String join(String delim, List<String> strings) { StringBuilder builder = new StringBuilder(); if (strings != null) { for (String str : strings) { if (builder.length() > 0) { builder.append(delim).append(" "); } builder.append(str); } } return builder.toString(); } }