eu.stratosphere.nephele.instance.HardwareDescriptionFactory.java Source code

Java tutorial

Introduction

Here is the source code for eu.stratosphere.nephele.instance.HardwareDescriptionFactory.java

Source

/***********************************************************************************************************************
 * Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
 *
 * 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 eu.stratosphere.nephele.instance;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import eu.stratosphere.configuration.ConfigConstants;
import eu.stratosphere.configuration.GlobalConfiguration;
import eu.stratosphere.util.OperatingSystem;

/**
 * A factory to construct {@link HardwareDescription} objects. In particular,
 * the factory can automatically generate a {@link HardwareDescription} object
 * from the system it is executed on.
 * <p>
 * This class is thread-safe.
 */
public class HardwareDescriptionFactory {

    /**
     * The log object used to report errors.
     */
    private static final Log LOG = LogFactory.getLog(HardwareDescriptionFactory.class);

    /**
     * The path to the interface to extract memory information under Linux.
     */
    private static final String LINUX_MEMORY_INFO_PATH = "/proc/meminfo";

    /**
     * The regular expression used to extract the size of the physical memory
     * under Linux.
     */
    private static final Pattern LINUX_MEMORY_REGEX = Pattern.compile("^MemTotal:\\s*(\\d+)\\s+kB$");

    /**
     * Private constructor, so class cannot be instantiated.
     */
    private HardwareDescriptionFactory() {
    }

    /**
     * Extracts a hardware description object from the system.
     * 
     * @return the hardware description object or <code>null</code> if at least
     *         one value for the hardware description cannot be determined
     */
    public static HardwareDescription extractFromSystem() {
        int numberOfCPUCores = Runtime.getRuntime().availableProcessors();

        long sizeOfPhysicalMemory = getSizeOfPhysicalMemory();
        if (sizeOfPhysicalMemory < 0) {
            sizeOfPhysicalMemory = 1;
        }

        long sizeOfFreeMemory = getSizeOfFreeMemory();

        return new HardwareDescription(numberOfCPUCores, sizeOfPhysicalMemory, sizeOfFreeMemory);
    }

    /**
     * Constructs a new hardware description object.
     * 
     * @param numberOfCPUCores
     *        the number of CPU cores available to the JVM on the compute
     *        node
     * @param sizeOfPhysicalMemory
     *        the size of physical memory in bytes available on the compute
     *        node
     * @param sizeOfFreeMemory
     *        the size of free memory in bytes available to the JVM on the
     *        compute node
     * @return the hardware description object
     */
    public static HardwareDescription construct(int numberOfCPUCores, long sizeOfPhysicalMemory,
            long sizeOfFreeMemory) {
        return new HardwareDescription(numberOfCPUCores, sizeOfPhysicalMemory, sizeOfFreeMemory);
    }

    /**
     * Returns the size of free memory in bytes available to the JVM.
     * 
     * @return the size of the free memory in bytes available to the JVM or <code>-1</code> if the size cannot be
     *         determined
     */
    private static long getSizeOfFreeMemory() {
        float fractionToUse = GlobalConfiguration.getFloat(ConfigConstants.TASK_MANAGER_MEMORY_FRACTION_KEY,
                ConfigConstants.DEFAULT_MEMORY_MANAGER_MEMORY_FRACTION);

        Runtime r = Runtime.getRuntime();
        long max = r.maxMemory();
        long total = r.totalMemory();
        long free = r.freeMemory();

        long available = max - total + free;
        return (long) (fractionToUse * available);
    }

    /**
     * Returns the size of the physical memory in bytes.
     * 
     * @return the size of the physical memory in bytes or <code>-1</code> if
     *         the size could not be determined
     */
    private static long getSizeOfPhysicalMemory() {
        switch (OperatingSystem.getCurrentOperatingSystem()) {
        case LINUX:
            return getSizeOfPhysicalMemoryForLinux();

        case WINDOWS:
            return getSizeOfPhysicalMemoryForWindows();

        case MAC_OS:
            return getSizeOfPhysicalMemoryForMac();

        case FREE_BSD:
            return getSizeOfPhysicalMemoryForFreeBSD();

        case UNKNOWN:
            LOG.error("Cannot determine size of physical memory for unknown operating system");
            return -1;

        default:
            LOG.error("Unrecognized OS");
            return -1;
        }
    }

