eu.stratosphere.nephele.io.compression.CompressionLoader.java Source code

Java tutorial

Introduction

Here is the source code for eu.stratosphere.nephele.io.compression.CompressionLoader.java

Source

/***********************************************************************************************************************
 *
 * Copyright (C) 2010 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.io.compression;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

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

import eu.stratosphere.nephele.configuration.ConfigConstants;
import eu.stratosphere.nephele.configuration.GlobalConfiguration;
import eu.stratosphere.nephele.util.StringUtils;

public class CompressionLoader {

    private static final Log LOG = LogFactory.getLog(CompressionLoader.class);

    private static final Map<CompressionLevel, CompressionLibrary> compressionLibraries = new HashMap<CompressionLevel, CompressionLibrary>();

    private static final String NATIVELIBRARYCACHENAME = "nativeLibraryCache";

    public static synchronized void init(final CompressionLevel compressionLevel) {

        // Return immediately, if implementation for compression level has already been loaded
        if (compressionLibraries.containsKey(compressionLevel)) {
            return;
        }

        String keySuffix = null;
        switch (compressionLevel) {
        case LIGHT_COMPRESSION:
            keySuffix = "lightClass";
            break;
        case MEDIUM_COMPRESSION:
            keySuffix = "mediumClass";
            break;
        case HEAVY_COMPRESSION:
            keySuffix = "heavyClass";
            break;
        case DYNAMIC_COMPRESSION:
            keySuffix = "dynamicClass";
            break;
        }

        if (keySuffix == null) {
            throw new RuntimeException("Cannot find keySuffix for compression level " + compressionLevel);
        }

        final String key = "channel.compression." + keySuffix;
        final String libraryClass = GlobalConfiguration.getString(key, null);
        if (libraryClass == null) {
            throw new RuntimeException(
                    "No library class for compression Level " + compressionLevel + " configured");
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug("Trying to load compression library " + libraryClass);
        }

        final CompressionLibrary compressionLibrary = initCompressionLibrary(libraryClass);
        if (compressionLibrary == null) {
            throw new RuntimeException("Cannot load " + libraryClass);
        }

        compressionLibraries.put(compressionLevel, compressionLibrary);
    }

    /**
     * Returns the path to the native libraries or <code>null</code> if an error occurred.
     * 
     * @param libraryClass
     *        the name of this compression library's wrapper class including full package name
     * @return the path to the native libraries or <code>null</code> if an error occurred
     */
    private static String getNativeLibraryPath(final String libraryClass) {

        final ClassLoader cl = ClassLoader.getSystemClassLoader();
        if (cl == null) {
            LOG.error("Cannot find system class loader");
            return null;
        }

        final String classLocation = libraryClass.replace('.', '/') + ".class";
        if (LOG.isDebugEnabled()) {
            LOG.debug("Class location is " + classLocation);
        }

        final URL location = cl.getResource(classLocation);
        if (location == null) {
            LOG.error("Cannot determine location of CompressionLoader class");
            return null;
        }

        final String locationString = location.toString();
        if (locationString.contains(".jar!")) { // Class if inside of a deployed jar file

            // Create and return path to native library cache
            final String pathName = GlobalConfiguration
                    .getString(ConfigConstants.TASK_MANAGER_TMP_DIR_KEY,
                            ConfigConstants.DEFAULT_TASK_MANAGER_TMP_PATH)
                    .split(File.pathSeparator)[0] + File.separator + NATIVELIBRARYCACHENAME;

            final File path = new File(pathName);
            if (!path.exists()) {
                if (!path.mkdir()) {
                    LOG.error("Cannot create directory for native library cache.");
                    return null;
                }
            }

            return pathName;

        } else {

            String result = "";

            int pos = locationString.indexOf(classLocation);
            if (pos < 0) {
                LOG.error("Cannot find extract native path from class location");
                return null;
            }

            result = locationString.substring(0, pos) + "META-INF/lib";

            // Strip the file:/ scheme, it confuses the class loader
            if (result.startsWith("file:")) {
                result = result.substring(5);
            }

            return result;
        }
    }

    @SuppressWarnings("unchecked")
    private static CompressionLibrary initCompressionLibrary(String libraryClass) {

        Class<? extends CompressionLibrary> compressionLibraryClass;
        try {
            compressionLibraryClass = (Class<? extends CompressionLibrary>) Class.forName(libraryClass);
        } catch (ClassNotFoundException e1) {
            LOG.error(e1);
            return null;
        }

        if (compressionLibraryClass == null) {
            LOG.error("Cannot load compression library " + libraryClass);
            return null;
        }

        Constructor<? extends CompressionLibrary> constructor;
        try {
            constructor = compressionLibraryClass.getConstructor(String.class);
        } catch (SecurityException e) {
            LOG.error(e);
            return null;
        } catch (NoSuchMethodException e) {
            LOG.error(e);
            return null;
        }
        if (constructor == null) {
            LOG.error("Cannot find matching constructor for class " + compressionLibraryClass.toString());
            return null;
        }

        CompressionLibrary compressionLibrary;

        try {
            compressionLibrary = constructor.newInstance(getNativeLibraryPath(libraryClass));
        } catch (IllegalArgumentException e) {
            LOG.error(StringUtils.stringifyException(e));
            return null;
        } catch (InstantiationException e) {
            LOG.error(StringUtils.stringifyException(e));
            return null;
        } catch (IllegalAccessException e) {
            LOG.error(StringUtils.stringifyException(e));
            return null;
        } catch (InvocationTargetException e) {
            LOG.error(StringUtils.stringifyException(e));
            return null;
        }

        return compressionLibrary;
    }

    public static synchronized CompressionLibrary getCompressionLibraryByCompressionLevel(CompressionLevel level) {

        if (level == CompressionLevel.NO_COMPRESSION) {
            return null;
        }

        init(level);

        final CompressionLibrary cl = compressionLibraries.get(level);
        if (cl == null) {
            LOG.error("Cannot find compression library for compression level " + level);
            return null;
        }

        return cl;
    }

    public static synchronized Compressor getCompressorByCompressionLevel(final CompressionLevel level,
            final CompressionBufferProvider compressionBufferProvider) {

        if (level == CompressionLevel.NO_COMPRESSION) {
            return null;
        }

        init(level);

        try {

            final CompressionLibrary cl = compressionLibraries.get(level);
            if (cl == null) {
                LOG.error("Cannot find compression library for compression level " + level);
                return null;
            }

            return cl.createNewCompressor(compressionBufferProvider);

        } catch (CompressionException e) {
            LOG.error("Cannot load native compressor: " + StringUtils.stringifyException(e));
            return null;
        }
    }

    public static synchronized Decompressor getDecompressorByCompressionLevel(final CompressionLevel level,
            final CompressionBufferProvider compressionBufferProvider) {

        if (level == CompressionLevel.NO_COMPRESSION) {
            return null;
        }

        init(level);

        try {

            final CompressionLibrary cl = compressionLibraries.get(level);
            if (cl == null) {
                LOG.error("Cannot find compression library for compression level " + level);
                return null;
            }

            return cl.createNewDecompressor(compressionBufferProvider);

        } catch (CompressionException e) {
            LOG.error("Cannot load native decompressor: " + StringUtils.stringifyException(e));
            return null;
        }
    }

    public static synchronized int getUncompressedBufferSize(int compressedBufferSize, CompressionLevel cl) {

        final CompressionLibrary c = compressionLibraries.get(cl);
        if (c == null) {
            LOG.error("Cannot find compression library for compression level " + cl);
            return compressedBufferSize;
        }

        return c.getUncompressedBufferSize(compressedBufferSize);
    }

    // public static synchronized int getCompressedBufferSize(int uncompressedBufferSize, CompressionLevel cl) {
    // switch (cl) {
    // case HEAVY_COMPRESSION:
    // /*
    // * Calculate size of compressed data buffer according to
    // * http://gpwiki.org/index.php/LZO
    // */
    // // TODO check that for LZMA
    // return uncompressedBufferSize + ((uncompressedBufferSize / 1024) * 16);
    // case MEDIUM_COMPRESSION:
    // /*
    // * Calculate size of compressed data buffer according to
    // * zlib manual
    // * http://www.zlib.net/zlib_tech.html
    // */
    // return uncompressedBufferSize + (int) ((uncompressedBufferSize / 100) * 0.04) + 6;
    // case DYNAMIC_COMPRESSION:
    // case LIGHT_COMPRESSION:
    // /*
    // * Calculate size of compressed data buffer according to
    // * LZO Manual http://www.oberhumer.com/opensource/lzo/lzofaq.php
    // */
    // return uncompressedBufferSize + (uncompressedBufferSize / 16) + 64 + 3;
    // default:
    // return uncompressedBufferSize;
    // }
    // }
}