From 1396fa2a2727b8a678628d59768b355845eeb9a9 Mon Sep 17 00:00:00 2001 From: Gera Shegalov Date: Tue, 17 Jul 2018 00:05:39 -0700 Subject: [PATCH] HADOOP-15612. Improve exception when tfile fails to load LzoCodec. (gera) (cherry picked from commit 6bec03cfc8bdcf6aa3df9c22231ab959ba31f2f5) --- .../hadoop/io/file/tfile/Compression.java | 31 +++++++++++------ .../hadoop/io/file/tfile/TestCompression.java | 34 ++++++++++++++++++- 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/file/tfile/Compression.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/file/tfile/Compression.java index fa85ed77a1f..c4347e0c1af 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/file/tfile/Compression.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/file/tfile/Compression.java @@ -5,9 +5,9 @@ * 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 @@ -24,6 +24,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import com.google.common.annotations.VisibleForTesting; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.compress.CodecPool; import org.apache.hadoop.io.compress.CompressionCodec; @@ -78,25 +79,33 @@ public final class Compression { public enum Algorithm { LZO(TFile.COMPRESSION_LZO) { private transient boolean checked = false; + private transient ClassNotFoundException cnf; + private transient boolean reinitCodecInTests; private static final String defaultClazz = "org.apache.hadoop.io.compress.LzoCodec"; + private transient String clazz; private transient CompressionCodec codec = null; + private String getLzoCodecClass() { + String extClazzConf = conf.get(CONF_LZO_CLASS); + String extClazz = (extClazzConf != null) ? + extClazzConf : System.getProperty(CONF_LZO_CLASS); + return (extClazz != null) ? extClazz : defaultClazz; + } + @Override public synchronized boolean isSupported() { - if (!checked) { + if (!checked || reinitCodecInTests) { checked = true; - String extClazzConf = conf.get(CONF_LZO_CLASS); - String extClazz = (extClazzConf != null) ? - extClazzConf : System.getProperty(CONF_LZO_CLASS); - String clazz = (extClazz != null) ? extClazz : defaultClazz; + reinitCodecInTests = conf.getBoolean("test.reload.lzo.codec", false); + clazz = getLzoCodecClass(); try { LOG.info("Trying to load Lzo codec class: " + clazz); codec = (CompressionCodec) ReflectionUtils.newInstance(Class .forName(clazz), conf); } catch (ClassNotFoundException e) { - // that is okay + cnf = e; } } return codec != null; @@ -105,9 +114,9 @@ public final class Compression { @Override CompressionCodec getCodec() throws IOException { if (!isSupported()) { - throw new IOException( - "LZO codec class not specified. Did you forget to set property " - + CONF_LZO_CLASS + "?"); + throw new IOException(String.format( + "LZO codec %s=%s could not be loaded", CONF_LZO_CLASS, clazz), + cnf); } return codec; diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/file/tfile/TestCompression.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/file/tfile/TestCompression.java index ff6c72a8bbd..b1bf0774974 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/file/tfile/TestCompression.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/file/tfile/TestCompression.java @@ -17,14 +17,28 @@ */ package org.apache.hadoop.io.file.tfile; -import org.junit.Test; +import org.apache.hadoop.io.compress.CompressionCodec; +import org.apache.hadoop.test.LambdaTestUtils; +import org.junit.*; import java.io.IOException; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public class TestCompression { + @BeforeClass + public static void resetConfigBeforeAll() { + Compression.Algorithm.LZO.conf.setBoolean("test.reload.lzo.codec", true); + } + + @AfterClass + public static void resetConfigAfterAll() { + Compression.Algorithm.LZO.conf.setBoolean("test.reload.lzo.codec", false); + } + /** * Regression test for HADOOP-11418. * Verify we can set a LZO codec different from default LZO codec. @@ -38,4 +52,22 @@ public class TestCompression { assertEquals(defaultCodec, Compression.Algorithm.LZO.getCodec().getClass().getName()); } + + + @Test + public void testMisconfiguredLZOCodec() throws Exception { + // Dummy codec + String defaultCodec = "org.apache.hadoop.io.compress.InvalidLzoCodec"; + Compression.Algorithm.conf.set( + Compression.Algorithm.CONF_LZO_CLASS, defaultCodec); + IOException ioEx = LambdaTestUtils.intercept( + IOException.class, + defaultCodec, + () -> Compression.Algorithm.LZO.getCodec()); + + if (!(ioEx.getCause() instanceof ClassNotFoundException)) { + throw ioEx; + } + } + }