    /**
     * Returns the size of the physical memory in bytes on a Linux-based
     * operating system.
     * 
     * @return the size of the physical memory in bytes or <code>-1</code> if
     *         the size could not be determined
     */
    @SuppressWarnings("resource")
    private static long getSizeOfPhysicalMemoryForLinux() {
        BufferedReader lineReader = null;
        try {
            lineReader = new BufferedReader(new FileReader(LINUX_MEMORY_INFO_PATH));

            String line = null;
            while ((line = lineReader.readLine()) != null) {
                Matcher matcher = LINUX_MEMORY_REGEX.matcher(line);
                if (matcher.matches()) {
                    String totalMemory = matcher.group(1);
                    return Long.parseLong(totalMemory) * 1024L; // Convert from kilobyte to byte
                }
            }

            // expected line did not come
            LOG.error("Cannot determine the size of the physical memory using '/proc/meminfo'. Unexpected format.");
            return -1;
        } catch (NumberFormatException e) {
            LOG.error("Cannot determine the size of the physical memory using '/proc/meminfo'. Unexpected format.");
            return -1;
        } catch (IOException e) {
            LOG.error("Cannot determine the size of the physical memory using '/proc/meminfo': " + e.getMessage(),
                    e);
            return -1;
        } finally {
            // Make sure we always close the file handle
            try {
                if (lineReader != null) {
                    lineReader.close();
                }
            } catch (Throwable t) {
            }
        }
    }

    /**
     * Returns the size of the physical memory in bytes on a Mac OS-based
     * operating system
     * 
     * @return the size of the physical memory in bytes or <code>-1</code> if
     *         the size could not be determined
     */
    private static long getSizeOfPhysicalMemoryForMac() {

        BufferedReader bi = null;

        try {
            Process proc = Runtime.getRuntime().exec("sysctl hw.memsize");

            bi = new BufferedReader(new InputStreamReader(proc.getInputStream()));

            String line;

            while ((line = bi.readLine()) != null) {
                if (line.startsWith("hw.memsize")) {
                    long memsize = Long.parseLong(line.split(":")[1].trim());
                    bi.close();
                    proc.destroy();
                    return memsize;
                }
            }

        } catch (Exception e) {
            LOG.error(e);
            return -1;
        } finally {
            if (bi != null) {
                try {
                    bi.close();
                } catch (IOException ioe) {
                }
            }
        }
        return -1;
    }

    /**
     * Returns the size of the physical memory in bytes on FreeBSD.
     * 
     * @return the size of the physical memory in bytes or <code>-1</code> if
     *         the size could not be determined
     */
    private static long getSizeOfPhysicalMemoryForFreeBSD() {
        BufferedReader bi = null;
        try {
            Process proc = Runtime.getRuntime().exec("sysctl hw.physmem");

            bi = new BufferedReader(new InputStreamReader(proc.getInputStream()));

            String line;

            while ((line = bi.readLine()) != null) {
                if (line.startsWith("hw.physmem")) {
                    long memsize = Long.parseLong(line.split(":")[1].trim());
                    bi.close();
                    proc.destroy();
                    return memsize;
                }
            }

            LOG.error("Cannot determine the size of the physical memory using 'sysctl hw.physmem'.");
            return -1;
        } catch (Exception e) {
            LOG.error(
                    "Cannot determine the size of the physical memory using 'sysctl hw.physmem': " + e.getMessage(),
                    e);
            return -1;
        } finally {
            if (bi != null) {
                try {
                    bi.close();
                } catch (IOException ioe) {
                }
            }
        }
    }

    /**
     * Returns the size of the physical memory in bytes on Windows.
     * 
     * @return the size of the physical memory in bytes or <code>-1</code> if
     *         the size could not be determined
     */
    private static long getSizeOfPhysicalMemoryForWindows() {
        BufferedReader bi = null;
        try {
            Process proc = Runtime.getRuntime().exec("wmic memorychip get capacity");

            bi = new BufferedReader(new InputStreamReader(proc.getInputStream()));

            String line = bi.readLine();
            if (line == null) {
                return -1L;
            }

            if (!line.startsWith("Capacity")) {
                return -1L;
            }

            long sizeOfPhyiscalMemory = 0L;
            while ((line = bi.readLine()) != null) {
                if (line.isEmpty()) {
                    continue;
                }

                line = line.replaceAll(" ", "");
                sizeOfPhyiscalMemory += Long.parseLong(line);
            }
            return sizeOfPhyiscalMemory;
        } catch (Exception e) {
            LOG.error("Cannot determine the size of the physical memory using 'wmic memorychip': " + e.getMessage(),
                    e);
            return -1L;
        } finally {
            if (bi != null) {
                try {
                    bi.close();
                } catch (Throwable t) {
                }
            }
        }
    }
}