Skip to content

Commit ee4cbdb

Browse files
gvprathyusha6virajjasani
authored andcommitted
HBASE-27938 PE load any custom implementation of tests at runtime (#5307) (#5899)
Signed-off-by: Duo Zhang <zhangduo@apache.org> Signed-off-by: Wellington Chevreuil <wchevreuil@apache.org> Signed-off-by: Viraj Jasani <vjasani@apache.org>
1 parent 867a801 commit ee4cbdb

File tree

2 files changed

+94
-5
lines changed

2 files changed

+94
-5
lines changed

hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/PerformanceEvaluation.java

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.Locale;
3737
import java.util.Map;
3838
import java.util.NoSuchElementException;
39+
import java.util.Properties;
3940
import java.util.Queue;
4041
import java.util.Random;
4142
import java.util.TreeMap;
@@ -358,7 +359,8 @@ static boolean checkTable(Admin admin, TestOptions opts) throws IOException {
358359
// {RegionSplitPolicy,replica count} does not match requested, or when the
359360
// number of column families does not match requested.
360361
if (
361-
(exists && opts.presplitRegions != DEFAULT_OPTS.presplitRegions)
362+
(exists && opts.presplitRegions != DEFAULT_OPTS.presplitRegions
363+
&& opts.presplitRegions != admin.getRegions(tableName).size())
362364
|| (!isReadCmd && desc != null
363365
&& !StringUtils.equals(desc.getRegionSplitPolicyClassName(), opts.splitPolicy))
364366
|| (!isReadCmd && desc != null && desc.getRegionReplication() != opts.replicas)
@@ -719,6 +721,7 @@ static class TestOptions {
719721
boolean cacheBlocks = true;
720722
Scan.ReadType scanReadType = Scan.ReadType.DEFAULT;
721723
long bufferSize = 2l * 1024l * 1024l;
724+
Properties commandProperties;
722725

723726
public TestOptions() {
724727
}
@@ -775,6 +778,11 @@ public TestOptions(TestOptions that) {
775778
this.cacheBlocks = that.cacheBlocks;
776779
this.scanReadType = that.scanReadType;
777780
this.bufferSize = that.bufferSize;
781+
this.commandProperties = that.commandProperties;
782+
}
783+
784+
public Properties getCommandProperties() {
785+
return commandProperties;
778786
}
779787

780788
public int getCaching() {
@@ -1140,10 +1148,10 @@ private static long nextRandomSeed() {
11401148
protected final Configuration conf;
11411149
protected final TestOptions opts;
11421150

1143-
private final Status status;
1151+
protected final Status status;
11441152

11451153
private String testName;
1146-
private Histogram latencyHistogram;
1154+
protected Histogram latencyHistogram;
11471155
private Histogram replicaLatencyHistogram;
11481156
private Histogram valueSizeHistogram;
11491157
private Histogram rpcCallsHistogram;
@@ -2573,7 +2581,7 @@ protected static void printUsage(final String shortName, final String message) {
25732581
System.err.println(message);
25742582
}
25752583
System.err.print("Usage: hbase " + shortName);
2576-
System.err.println(" <OPTIONS> [-D<property=value>]* <command> <nclients>");
2584+
System.err.println(" <OPTIONS> [-D<property=value>]* <command|class> <nclients>");
25772585
System.err.println();
25782586
System.err.println("General Options:");
25792587
System.err.println(
@@ -2674,6 +2682,13 @@ protected static void printUsage(final String shortName, final String message) {
26742682
System.err.println(String.format(" %-20s %s", command.getName(), command.getDescription()));
26752683
}
26762684
System.err.println();
2685+
System.err.println("Class:");
2686+
System.err.println("To run any custom implementation of PerformanceEvaluation.Test, "
2687+
+ "provide the classname of the implementaion class in place of "
2688+
+ "command name and it will be loaded at runtime from classpath.:");
2689+
System.err.println("Please consider to contribute back "
2690+
+ "this custom test impl into a builtin PE command for the benefit of the community");
2691+
System.err.println();
26772692
System.err.println("Args:");
26782693
System.err.println(" nclients Integer. Required. Total number of clients "
26792694
+ "(and HRegionServers) running. 1 <= value <= 500");
@@ -2968,6 +2983,20 @@ static TestOptions parseOpts(Queue<String> args) {
29682983
continue;
29692984
}
29702985

2986+
final String commandPropertiesFile = "--commandPropertiesFile=";
2987+
if (cmd.startsWith(commandPropertiesFile)) {
2988+
String fileName = String.valueOf(cmd.substring(commandPropertiesFile.length()));
2989+
Properties properties = new Properties();
2990+
try {
2991+
properties
2992+
.load(PerformanceEvaluation.class.getClassLoader().getResourceAsStream(fileName));
2993+
opts.commandProperties = properties;
2994+
} catch (IOException e) {
2995+
LOG.error("Failed to load metricIds from properties file", e);
2996+
}
2997+
continue;
2998+
}
2999+
29713000
validateParsedOpts(opts);
29723001

29733002
if (isCommandClass(cmd)) {
@@ -3081,7 +3110,20 @@ public int run(String[] args) throws Exception {
30813110
}
30823111

30833112
private static boolean isCommandClass(String cmd) {
3084-
return COMMANDS.containsKey(cmd);
3113+
return COMMANDS.containsKey(cmd) || isCustomTestClass(cmd);
3114+
}
3115+
3116+
private static boolean isCustomTestClass(String cmd) {
3117+
Class<? extends Test> cmdClass;
3118+
try {
3119+
cmdClass =
3120+
(Class<? extends Test>) PerformanceEvaluation.class.getClassLoader().loadClass(cmd);
3121+
addCommandDescriptor(cmdClass, cmd, "custom command");
3122+
return true;
3123+
} catch (Throwable th) {
3124+
LOG.info("No class found for command: " + cmd, th);
3125+
return false;
3126+
}
30853127
}
30863128

30873129
private static Class<? extends TestBase> determineCommandClass(String cmd) {

hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/TestPerformanceEvaluation.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,26 @@
2828
import com.codahale.metrics.UniformReservoir;
2929
import java.io.BufferedReader;
3030
import java.io.ByteArrayInputStream;
31+
import java.io.File;
32+
import java.io.FileWriter;
3133
import java.io.IOException;
3234
import java.io.InputStreamReader;
3335
import java.lang.reflect.Constructor;
3436
import java.lang.reflect.InvocationTargetException;
3537
import java.nio.charset.StandardCharsets;
3638
import java.util.LinkedList;
3739
import java.util.NoSuchElementException;
40+
import java.util.Properties;
3841
import java.util.Queue;
3942
import java.util.Random;
4043
import java.util.concurrent.ThreadLocalRandom;
4144
import org.apache.hadoop.fs.FSDataInputStream;
4245
import org.apache.hadoop.fs.FileSystem;
4346
import org.apache.hadoop.fs.Path;
4447
import org.apache.hadoop.hbase.PerformanceEvaluation.RandomReadTest;
48+
import org.apache.hadoop.hbase.PerformanceEvaluation.Status;
4549
import org.apache.hadoop.hbase.PerformanceEvaluation.TestOptions;
50+
import org.apache.hadoop.hbase.client.Connection;
4651
import org.apache.hadoop.hbase.regionserver.CompactingMemStore;
4752
import org.apache.hadoop.hbase.testclassification.MiscTests;
4853
import org.apache.hadoop.hbase.testclassification.SmallTests;
@@ -357,4 +362,46 @@ public void testParseOptsValueRandom() {
357362
assertEquals(true, options.valueRandom);
358363
}
359364

365+
@Test
366+
public void testCustomTestClassOptions() throws IOException {
367+
Queue<String> opts = new LinkedList<>();
368+
// create custom properties that can be used for a custom test class
369+
Properties commandProps = new Properties();
370+
commandProps.put("prop1", "val1");
371+
String cmdPropsFilePath =
372+
this.getClass().getClassLoader().getResource("").getPath() + "cmd_properties.txt";
373+
FileWriter writer = new FileWriter(new File(cmdPropsFilePath));
374+
commandProps.store(writer, null);
375+
// create opts for the custom test class - commandPropertiesFile, testClassName
376+
opts.offer("--commandPropertiesFile=" + "cmd_properties.txt");
377+
String testClassName = "org.apache.hadoop.hbase.TestPerformanceEvaluation$PESampleTestImpl";
378+
opts.offer(testClassName);
379+
opts.offer("1");
380+
PerformanceEvaluation.TestOptions options = PerformanceEvaluation.parseOpts(opts);
381+
assertNotNull(options);
382+
assertNotNull(options.getCmdName());
383+
assertEquals(testClassName, options.getCmdName());
384+
assertNotNull(options.getCommandProperties());
385+
assertEquals("val1", options.getCommandProperties().get("prop1"));
386+
}
387+
388+
class PESampleTestImpl extends PerformanceEvaluation.Test {
389+
390+
PESampleTestImpl(Connection con, TestOptions options, Status status) {
391+
super(con, options, status);
392+
}
393+
394+
@Override
395+
void onStartup() throws IOException {
396+
}
397+
398+
@Override
399+
void onTakedown() throws IOException {
400+
}
401+
402+
@Override
403+
boolean testRow(int i, long startTime) throws IOException, InterruptedException {
404+
return false;
405+
}
406+
}
360407
}

0 commit comments

Comments
 (0)