/*
 * 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.storm.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.security.auth.Subject;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.storm.Config;
import org.apache.storm.DaemonConfig;
import org.apache.storm.blobstore.BlobStore;
import org.apache.storm.blobstore.BlobStoreAclHandler;
import org.apache.storm.blobstore.ClientBlobStore;
import org.apache.storm.blobstore.LocalFsBlobStore;
import org.apache.storm.blobstore.LocalModeClientBlobStore;
import org.apache.storm.daemon.Acker;
import org.apache.storm.daemon.StormCommon;
import org.apache.storm.generated.AccessControl;
import org.apache.storm.generated.AccessControlType;
import org.apache.storm.generated.AuthorizationException;
import org.apache.storm.generated.InvalidTopologyException;
import org.apache.storm.generated.KeyNotFoundException;
import org.apache.storm.generated.ReadableBlobMeta;
import org.apache.storm.generated.SettableBlobMeta;
import org.apache.storm.generated.StormTopology;
import org.apache.storm.nimbus.ILeaderElector;
import org.apache.storm.nimbus.NimbusInfo;
import org.apache.storm.scheduler.resource.ResourceUtils;
import org.apache.storm.scheduler.resource.normalization.NormalizedResourceRequest;
import org.apache.storm.security.auth.SingleUserPrincipal;
import org.apache.storm.shade.com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ServerUtils {
    public static final Logger LOG = LoggerFactory.getLogger(ServerUtils.class);

    public static final boolean IS_ON_WINDOWS = "Windows_NT".equals(System.getenv("OS"));

    public static final int SIGKILL = 9;
    public static final int SIGTERM = 15;

    // A singleton instance allows us to mock delegated static methods in our
    // tests by subclassing.
    private static ServerUtils _instance = new ServerUtils();

    /**
     * Provide an instance of this class for delegates to use.
     * To mock out delegated methods, provide an instance of a subclass that
     * overrides the implementation of the delegated method.
     *
     * @param u a ServerUtils instance
     * @return the previously set instance
     */
    public static ServerUtils setInstance(ServerUtils u) {
        ServerUtils oldInstance = _instance;
        _instance = u;
        return oldInstance;
    }

    public static <T> List<T> interleaveAll(List<List<T>> nodeList) {
        if (nodeList != null && nodeList.size() > 0) {
            List<T> first = new ArrayList<T>();
            List<List<T>> rest = new ArrayList<List<T>>();
            for (List<T> node : nodeList) {
                if (node != null && node.size() > 0) {
                    first.add(node.get(0));
                    rest.add(node.subList(1, node.size()));
                }
            }
            List<T> interleaveRest = interleaveAll(rest);
            if (interleaveRest != null) {
                first.addAll(interleaveRest);
            }
            return first;
        }
        return null;
    }

    public static BlobStore getNimbusBlobStore(Map<String, Object> conf,
            NimbusInfo nimbusInfo,
            ILeaderElector leaderElector) {
        return getNimbusBlobStore(conf, null, nimbusInfo, leaderElector);
    }

    public static BlobStore getNimbusBlobStore(Map<String, Object> conf,
            String baseDir,
            NimbusInfo nimbusInfo,
            ILeaderElector leaderElector) {
        String type = (String) conf.get(DaemonConfig.NIMBUS_BLOBSTORE);
        if (type == null) {
            type = LocalFsBlobStore.class.getName();
        }
        BlobStore store = (BlobStore) ReflectionUtils.newInstance(type);
        Map<String, Object> nconf = new HashMap<>(conf);
        // only enable cleanup of blobstore on nimbus
        nconf.put(Config.BLOBSTORE_CLEANUP_ENABLE, Boolean.TRUE);

        if (store != null) {
            // store can be null during testing when mocking utils.
            store.prepare(nconf, baseDir, nimbusInfo, leaderElector);
        }
        return store;
    }

    public static boolean isAbsolutePath(String path) {
        return Paths.get(path).isAbsolute();
    }

    /**
     * Returns the combined string, escaped for posix shell.
     *
     * @param command the list of strings to be combined
     * @return the resulting command string
     */
    public static String shellCmd(List<String> command) {
        List<String> changedCommands = new ArrayList<>(command.size());
        for (String str : command) {
            if (str == null) {
                continue;
            }
            changedCommands.add("'" + str.replaceAll("'", "'\"'\"'") + "'");
        }
        return StringUtils.join(changedCommands, " ");
    }

    /**
     * Takes an input dir or file and returns the disk usage on that local directory. Very basic implementation.
     *
     * @param dir The input dir to get the disk space of this local dir
     * @return The total disk space of the input local directory
     */
    public static long getDiskUsage(File dir) {
        long size = 0;
        if (!dir.exists()) {
            return 0;
        }
        if (!dir.isDirectory()) {
            return dir.length();
        } else {
            File[] allFiles = dir.listFiles();
            if (allFiles != null) {
                for (int i = 0; i < allFiles.length; i++) {
                    boolean isSymLink = org.apache.commons.io.FileUtils.isSymlink(allFiles[i]);
                    if (!isSymLink) {
                        size += getDiskUsage(allFiles[i]);
                    }
                }
            }
            return size;
        }
    }

    public static ClientBlobStore getClientBlobStoreForSupervisor(Map<String, Object> conf) {
        ClientBlobStore store;
        if (ConfigUtils.isLocalMode(conf)) {
            store = new LocalModeClientBlobStore(getNimbusBlobStore(conf, null, null));
        } else {
            store = (ClientBlobStore) ReflectionUtils.newInstance(
                (String) conf.get(DaemonConfig.SUPERVISOR_BLOBSTORE));
        }
        store.prepare(conf);
        return store;
    }

    /**
     * Returns the value of java.class.path System property. Kept separate for testing.
     *
     * @return the classpath
     */
    public static String currentClasspath() {
        return _instance.currentClasspathImpl();
    }


    /**
     *  Returns the current thread classloader.
     */
    public static URL getResourceFromClassloader(String name) {
        return _instance.getResourceFromClassloaderImpl(name);
    }

    /**
     * Determines if a zip archive contains a particular directory.
     *
     * @param zipfile path to the zipped file
     * @param target  directory being looked for in the zip.
     * @return boolean whether or not the directory exists in the zip.
     */
    public static boolean zipDoesContainDir(String zipfile, String target) throws IOException {
        List<ZipEntry> entries = (List<ZipEntry>) Collections.list(new ZipFile(zipfile).entries());

        String targetDir = target + "/";
        for (ZipEntry entry : entries) {
            String name = entry.getName();
            if (name.startsWith(targetDir)) {
                return true;
            }
        }

        return false;
    }

    public static String getFileOwner(String path) throws IOException {
        return Files.getOwner(FileSystems.getDefault().getPath(path)).getName();
    }

    public static String containerFilePath(String dir) {
        return dir + File.separator + "launch_container.sh";
    }

    public static String scriptFilePath(String dir) {
        return dir + File.separator + "storm-worker-script.sh";
    }

    /**
     * Writes a posix shell script file to be executed in its own process.
     *
     * @param dir         the directory under which the script is to be written
     * @param command     the command the script is to execute
     * @param environment optional environment variables to set before running the script's command. May be  null.
     * @return the path to the script that has been written
     */
    public static String writeScript(String dir, List<String> command,
                                     Map<String, String> environment) throws IOException {
        return writeScript(dir, command, environment, null);
    }

    /**
     * Writes a posix shell script file to be executed in its own process.
     *
     * @param dir         the directory under which the script is to be written
     * @param command     the command the script is to execute
     * @param environment optional environment variables to set before running the script's command. May be  null.
     * @param umask umask to be set. It can be null.
     * @return the path to the script that has been written
     */
    public static String writeScript(String dir, List<String> command,
                                     Map<String, String> environment, String umask) throws IOException {
        String path = scriptFilePath(dir);
        try (BufferedWriter out = new BufferedWriter(new FileWriter(path))) {
            out.write("#!/bin/bash");
            out.newLine();
            if (environment != null) {
                for (String k : environment.keySet()) {
                    String v = environment.get(k);
                    if (v == null) {
                        v = "";
                    }
                    out.write(shellCmd(
                        Arrays.asList(
                            "export", k + "=" + v)));
                    out.write(";");
                    out.newLine();
                }
            }
            out.newLine();
            if (umask != null) {
                out.write("umask " + umask);
                out.newLine();
            }
            out.write("exec " + shellCmd(command) + ";");
        }
        return path;
    }

    public static int execCommand(String... command) throws ExecuteException, IOException {
        CommandLine cmd = new CommandLine(command[0]);
        for (int i = 1; i < command.length; i++) {
            cmd.addArgument(command[i]);
        }

        DefaultExecutor exec = new DefaultExecutor();
        return exec.execute(cmd);
    }

    public static void sendSignalToProcess(long lpid, int signum) throws IOException {
        String pid = Long.toString(lpid);
        try {
            if (Utils.isOnWindows()) {
                if (signum == SIGKILL) {
                    execCommand("taskkill", "/f", "/pid", pid);
                } else {
                    execCommand("taskkill", "/pid", pid);
                }
            } else {
                execCommand("kill", "-" + signum, pid);
            }
        } catch (ExecuteException e) {
            LOG.info("Error when trying to kill {}. Process is probably already dead.", pid);
        } catch (IOException e) {
            LOG.info("IOException Error when trying to kill {}.", pid);
            throw e;
        }
    }

    public static void killProcessWithSigTerm(String pid) throws IOException {
        sendSignalToProcess(Long.parseLong(pid), SIGTERM);
    }

    public static void forceKillProcess(String pid) throws IOException {
        sendSignalToProcess(Long.parseLong(pid), SIGKILL);
    }

    public static long nimbusVersionOfBlob(String key, ClientBlobStore cb) throws AuthorizationException, KeyNotFoundException {
        long nimbusBlobVersion = 0;
        ReadableBlobMeta metadata = cb.getBlobMeta(key);
        nimbusBlobVersion = metadata.get_version();
        return nimbusBlobVersion;
    }

    public static boolean canUserReadBlob(ReadableBlobMeta meta, String user, Map<String, Object> conf) {

        if (!ObjectReader.getBoolean(conf.get(Config.STORM_BLOBSTORE_ACL_VALIDATION_ENABLED), false)) {
            return true;
        }

        SettableBlobMeta settable = meta.get_settable();
        for (AccessControl acl : settable.get_acl()) {
            if (acl.get_type().equals(AccessControlType.OTHER) && (acl.get_access() & BlobStoreAclHandler.READ) > 0) {
                return true;
            }
            if (acl.get_name().equals(user) && (acl.get_access() & BlobStoreAclHandler.READ) > 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * Unpack matching files from a jar. Entries inside the jar that do not match the given pattern will be skipped.
     *
     * @param jarFile the .jar file to unpack
     * @param toDir   the destination directory into which to unpack the jar
     */
    public static void unJar(File jarFile, File toDir) throws IOException {
        try (JarFile jar = new JarFile(jarFile)) {
            extractZipFile(jar, toDir, null);
        }
    }

    /**
     * Ensure the existence of a given directory.
     *
     * @throws IOException if it cannot be created and does not already exist
     */
    private static void ensureDirectory(File dir) throws IOException {
        if (!dir.mkdirs() && !dir.isDirectory()) {
            throw new IOException("Mkdirs failed to create " + dir.toString());
        }
    }

    /**
     * Given a Tar File as input it will untar the file in a the untar directory passed as the second parameter
     * <p/>
     * This utility will untar ".tar" files and ".tar.gz","tgz" files.
     *
     * @param inFile   The tar file as input
     * @param untarDir The untar directory where to untar the tar file
     * @param symlinksDisabled true if symlinks should be disabled, else false
     */
    public static void unTar(File inFile, File untarDir, boolean symlinksDisabled) throws IOException {
        ensureDirectory(untarDir);

        boolean gzipped = inFile.toString().endsWith("gz");
        if (Utils.isOnWindows() || symlinksDisabled) {
            // Tar is not native to Windows. Use simple Java based implementation for
            // tests and simple tar archives
            unTarUsingJava(inFile, untarDir, gzipped, symlinksDisabled);
        } else {
            // spawn tar utility to untar archive for full fledged unix behavior such
            // as resolving symlinks in tar archives
            unTarUsingTar(inFile, untarDir, gzipped);
        }
    }

    private static void unTarUsingTar(File inFile, File untarDir,
                                      boolean gzipped) throws IOException {
        StringBuffer untarCommand = new StringBuffer();
        if (gzipped) {
            untarCommand.append(" gzip -dc '");
            untarCommand.append(inFile.toString());
            untarCommand.append("' | (");
        }
        untarCommand.append("cd '");
        untarCommand.append(untarDir.toString());
        untarCommand.append("' ; ");
        untarCommand.append("tar -xf ");

        if (gzipped) {
            untarCommand.append(" -)");
        } else {
            untarCommand.append(inFile.toString());
        }
        String[] shellCmd = { "bash", "-c", untarCommand.toString() };
        ShellUtils.ShellCommandExecutor shexec = new ShellUtils.ShellCommandExecutor(shellCmd);
        shexec.execute();
        int exitcode = shexec.getExitCode();
        if (exitcode != 0) {
            throw new IOException("Error untarring file "
                    + inFile
                    + ". Tar process exited with exit code "
                    + exitcode);
        }
    }

    private static void unTarUsingJava(File inFile, File untarDir,
                                       boolean gzipped, boolean symlinksDisabled) throws IOException {
        final String base = untarDir.getCanonicalPath();
        LOG.trace("java untar {} to {}", inFile, base);
        InputStream inputStream = null;
        try {
            if (gzipped) {
                inputStream = new BufferedInputStream(new GZIPInputStream(
                    new FileInputStream(inFile)));
            } else {
                inputStream = new BufferedInputStream(new FileInputStream(inFile));
            }
            try (TarArchiveInputStream tis = new TarArchiveInputStream(inputStream)) {
                for (TarArchiveEntry entry = tis.getNextTarEntry(); entry != null; ) {
                    unpackEntries(tis, entry, untarDir, base, symlinksDisabled);
                    entry = tis.getNextTarEntry();
                }
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    private static void unpackEntries(TarArchiveInputStream tis,
                                      TarArchiveEntry entry, File outputDir, final String base,
                                      boolean symlinksDisabled) throws IOException {
        File target = new File(outputDir, entry.getName());
        String found = target.getCanonicalPath();
        if (!found.startsWith(base)) {
            LOG.error("Invalid location {} is outside of {}", found, base);
            return;
        }
        if (entry.isDirectory()) {
            LOG.trace("Extracting dir {}", target);
            ensureDirectory(target);
            for (TarArchiveEntry e : entry.getDirectoryEntries()) {
                unpackEntries(tis, e, target, base, symlinksDisabled);
            }
        } else if (entry.isSymbolicLink()) {
            if (symlinksDisabled) {
                LOG.info("Symlinks disabled skipping {}", target);
            } else {
                Path src = target.toPath();
                Path dest = Paths.get(entry.getLinkName());
                LOG.trace("Extracting sym link {} to {}", target, dest);
                // Create symbolic link relative to tar parent dir
                Files.createSymbolicLink(src, dest);
            }
        } else if (entry.isFile()) {
            LOG.trace("Extracting file {}", target);
            ensureDirectory(target.getParentFile());
            try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(target))) {
                IOUtils.copy(tis, outputStream);
            }
        } else {
            LOG.error("{} is not a currently supported tar entry type.", entry);
        }

        Path p = target.toPath();
        if (Files.exists(p)) {
            try {
                //We created it so lets chmod it properly
                int mode = entry.getMode();
                Files.setPosixFilePermissions(p, parsePerms(mode));
            } catch (UnsupportedOperationException e) {
                //Ignored the file system we are on does not support this, so don't do it.
            }
        }
    }

    private static Set<PosixFilePermission> parsePerms(int mode) {
        Set<PosixFilePermission> ret = new HashSet<>();
        if ((mode & 0001) > 0) {
            ret.add(PosixFilePermission.OTHERS_EXECUTE);
        }
        if ((mode & 0002) > 0) {
            ret.add(PosixFilePermission.OTHERS_WRITE);
        }
        if ((mode & 0004) > 0) {
            ret.add(PosixFilePermission.OTHERS_READ);
        }
        if ((mode & 0010) > 0) {
            ret.add(PosixFilePermission.GROUP_EXECUTE);
        }
        if ((mode & 0020) > 0) {
            ret.add(PosixFilePermission.GROUP_WRITE);
        }
        if ((mode & 0040) > 0) {
            ret.add(PosixFilePermission.GROUP_READ);
        }
        if ((mode & 0100) > 0) {
            ret.add(PosixFilePermission.OWNER_EXECUTE);
        }
        if ((mode & 0200) > 0) {
            ret.add(PosixFilePermission.OWNER_WRITE);
        }
        if ((mode & 0400) > 0) {
            ret.add(PosixFilePermission.OWNER_READ);
        }
        return ret;
    }

    public static void unpack(File localrsrc, File dst, boolean symLinksDisabled) throws IOException {
        String lowerDst = localrsrc.getName().toLowerCase();
        if (lowerDst.endsWith(".jar")
                || lowerDst.endsWith("_jar")) {
            unJar(localrsrc, dst);
        } else if (lowerDst.endsWith(".zip")
                || lowerDst.endsWith("_zip")) {
            unZip(localrsrc, dst);
        } else if (lowerDst.endsWith(".tar.gz")
                || lowerDst.endsWith("_tar_gz")
                || lowerDst.endsWith(".tgz")
                || lowerDst.endsWith("_tgz")
                || lowerDst.endsWith(".tar")
                || lowerDst.endsWith("_tar")) {
            unTar(localrsrc, dst, symLinksDisabled);
        } else {
            LOG.warn("Cannot unpack " + localrsrc);
            if (!localrsrc.renameTo(dst)) {
                throw new IOException("Unable to rename file: [" + localrsrc
                                      + "] to [" + dst + "]");
            }
        }
        if (localrsrc.isFile()) {
            localrsrc.delete();
        }
    }
    
    /**
     * Extracts the given file to the given directory. Only zip entries starting with the given prefix are extracted.
     * The prefix is stripped off entry names before extraction.
     *
     * @param zipFile The zip file to extract
     * @param toDir The directory to extract to
     * @param prefix The prefix to look for in the zip file. If not null only paths starting with the prefix will be
     *     extracted
     */
    public static void extractZipFile(ZipFile zipFile, File toDir, String prefix) throws IOException {
        ensureDirectory(toDir);
        final String base = toDir.getCanonicalPath();

        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            if (!entry.isDirectory()) {
                if (prefix != null && !entry.getName().startsWith(prefix)) {
                    //No need to extract it, it is not what we are looking for.
                    continue;
                }
                String entryName;
                if (prefix != null) {
                    entryName = entry.getName().substring(prefix.length());
                    LOG.debug("Extracting {} shortened to {} into {}", entry.getName(), entryName, toDir);
                } else {
                    entryName = entry.getName();
                }
                File file = new File(toDir, entryName);
                String found = file.getCanonicalPath();
                if (!found.startsWith(base)) {
                    LOG.error("Invalid location {} is outside of {}", found, base);
                    continue;
                }

                try (InputStream in = zipFile.getInputStream(entry)) {
                    ensureDirectory(file.getParentFile());
                    try (OutputStream out = new FileOutputStream(file)) {
                        IOUtils.copy(in, out);
                    }
                }
            }
        }
    }

    /**
     * Given a File input it will unzip the file in a the unzip directory passed as the second parameter.
     *
     * @param inFile   The zip file as input
     * @param toDir The unzip directory where to unzip the zip file
     */
    public static void unZip(File inFile, File toDir) throws IOException {
        try (ZipFile zipFile = new ZipFile(inFile)) {
            extractZipFile(zipFile, toDir, null);
        }
    }

    /**
     * Given a zip File input it will return its size Only works for zip files whose uncompressed size is less than 4 GB, otherwise returns
     * the size module 2^32, per gzip specifications.
     *
     * @param myFile The zip file as input
     * @return zip file size as a long
     */
    public static long zipFileSize(File myFile) throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(myFile, "r")) {
            raf.seek(raf.length() - 4);
            long b4 = raf.read();
            long b3 = raf.read();
            long b2 = raf.read();
            long b1 = raf.read();
            return (b1 << 24) | (b2 << 16) + (b3 << 8) + b4;
        }
    }

    /**
     * Check if the scheduler is resource aware or not.
     *
     * @param conf The configuration
     * @return True if it's resource aware; false otherwise
     */
    public static boolean isRas(Map<String, Object> conf) {
        if (conf.containsKey(DaemonConfig.STORM_SCHEDULER)) {
            if (conf.get(DaemonConfig.STORM_SCHEDULER).equals("org.apache.storm.scheduler.resource.ResourceAwareScheduler")) {
                return true;
            }
        }
        return false;
    }

    public static int getEstimatedWorkerCountForRasTopo(Map<String, Object> topoConf, StormTopology topology)
        throws InvalidTopologyException {
        Double defaultWorkerMaxHeap = ObjectReader.getDouble(topoConf.get(Config.WORKER_HEAP_MEMORY_MB), 768d);
        Double topologyWorkerMaxHeap = ObjectReader.getDouble(topoConf.get(Config.TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB), defaultWorkerMaxHeap);
        return (int) Math.ceil(getEstimatedTotalHeapMemoryRequiredByTopo(topoConf, topology) / topologyWorkerMaxHeap);
    }

    public static double getEstimatedTotalHeapMemoryRequiredByTopo(Map<String, Object> topoConf, StormTopology topology)
        throws InvalidTopologyException {
        Map<String, Integer> componentParallelism = getComponentParallelism(topoConf, topology);
        double totalMemoryRequired = 0.0;

        for (Map.Entry<String, NormalizedResourceRequest> entry : ResourceUtils.getBoltsResources(topology, topoConf).entrySet()) {
            int parallelism = componentParallelism.getOrDefault(entry.getKey(), 1);
            double memoryRequirement = entry.getValue().getOnHeapMemoryMb();
            totalMemoryRequired += memoryRequirement * parallelism;
        }

        for (Map.Entry<String, NormalizedResourceRequest> entry : ResourceUtils.getSpoutsResources(topology, topoConf).entrySet()) {
            int parallelism = componentParallelism.getOrDefault(entry.getKey(), 1);
            double memoryRequirement = entry.getValue().getOnHeapMemoryMb();
            totalMemoryRequired += memoryRequirement * parallelism;
        }
        return totalMemoryRequired;
    }

    public static Map<String, Integer> getComponentParallelism(Map<String, Object> topoConf, StormTopology topology)
        throws InvalidTopologyException {
        Map<String, Integer> ret = new HashMap<>();
        Map<String, Object> components = StormCommon.allComponents(topology);
        for (Map.Entry<String, Object> entry : components.entrySet()) {
            ret.put(entry.getKey(), getComponentParallelism(topoConf, entry.getValue()));
        }
        return ret;
    }

    public static int getComponentParallelism(Map<String, Object> topoConf, Object component) throws InvalidTopologyException {
        Map<String, Object> combinedConf = Utils.merge(topoConf, StormCommon.componentConf(component));
        int numTasks = ObjectReader.getInt(combinedConf.get(Config.TOPOLOGY_TASKS), StormCommon.numStartExecutors(component));
        Integer maxParallel = ObjectReader.getInt(combinedConf.get(Config.TOPOLOGY_MAX_TASK_PARALLELISM), null);
        int ret = numTasks;
        if (maxParallel != null) {
            ret = Math.min(maxParallel, numTasks);
        }
        return ret;
    }

    public static Subject principalNameToSubject(String name) {
        SingleUserPrincipal principal = new SingleUserPrincipal(name);
        Subject sub = new Subject();
        sub.getPrincipals().add(principal);
        return sub;
    }

    // Non-static impl methods exist for mocking purposes.
    public String currentClasspathImpl() {
        return System.getProperty("java.class.path");
    }


    public URL getResourceFromClassloaderImpl(String name) {
        return Thread.currentThread().getContextClassLoader().getResource(name);
    }

    private static final Pattern MEMINFO_PATTERN = Pattern.compile("^([^:\\s]+):\\s*([0-9]+)\\s*kB$");

    /**
     * Get system free memory in megabytes.
     * @return system free memory in megabytes
     * @throws IOException on I/O exception
     */
    public static long getMemInfoFreeMb() throws IOException {
        //MemFree:        14367072 kB
        //Buffers:          536512 kB
        //Cached:          1192096 kB
        // MemFree + Buffers + Cached
        long memFree = 0;
        long buffers = 0;
        long cached = 0;
        try (BufferedReader in = new BufferedReader(new FileReader("/proc/meminfo"))) {
            String line = null;
            while ((line = in.readLine()) != null) {
                Matcher match = MEMINFO_PATTERN.matcher(line);
                if (match.matches()) {
                    String tag = match.group(1);
                    if (tag.equalsIgnoreCase("MemFree")) {
                        memFree = Long.parseLong(match.group(2));
                    } else if (tag.equalsIgnoreCase("Buffers")) {
                        buffers = Long.parseLong(match.group(2));
                    } else if (tag.equalsIgnoreCase("Cached")) {
                        cached = Long.parseLong(match.group(2));
                    }
                }
            }
        }
        return (memFree + buffers + cached) / 1024;
    }

    /**
     * Is a process alive and running?.
     *
     * @param pid the PID of the running process
     * @param user the user that is expected to own that process
     * @return true if it is, else false
     *
     * @throws IOException on any error
     */
    public static boolean isProcessAlive(long pid, String user) throws IOException {
        if (ServerUtils.IS_ON_WINDOWS) {
            return isWindowsProcessAlive(pid, user);
        }
        return isPosixProcessAlive(pid, user);
    }

    private static boolean isWindowsProcessAlive(long pid, String user) throws IOException {
        boolean ret = false;
        LOG.debug("CMD: tasklist /fo list /fi \"pid eq {}\" /v", pid);
        ProcessBuilder pb = new ProcessBuilder("tasklist", "/fo", "list", "/fi", "pid eq " + pid, "/v");
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        try (BufferedReader in = new BufferedReader(new InputStreamReader(pb.start().getInputStream(), StandardCharsets.UTF_8))) {
            int lineNo = 0;
            String line;
            while ((line = in.readLine()) != null) {
                lineNo++;
                LOG.debug("CMD=LINE#{}: {}", lineNo, line);
                if (line.contains("User Name:")) { //Check for : in case someone called their user "User Name"
                    //This line contains the user name for the pid we're looking up
                    //Example line: "User Name:    exampleDomain\exampleUser"
                    List<String> userNameLineSplitOnWhitespace = Arrays.asList(line.split(":"));
                    if (userNameLineSplitOnWhitespace.size() == 2) {
                        List<String> userAndMaybeDomain = Arrays.asList(userNameLineSplitOnWhitespace.get(1).trim().split("\\\\"));
                        String processUser = userAndMaybeDomain.size() == 2 ? userAndMaybeDomain.get(1) : userAndMaybeDomain.get(0);
                        processUser = processUser.trim();
                        if (user.equals(processUser)) {
                            ret = true;
                        } else {
                            LOG.info("Found {} running as {}, but expected it to be {}", pid, processUser, user);
                        }
                    } else {
                        LOG.error("Received unexpected output from tasklist command. Expected one colon in user name line. Line was {}",
                            line);
                    }
                    break;
                }
            }
        }
        return ret;
    }

    private static boolean isPosixProcessAlive(long pid, String user) throws IOException {
        LOG.debug("CMD: ps -o user -p {}", pid);
        ProcessBuilder pb = new ProcessBuilder("ps", "-o", "user", "-p", String.valueOf(pid));
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        try (BufferedReader in = new BufferedReader(new InputStreamReader(pb.start().getInputStream(), StandardCharsets.UTF_8))) {
            int lineNo = 1;
            String line = in.readLine();
            LOG.debug("CMD-LINE#{}: {}", lineNo, line);
            if (!"USER".equals(line.trim())) {
                LOG.error("Expecting first line to contain USER, found \"{}\"", line);
                return false;
            }
            while ((line = in.readLine()) != null) {
                lineNo++;
                LOG.debug("CMD-LINE#{}: {}", lineNo, line);
                line = line.trim();
                if (user.equals(line)) {
                    return true;
                }
                LOG.info("Found {} running as {}, but expected it to be {}", pid, line, user);
            }
        } catch (IOException ex) {
            String err = String.format("Cannot read output of command \"ps -o user -p %d\"", pid);
            throw new IOException(err, ex);
        }
        return false;
    }

    /**
     * Are any of the processes alive and running for the specified user. If collection is empty or null
     * then the return value is trivially false.
     *
     * @param pids the PIDs of the running processes
     * @param user the user that is expected to own that process
     * @return true if any one of the processes is owned by user and alive, else false
     * @throws IOException on I/O exception
     */
    public static boolean isAnyProcessAlive(Collection<Long> pids, String user) throws IOException {
        if (pids == null || pids.isEmpty()) {
            return false;
        }

        if (ServerUtils.IS_ON_WINDOWS) {
            return isAnyWindowsProcessAlive(pids, user);
        }
        return isAnyPosixProcessAlive(pids, user);
    }

    /**
     * Are any of the processes alive and running for the specified userId. If collection is empty or null
     * then the return value is trivially false.
     *
     * @param pids the PIDs of the running processes
     * @param uid the user that is expected to own that process
     * @return true if any one of the processes is owned by user and alive, else false
     * @throws IOException on I/O exception
     */
    public static boolean isAnyProcessAlive(Collection<Long> pids, int uid) throws IOException {
        if (pids == null || pids.isEmpty()) {
            return false;
        }
        if (ServerUtils.IS_ON_WINDOWS) {
            return isAnyWindowsProcessAlive(pids, uid);
        }
        return isAnyPosixProcessAlive(pids, uid);
    }

    /**
     * Find if any of the Windows processes are alive and owned by the specified user.
     * Command reference https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/tasklist.
     *
     * @param pids the PIDs of the running processes
     * @param user the user that is expected to own that process
     * @return true if any one of the processes is owned by user and alive, else false
     * @throws IOException on I/O exception
     */
    private static boolean isAnyWindowsProcessAlive(Collection<Long> pids, String user) throws IOException {
        List<String> unexpectedUsers = new ArrayList<>();
        for (Long pid: pids) {
            List<String> cmdArgs = new ArrayList<>();
            cmdArgs.add("tasklist");
            cmdArgs.add("/fo");
            cmdArgs.add("list");
            cmdArgs.add("/fi");
            cmdArgs.add("pid eq " + pid);
            cmdArgs.add("/v");
            LOG.debug("CMD: {}", String.join(" ", cmdArgs));
            ProcessBuilder pb = new ProcessBuilder(cmdArgs);
            pb.redirectError(ProcessBuilder.Redirect.INHERIT);
            try (BufferedReader in = new BufferedReader(new InputStreamReader(pb.start().getInputStream(), StandardCharsets.UTF_8))) {
                int lineNo = 0;
                String line;
                while ((line = in.readLine()) != null) {
                    lineNo++;
                    LOG.debug("CMD-LINE#{}: {}", lineNo, line);
                    if (line.contains("User Name:")) { //Check for : in case someone called their user "User Name"
                        //This line contains the user name for the pid we're looking up
                        //Example line: "User Name:    exampleDomain\exampleUser"
                        List<String> userNameLineSplitOnWhitespace = Arrays.asList(line.split(":"));
                        if (userNameLineSplitOnWhitespace.size() == 2) {
                            List<String> userAndMaybeDomain = Arrays.asList(userNameLineSplitOnWhitespace.get(1).trim().split("\\\\"));
                            String processUser = userAndMaybeDomain.size() == 2 ? userAndMaybeDomain.get(1) : userAndMaybeDomain.get(0);
                            processUser = processUser.trim();
                            if (user.equals(processUser)) {
                                return true;
                            }
                            unexpectedUsers.add(processUser);
                        } else {
                            LOG.error("Received unexpected output from tasklist command. Expected one colon in user name line. Line was {}",
                                    line);
                        }
                        break;
                    }
                }
            } catch (IOException ex) {
                String err = String.format("Cannot read output of command \"%s\"", String.join(" ", cmdArgs));
                throw new IOException(err, ex);
            }
        }
        String pidsAsStr = StringUtils.join(pids, ",");
        if (unexpectedUsers.isEmpty()) {
            LOG.info("None of the processes {} are alive", pidsAsStr);
        } else {
            LOG.info("{} of the Processes {} are running as user(s) {}: but expected user is {}",
                unexpectedUsers.size(), pidsAsStr, String.join(",", new TreeSet<>(unexpectedUsers)), user);
        }
        return false;
    }

    /**
     * Find if any of the Windows processes are alive and owned by the specified userId.
     * This overridden method is provided for symmetry, but is not implemented.
     *
     * @param pids the PIDs of the running processes
     * @param uid the user that is expected to own that process
     * @return true if any one of the processes is owned by user and alive, else false
     * @throws IOException on I/O exception
     */
    private static boolean isAnyWindowsProcessAlive(Collection<Long> pids, int uid) throws IOException {
        throw new IllegalArgumentException("UID is not supported on Windows");
    }

    /**
     * Are any of the processes alive and running for the specified user.
     *
     * @param pids the PIDs of the running processes
     * @param user the user that is expected to own that process
     * @return true if any one of the processes is owned by user and alive, else false
     * @throws IOException on I/O exception
     */
    private static boolean isAnyPosixProcessAlive(Collection<Long> pids, String user) throws IOException {
        String pidParams = StringUtils.join(pids, ",");
        LOG.debug("CMD: ps -o user -p {}", pidParams);
        ProcessBuilder pb = new ProcessBuilder("ps", "-o", "user", "-p", pidParams);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        List<String> unexpectedUsers = new ArrayList<>();
        try (BufferedReader in = new BufferedReader(new InputStreamReader(pb.start().getInputStream(), StandardCharsets.UTF_8))) {
            int lineNo = 1;
            String line = in.readLine();
            LOG.debug("CMD-LINE#{}: {}", lineNo, line);
            if (!"USER".equals(line.trim())) {
                LOG.error("Expecting first line to contain USER, found \"{}\"", line);
                return false;
            }
            while ((line = in.readLine()) != null) {
                lineNo++;
                LOG.debug("CMD-LINE#{}: {}", lineNo, line);
                line = line.trim();
                if (user.equals(line)) {
                    return true;
                }
                unexpectedUsers.add(line);
            }
        } catch (IOException ex) {
            String err = String.format("Cannot read output of command \"ps -o user -p %s\"", pidParams);
            throw new IOException(err, ex);
        }
        if (unexpectedUsers.isEmpty()) {
            LOG.info("None of the processes {} are alive", pidParams);
        } else {
            LOG.info("{} of {} Processes {} are running as user(s) {}: but expected user is {}",
                unexpectedUsers.size(), pids.size(), pidParams, String.join(",", new TreeSet<>(unexpectedUsers)), user);
        }
        return false;
    }

    /**
     * Are any of the processes alive and running for the specified UID.
     *
     * @param pids the PIDs of the running processes
     * @param uid the userId that is expected to own that process
     * @return true if any one of the processes is owned by user and alive, else false
     * @throws IOException on I/O exception
     */
    private static boolean isAnyPosixProcessAlive(Collection<Long> pids, int uid) throws IOException {
        String pidParams = StringUtils.join(pids, ",");
        LOG.debug("CMD: ps -o uid -p {}", pidParams);
        ProcessBuilder pb = new ProcessBuilder("ps", "-o", "uid", "-p", pidParams);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        List<String> unexpectedUsers = new ArrayList<>();
        try (BufferedReader in = new BufferedReader(new InputStreamReader(pb.start().getInputStream(), StandardCharsets.UTF_8))) {
            int lineNo = 1;
            String line = in.readLine();
            LOG.debug("CMD-LINE#{}: {}", lineNo, line);
            if (!"UID".equals(line.trim())) {
                LOG.error("Expecting first line to contain UID, found \"{}\"", line);
                return false;
            }
            while ((line = in.readLine()) != null) {
                lineNo++;
                LOG.debug("CMD-LINE#{}: {}", lineNo, line);
                line = line.trim();
                try {
                    if (uid == Integer.parseInt(line)) {
                        return true;
                    }
                } catch (Exception ex) {
                    LOG.warn("Expecting UID integer but got {} in output of ps command", line);
                }
                unexpectedUsers.add(line);
            }
        } catch (IOException ex) {
            String err = String.format("Cannot read output of command \"ps -o uid -p %s\"", pidParams);
            throw new IOException(err, ex);
        }
        if (unexpectedUsers.isEmpty()) {
            LOG.info("None of the processes {} are alive", pidParams);
        } else {
            LOG.info("{} of {} Processes {} are running as UIDs {}: but expected userId is {}",
                unexpectedUsers.size(), pids.size(), pidParams, String.join(",", new TreeSet<>(unexpectedUsers)), uid);
        }
        return false;
    }

    /**
     * Get the userId for a user name. This works on Posix systems by using "id -u" command.
     * Throw IllegalArgumentException on Windows.
     *
     * @param user username to be converted to UID. This is optional, in which case current user is returned.
     * @return UID for the specified user (if supplied), else UID of current user, -1 upon Exception.
     */
    public static int getUserId(String user) {
        if (ServerUtils.IS_ON_WINDOWS) {
            throw new IllegalArgumentException("Not supported in Windows platform");
        }
        List<String> cmdArgs = new ArrayList<>();
        cmdArgs.add("id");
        cmdArgs.add("-u");
        if (user != null && !user.isEmpty()) {
            cmdArgs.add(user);
        }
        LOG.debug("CMD: {}", String.join(" ", cmdArgs));
        ProcessBuilder pb = new ProcessBuilder(cmdArgs);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        try (BufferedReader in = new BufferedReader(new InputStreamReader(pb.start().getInputStream(), StandardCharsets.UTF_8))) {
            String line = in.readLine();
            LOG.debug("CMD-LINE#1: {}", line);
            try {
                return Integer.parseInt(line.trim());
            } catch (NumberFormatException ex) {
                LOG.error("Expecting UID integer but got {} in output of \"id -u {}\" command", line, user);
                return -1;
            }
        } catch (IOException ex) {
            LOG.error(String.format("Cannot read output of command \"%s\"", String.join(" ", cmdArgs)), ex);
            return -1;
        }
    }

    /**
     * Get the userId of the onwer of the path by running "ls -dn path" command.
     * This command works on Posix systems only.
     *
     * @param fpath full path to the file or directory.
     * @return UID for the specified if successful, -1 upon failure.
     */
    public static int getPathOwnerUid(String fpath) {
        if (ServerUtils.IS_ON_WINDOWS) {
            throw new IllegalArgumentException("Not supported in Windows platform");
        }
        File f = new File(fpath);
        if (!f.exists()) {
            LOG.error("Cannot determine owner of non-existent file {}", fpath);
            return -1;
        }
        LOG.debug("CMD: ls -dn {}", fpath);
        ProcessBuilder pb = new ProcessBuilder("ls", "-dn", fpath);
        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
        try (BufferedReader in = new BufferedReader(new InputStreamReader(pb.start().getInputStream(), StandardCharsets.UTF_8))) {
            String line = in.readLine();
            LOG.debug("CMD-OUTLINE: {}", line);
            line = line.trim();
            String[] parts = line.split("\\s+");
            if (parts.length < 3) {
                LOG.error("Expecting at least 3 space separated fields in \"ls -dn {}\" output, got {}", fpath, line);
                return -1;
            }
            try {
                return Integer.parseInt(parts[2]);
            } catch (NumberFormatException ex) {
                LOG.error("Expecting at third field {} to be numeric UID \"ls -dn {}\" output, got {}", parts[2], fpath, line);
                return -1;
            }
        } catch (IOException ex) {
            LOG.error(String.format("Cannot read output of command \"ls -dn %s\"", fpath), ex);
            return -1;
        }
    }

    /**
     * Get UID of the owner to the workerId Root directory.
     *
     * @return User ID (UID) of owner of the workerId root directory, -1 if directory is missing.
     */
    private static int getWorkerPathOwnerUid(Map<String, Object> conf, String workerId) {
        return getPathOwnerUid(ConfigUtils.workerRoot(conf, workerId));
    }

    private static final Map<String, Integer> cachedUserToUidMap = new ConcurrentHashMap<>();

    /**
     * Find if all processes for the user on workId are dead.
     * This method attempts to optimize the calls by:
     * <p>
     *     <li>checking a collection of ProcessIds at once</li>
     *     <li>using userId one Posix systems instead of user</li>
     * </p>
     *
     * @return true if all processes for the user are dead on the worker
     * @throws IOException if external commands have exception.
     */
    public static boolean areAllProcessesDead(Map<String, Object> conf, String user, String workerId, Set<Long> pids) throws IOException {
        if (pids == null || pids.isEmpty()) {
            return true;
        }

        if (ServerUtils.IS_ON_WINDOWS) {
            return !isAnyProcessAlive(pids, user);
        }
        // optimized for Posix - first examine /proc and then use optimized version of "ps" with uid
        try {
            return !isAnyPosixProcessPidDirAlive(pids, user);
        } catch (IOException ex) {
            LOG.warn("Failed to determine if processes {} for user {} are dead using filesystem, will try \"ps\" command: {}",
                    pids, user, ex);
        }
        if (!cachedUserToUidMap.containsKey(user)) {
            int uid = ServerUtils.getWorkerPathOwnerUid(conf, workerId);
            if (uid < 0) {
                uid = ServerUtils.getUserId(user);
            }
            if (uid >= 0) {
                cachedUserToUidMap.put(user, uid);
            }
        }
        if (cachedUserToUidMap.containsKey(user)) {
            return !ServerUtils.isAnyProcessAlive(pids, cachedUserToUidMap.get(user));
        } else {
            return !ServerUtils.isAnyProcessAlive(pids, user);
        }
    }

    /**
     * Find if the process is alive using the existence of /proc/&lt;pid&gt; directory
     * owned by the supplied user. This is an alternative to "ps -p pid -u uid" command
     * used in {@link #isAnyPosixProcessAlive(Collection, int)}
     *
     * <p>
     * Processes are tracked using the existence of the directory "/proc/&lt;pid&gt;
     * For each of the supplied PIDs, their PID directory is checked for existence and ownership
     * by the specified uid.
     * </p>
     *
     * @param pids Process IDs that need to be monitored for liveness
     * @param user the userId that is expected to own that process
     * @return true if any one of the processes is owned by user and alive, else false
     * @throws IOException on I/O exception
     */
    public static boolean isAnyPosixProcessPidDirAlive(Collection<Long> pids, String user) throws IOException {
        return isAnyPosixProcessPidDirAlive(pids, user, false);
    }

    /**
     * Find if the process is alive using the existence of /proc/&lt;pid&gt; directory
     * owned by the supplied expectedUser. This is an alternative to "ps -p pid -u uid" command
     * used in {@link #isAnyPosixProcessAlive(Collection, int)}
     *
     * <p>
     * Processes are tracked using the existence of the directory "/proc/&lt;pid&gt;
     * For each of the supplied PIDs, their PID directory is checked for existence and ownership
     * by the specified uid.
     * </p>
     *
     * @param pids Process IDs that need to be monitored for liveness
     * @param expectedUser the userId that is expected to own that process
     * @param mockFileOwnerToUid if true (used for testing), then convert File.owner to UID
     * @return true if any one of the processes is owned by expectedUser and alive, else false
     * @throws IOException on I/O exception
     */
    @VisibleForTesting
    public static boolean isAnyPosixProcessPidDirAlive(Collection<Long> pids, String expectedUser, boolean mockFileOwnerToUid)
            throws IOException {
        File procDir = new File("/proc");
        if (!procDir.exists()) {
            throw new IOException("Missing process directory " + procDir.getAbsolutePath() + ": method not supported on "
                    + "os.name=" + System.getProperty("os.name"));
        }
        for (long pid: pids) {
            File pidDir = new File(procDir, String.valueOf(pid));
            if (!pidDir.exists()) {
                continue;
            }
            // check if existing process is owned by the specified expectedUser, if not, the process is dead
            String actualUser;
            try {
                actualUser = Files.getOwner(pidDir.toPath()).getName();
            } catch (NoSuchFileException ex) {
                continue; // process died before the expectedUser can be checked
            }
            if (mockFileOwnerToUid) {
                // code activated in testing to simulate Files.getOwner returning UID (which sometimes happens in runtime)
                if (StringUtils.isNumeric(actualUser)) {
                    LOG.info("Skip mocking, since owner {} of pidDir {} is already numeric", actualUser, pidDir);
                } else {
                    Integer actualUid = cachedUserToUidMap.get(actualUser);
                    if (actualUid == null) {
                        actualUid = ServerUtils.getUserId(actualUser);
                        if (actualUid < 0) {
                            String err = String.format("Cannot get UID for %s, while mocking the owner of pidDir %s",
                                    actualUser, pidDir.getAbsolutePath());
                            throw new IOException(err);
                        }
                        cachedUserToUidMap.put(actualUser, actualUid);
                        LOG.info("Found UID {} for {}, while mocking the owner of pidDir {}", actualUid, actualUser, pidDir);
                    } else {
                        LOG.info("Found cached UID {} for {}, while mocking the owner of pidDir {}", actualUid, actualUser, pidDir);
                    }
                    actualUser = String.valueOf(actualUid);
                }
            }
            //sometimes uid is returned instead of username - if so, try to convert and compare with uid
            if (StringUtils.isNumeric(actualUser)) {
                // numeric actualUser - this is UID not user
                LOG.debug("Process directory {} owner is uid={}", pidDir, actualUser);
                int actualUid = Integer.parseInt(actualUser);
                Integer expectedUid = cachedUserToUidMap.get(expectedUser);
                if (expectedUid == null) {
                    expectedUid = ServerUtils.getUserId(expectedUser);
                    if (expectedUid < 0) {
                        String err = String.format("Cannot get uid for %s to compare with owner id=%d of process directory %s",
                                expectedUser, actualUid, pidDir.getAbsolutePath());
                        throw new IOException(err);
                    }
                    cachedUserToUidMap.put(expectedUser, expectedUid);
                }
                if (expectedUid == actualUid) {
                    LOG.debug("Process {} is alive and owned by expectedUser {}/{}", pid, expectedUser, expectedUid);
                    return true;
                }
                LOG.info("Prior process is dead, since directory {} owner {} is not same as expectedUser {}/{}, "
                        + "likely pid {} was reused for a new process for uid {}, {}",
                        pidDir, actualUser, expectedUser, expectedUid, pid, actualUid, getProcessDesc(pidDir));
            } else {
                // actualUser is a string
                LOG.debug("Process directory {} owner is {}", pidDir, actualUser);
                if (expectedUser.equals(actualUser)) {
                    LOG.debug("Process {} is alive and owned by expectedUser {}", pid, expectedUser);
                    return true;
                }
                LOG.info("Prior process is dead, since directory {} owner {} is not same as expectedUser {}, "
                        + "likely pid {} was reused for a new process for actualUser {}, {}}",
                        pidDir, actualUser, expectedUser, pid, actualUser, getProcessDesc(pidDir));
            }
        }
        LOG.info("None of the processes {} are alive AND owned by expectedUser {}", pids, expectedUser);
        return false;
    }

    @VisibleForTesting
    public static void validateTopologyWorkerMaxHeapSizeConfigs(
        Map<String, Object> stormConf, StormTopology topology, double defaultWorkerMaxHeapSizeMb)
        throws InvalidTopologyException {

        double largestMemReq = getMaxExecutorMemoryUsageForTopo(topology, stormConf);
        double topologyWorkerMaxHeapSize =
            ObjectReader.getDouble(stormConf.get(Config.TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB), defaultWorkerMaxHeapSizeMb);
        if (topologyWorkerMaxHeapSize < largestMemReq) {
            throw new InvalidTopologyException(
                "Topology will not be able to be successfully scheduled: Config "
                    + "TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB="
                    + topologyWorkerMaxHeapSize
                    + " < " + largestMemReq + " (Largest memory requirement of a component in the topology)."
                    + " Perhaps set TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB to a larger amount");
        }
    }

    /**
     * RAS scheduler will try to distribute ackers evenly over workers by adding some ackers to each newly launched worker.
     * Validations are performed here:
     * ({@link Config#TOPOLOGY_RAS_ACKER_EXECUTORS_PER_WORKER} * memory for an acker
     *      + memory for the biggest topo executor) < max worker heap memory.
     *    When RAS tries to schedule an executor to a new worker,
     *    it will put {@link Config#TOPOLOGY_RAS_ACKER_EXECUTORS_PER_WORKER} ackers into the worker first.
     *    So {@link Config#TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB} need to be able to accommodate this.
     * @param topoConf Topology conf
     * @param topology Topology (not system topology)
     * @param topoName The name of the topology
     */
    public static void validateTopologyAckerBundleResource(Map<String, Object> topoConf,
                                                           StormTopology topology, String topoName)
        throws InvalidTopologyException {

        boolean oneExecutorPerWorker = (Boolean) topoConf.getOrDefault(Config.TOPOLOGY_RAS_ONE_EXECUTOR_PER_WORKER, false);
        boolean oneComponentPerWorker = (Boolean) topoConf.getOrDefault(Config.TOPOLOGY_RAS_ONE_COMPONENT_PER_WORKER, false);

        double topologyWorkerMaxHeapSize =
            ObjectReader.getDouble(topoConf.get(Config.TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB));

        int numOfAckerExecutorsPerWorker = ObjectReader.getInt(topoConf.get(Config.TOPOLOGY_RAS_ACKER_EXECUTORS_PER_WORKER));
        double maxTopoExecMem = getMaxExecutorMemoryUsageForTopo(topology, topoConf);
        double ackerExecMem = getAckerExecutorMemoryUsageForTopo(topology, topoConf);
        double minMemReqForWorker = maxTopoExecMem + ackerExecMem * numOfAckerExecutorsPerWorker;

        // A worker need to have enough resources for a bigest topo executor + topology.acker.executors.per.worker ackers
        if (!oneExecutorPerWorker
            && !oneComponentPerWorker
            && topologyWorkerMaxHeapSize < minMemReqForWorker) {
            String warnMsg
                = String.format("For topology %s. Worker max on-heap limit %s is %s. "
                    + "The biggest topo executor requires %s MB on-heap memory, "
                    + "there might not be enough space for %s ackers. "
                    + "Real acker-per-worker will be determined by scheduler.",
                    topoName, Config.TOPOLOGY_WORKER_MAX_HEAP_SIZE_MB, topologyWorkerMaxHeapSize,
                    maxTopoExecMem, numOfAckerExecutorsPerWorker);
            LOG.warn(warnMsg);
        }
    }

    private static double getMaxExecutorMemoryUsageForTopo(
        StormTopology topology, Map<String, Object> topologyConf) {
        double largestMemoryOperator = 0.0;
        for (NormalizedResourceRequest entry :
            ResourceUtils.getBoltsResources(topology, topologyConf).values()) {
            double memoryRequirement = entry.getTotalMemoryMb();
            if (memoryRequirement > largestMemoryOperator) {
                largestMemoryOperator = memoryRequirement;
            }
        }
        for (NormalizedResourceRequest entry :
            ResourceUtils.getSpoutsResources(topology, topologyConf).values()) {
            double memoryRequirement = entry.getTotalMemoryMb();
            if (memoryRequirement > largestMemoryOperator) {
                largestMemoryOperator = memoryRequirement;
            }
        }
        return largestMemoryOperator;
    }

    private static double getAckerExecutorMemoryUsageForTopo(
        StormTopology topology, Map<String, Object> topologyConf)
        throws InvalidTopologyException {
        topology = StormCommon.systemTopology(topologyConf, topology);
        Map<String, NormalizedResourceRequest> boltResources = ResourceUtils.getBoltsResources(topology, topologyConf);
        NormalizedResourceRequest entry = boltResources.get(Acker.ACKER_COMPONENT_ID);
        return entry.getTotalMemoryMb();
    }

    /**
     * Support method to obtain additional log info for the process. Use the contents of comm and cmdline
     * in the process directory. Note that this method works properly only on posix systems with /proc directory.
     *
     * @param pidDir PID directory (/proc/&lt;pid&gt;)
     * @return process description string
     */
    private static String getProcessDesc(File pidDir) {
        String comm = "";
        Path p = pidDir.toPath().resolve("comm");
        try {
            comm = String.join(", ", Files.readAllLines(p));
        } catch (IOException ex) {
            LOG.warn("Cannot get contents of " + p, ex);
        }
        String cmdline = "";
        p = pidDir.toPath().resolve("cmdline");
        try {
            cmdline = String.join(", ", Files.readAllLines(p)).replace('\0', ' ');
        } catch (IOException ex) {
            LOG.warn("Cannot get contents of " + p, ex);
        }
        return String.format("process(comm=\"%s\", cmdline=\"%s\")", comm, cmdline);
    }
}
