diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/util/ClassLoaderTestHelper.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/util/ClassLoaderTestHelper.java index fd771c722b8..decc0da2e9b 100644 --- a/hbase-common/src/test/java/org/apache/hadoop/hbase/util/ClassLoaderTestHelper.java +++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/util/ClassLoaderTestHelper.java @@ -213,7 +213,7 @@ public final class ClassLoaderTestHelper { LOG.info("Adding jar file to outer jar file completed"); } - static String localDirPath(Configuration conf) { + public static String localDirPath(Configuration conf) { return conf.get(ClassLoaderBase.LOCAL_DIR_KEY) + File.separator + "jars" + File.separator; } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java index 44250763005..319936d9ebf 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java @@ -46,6 +46,7 @@ import org.apache.hadoop.hbase.ipc.RpcServer; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.util.CoprocessorClassLoader; import org.apache.hadoop.hbase.util.SortedList; +import org.apache.hbase.thirdparty.com.google.common.base.Strings; /** * Provides the common setup framework and runtime services for coprocessor @@ -144,14 +145,22 @@ public abstract class CoprocessorHost 1){ - overridePriority = Integer.parseInt(classNameAndPriority[1]); + Path path = null; + if (classNameToken.length > 1 && !Strings.isNullOrEmpty(classNameToken[1])) { + overridePriority = Integer.parseInt(classNameToken[1]); hasPriorityOverride = true; } + if (classNameToken.length > 2 && !Strings.isNullOrEmpty(classNameToken[2])) { + path = new Path(classNameToken[2].trim()); + hasPath = true; + } className = className.trim(); if (findCoprocessor(className) != null) { // If already loaded will just continue @@ -159,8 +168,13 @@ public abstract class CoprocessorHost> host; + host = new CoprocessorHostForTest<>(conf); + + // make a string of coprocessor with only priority + int overridePriority = Integer.MAX_VALUE - 1; + final String coprocessorWithPriority = + SimpleRegionObserverV3.class.getName() + "|" + overridePriority; + // make a string of coprocessor with path but no priority + final String coprocessorWithPath = + String.format("%s|%s|%s", testClassName, "", jarFile.getAbsolutePath()); + // make a string of coprocessor with priority and path + final String coprocessorWithPriorityAndPath = String + .format("%s|%s|%s", testClassNameWithPriorityAndPath, (overridePriority - 1), + jarFileWithPriorityAndPath.getAbsolutePath()); + + // Try and load a system coprocessors + conf.setStrings(key, SimpleRegionObserverV2.class.getName(), coprocessorWithPriority, + coprocessorWithPath, coprocessorWithPriorityAndPath); + host.loadSystemCoprocessors(conf, key); + + // first loaded system coprocessor with default priority + CoprocessorEnvironment simpleEnv = + host.findCoprocessorEnvironment(SimpleRegionObserverV2.class.getName()); + assertNotNull(simpleEnv); + assertEquals(Coprocessor.PRIORITY_SYSTEM, simpleEnv.getPriority()); + + // external system coprocessor with default priority + CoprocessorEnvironment coprocessorEnvironmentWithPath = + host.findCoprocessorEnvironment(testClassName); + assertNotNull(coprocessorEnvironmentWithPath); + assertEquals(Coprocessor.PRIORITY_SYSTEM + 1, coprocessorEnvironmentWithPath.getPriority()); + + // system coprocessor with configured priority + CoprocessorEnvironment coprocessorEnvironmentWithPriority = + host.findCoprocessorEnvironment(SimpleRegionObserverV3.class.getName()); + assertNotNull(coprocessorEnvironmentWithPriority); + assertEquals(overridePriority, coprocessorEnvironmentWithPriority.getPriority()); + + // external system coprocessor with override priority + CoprocessorEnvironment coprocessorEnvironmentWithPriorityAndPath = + host.findCoprocessorEnvironment(testClassNameWithPriorityAndPath); + assertNotNull(coprocessorEnvironmentWithPriorityAndPath); + assertEquals(overridePriority - 1, coprocessorEnvironmentWithPriorityAndPath.getPriority()); + } finally { + if (jarFile.exists()) { + jarFile.delete(); + } + if (jarFileWithPriorityAndPath.exists()) { + jarFileWithPriorityAndPath.delete(); + } + } + } + + @Test(expected = AssertionError.class) + public void testLoadSystemCoprocessorWithPathDoesNotExist() throws Exception { + Configuration conf = TEST_UTIL.getConfiguration(); + final String key = "KEY"; + final String testClassName = "TestSystemCoprocessor"; + + CoprocessorHost> host; + host = new CoprocessorHostForTest<>(conf); + + // make a string of coprocessor with path but no priority + final String coprocessorWithPath = testClassName + "||" + testClassName + ".jar"; + + // Try and load a system coprocessors + conf.setStrings(key, coprocessorWithPath); + // when loading non-exist with CoprocessorHostForTest host, it aborts with AssertionError + host.loadSystemCoprocessors(conf, key); + } + + @Test(expected = AssertionError.class) + public void testLoadSystemCoprocessorWithPathDoesNotExistAndPriority() throws Exception { + Configuration conf = TEST_UTIL.getConfiguration(); + final String key = "KEY"; + final String testClassName = "TestSystemCoprocessor"; + + CoprocessorHost> host; + host = new CoprocessorHostForTest<>(conf); + + int overridePriority = Integer.MAX_VALUE - 1; + // make a string of coprocessor with path and priority + final String coprocessor = + testClassName + "|" + overridePriority + "|" + testClassName + ".jar"; + + // Try and load a system coprocessors + conf.setStrings(key, coprocessor); + // when loading non-exist coprocessor, it aborts with AssertionError + host.loadSystemCoprocessors(conf, key); + } + public static class SimpleRegionObserverV2 extends SimpleRegionObserver { } public static class SimpleRegionObserverV3 extends SimpleRegionObserver { @@ -128,4 +235,11 @@ public class TestCoprocessorHost { return new BaseEnvironment<>(instance, priority, 0, cpHostConf); } } + + private File buildCoprocessorJar(String className) throws Exception { + String dataTestDir = TEST_UTIL.getDataTestDir().toString(); + String code = String.format("import org.apache.hadoop.hbase.coprocessor.*; public class %s" + + " implements RegionCoprocessor {}", className); + return ClassLoaderTestHelper.buildJar(dataTestDir, className, code); + } }