HBASE-26729 Backport "HBASE-26714 Introduce path configuration for system coprocessors" to branch-2 (#4093)
- rename from HBaseCommonTestingUtil to HBaseCommonTestingUtility Signed-off-by: Ankit Singhal <ankit@apache.org>
This commit is contained in:
parent
590e38e8e4
commit
b8db5ac24c
|
@ -213,7 +213,7 @@ public final class ClassLoaderTestHelper {
|
||||||
LOG.info("Adding jar file to outer jar file completed");
|
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)
|
return conf.get(ClassLoaderBase.LOCAL_DIR_KEY)
|
||||||
+ File.separator + "jars" + File.separator;
|
+ File.separator + "jars" + File.separator;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.apache.hadoop.hbase.ipc.RpcServer;
|
||||||
import org.apache.hadoop.hbase.security.User;
|
import org.apache.hadoop.hbase.security.User;
|
||||||
import org.apache.hadoop.hbase.util.CoprocessorClassLoader;
|
import org.apache.hadoop.hbase.util.CoprocessorClassLoader;
|
||||||
import org.apache.hadoop.hbase.util.SortedList;
|
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
|
* Provides the common setup framework and runtime services for coprocessor
|
||||||
|
@ -144,14 +145,22 @@ public abstract class CoprocessorHost<C extends Coprocessor, E extends Coprocess
|
||||||
|
|
||||||
int currentSystemPriority = Coprocessor.PRIORITY_SYSTEM;
|
int currentSystemPriority = Coprocessor.PRIORITY_SYSTEM;
|
||||||
for (String className : defaultCPClasses) {
|
for (String className : defaultCPClasses) {
|
||||||
String[] classNameAndPriority = className.split("\\|");
|
// After HBASE-23710 and HBASE-26714 when configuring for system coprocessor, we accept
|
||||||
|
// an optional format of className|priority|path
|
||||||
|
String[] classNameToken = className.split("\\|");
|
||||||
boolean hasPriorityOverride = false;
|
boolean hasPriorityOverride = false;
|
||||||
className = classNameAndPriority[0];
|
boolean hasPath = false;
|
||||||
|
className = classNameToken[0];
|
||||||
int overridePriority = Coprocessor.PRIORITY_SYSTEM;
|
int overridePriority = Coprocessor.PRIORITY_SYSTEM;
|
||||||
if (classNameAndPriority.length > 1){
|
Path path = null;
|
||||||
overridePriority = Integer.parseInt(classNameAndPriority[1]);
|
if (classNameToken.length > 1 && !Strings.isNullOrEmpty(classNameToken[1])) {
|
||||||
|
overridePriority = Integer.parseInt(classNameToken[1]);
|
||||||
hasPriorityOverride = true;
|
hasPriorityOverride = true;
|
||||||
}
|
}
|
||||||
|
if (classNameToken.length > 2 && !Strings.isNullOrEmpty(classNameToken[2])) {
|
||||||
|
path = new Path(classNameToken[2].trim());
|
||||||
|
hasPath = true;
|
||||||
|
}
|
||||||
className = className.trim();
|
className = className.trim();
|
||||||
if (findCoprocessor(className) != null) {
|
if (findCoprocessor(className) != null) {
|
||||||
// If already loaded will just continue
|
// If already loaded will just continue
|
||||||
|
@ -159,8 +168,13 @@ public abstract class CoprocessorHost<C extends Coprocessor, E extends Coprocess
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ClassLoader cl = this.getClass().getClassLoader();
|
ClassLoader cl = this.getClass().getClassLoader();
|
||||||
Thread.currentThread().setContextClassLoader(cl);
|
|
||||||
try {
|
try {
|
||||||
|
// override the class loader if a path for the system coprocessor is provided.
|
||||||
|
if (hasPath) {
|
||||||
|
cl = CoprocessorClassLoader.getClassLoader(path, this.getClass().getClassLoader(),
|
||||||
|
pathPrefix, conf);
|
||||||
|
}
|
||||||
|
Thread.currentThread().setContextClassLoader(cl);
|
||||||
implClass = cl.loadClass(className);
|
implClass = cl.loadClass(className);
|
||||||
int coprocPriority = hasPriorityOverride ? overridePriority : currentSystemPriority;
|
int coprocPriority = hasPriorityOverride ? overridePriority : currentSystemPriority;
|
||||||
// Add coprocessors as we go to guard against case where a coprocessor is specified twice
|
// Add coprocessors as we go to guard against case where a coprocessor is specified twice
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.coprocessor;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
@ -27,8 +28,10 @@ import org.apache.hadoop.hbase.Abortable;
|
||||||
import org.apache.hadoop.hbase.Coprocessor;
|
import org.apache.hadoop.hbase.Coprocessor;
|
||||||
import org.apache.hadoop.hbase.CoprocessorEnvironment;
|
import org.apache.hadoop.hbase.CoprocessorEnvironment;
|
||||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||||
|
import org.apache.hadoop.hbase.HBaseCommonTestingUtility;
|
||||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||||
import org.apache.hadoop.hbase.testclassification.SmallTests;
|
import org.apache.hadoop.hbase.testclassification.SmallTests;
|
||||||
|
import org.apache.hadoop.hbase.util.ClassLoaderTestHelper;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -41,6 +44,8 @@ public class TestCoprocessorHost {
|
||||||
public static final HBaseClassTestRule CLASS_RULE =
|
public static final HBaseClassTestRule CLASS_RULE =
|
||||||
HBaseClassTestRule.forClass(TestCoprocessorHost.class);
|
HBaseClassTestRule.forClass(TestCoprocessorHost.class);
|
||||||
|
|
||||||
|
private static final HBaseCommonTestingUtility TEST_UTIL = new HBaseCommonTestingUtility();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Abortable} implementation for tests.
|
* An {@link Abortable} implementation for tests.
|
||||||
*/
|
*/
|
||||||
|
@ -50,7 +55,7 @@ public class TestCoprocessorHost {
|
||||||
@Override
|
@Override
|
||||||
public void abort(String why, Throwable e) {
|
public void abort(String why, Throwable e) {
|
||||||
this.aborted = true;
|
this.aborted = true;
|
||||||
Assert.fail();
|
Assert.fail(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -97,6 +102,108 @@ public class TestCoprocessorHost {
|
||||||
assertEquals(overridePriority, simpleEnv_v3.getPriority());
|
assertEquals(overridePriority, simpleEnv_v3.getPriority());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoadSystemCoprocessorWithPath() throws Exception {
|
||||||
|
Configuration conf = TEST_UTIL.getConfiguration();
|
||||||
|
final String key = "KEY";
|
||||||
|
final String testClassName = "TestSystemCoprocessor";
|
||||||
|
final String testClassNameWithPriorityAndPath = testClassName + "PriorityAndPath";
|
||||||
|
|
||||||
|
File jarFile = buildCoprocessorJar(testClassName);
|
||||||
|
File jarFileWithPriorityAndPath = buildCoprocessorJar(testClassNameWithPriorityAndPath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
CoprocessorHost<RegionCoprocessor, CoprocessorEnvironment<RegionCoprocessor>> 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<RegionCoprocessor, CoprocessorEnvironment<RegionCoprocessor>> 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<RegionCoprocessor, CoprocessorEnvironment<RegionCoprocessor>> 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 SimpleRegionObserverV2 extends SimpleRegionObserver { }
|
||||||
|
|
||||||
public static class SimpleRegionObserverV3 extends SimpleRegionObserver {
|
public static class SimpleRegionObserverV3 extends SimpleRegionObserver {
|
||||||
|
@ -128,4 +235,11 @@ public class TestCoprocessorHost {
|
||||||
return new BaseEnvironment<>(instance, priority, 0, cpHostConf);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue