From d6dd1be41c4e827e801c1c208dbc90c8808827e6 Mon Sep 17 00:00:00 2001 From: Sean Busbey Date: Tue, 3 May 2016 14:34:50 -0500 Subject: [PATCH] HBASE-15698 Test to verify coprocessors can see client provided time ranges on increments. --- .../hadoop/hbase/coprocessor/CoprocessorHost.java | 2 +- .../coprocessor/IncrementTimestampChecker.java | 55 +++++++++++++++++++ .../coprocessor/TestRegionObserverInterface.java | 64 ++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/IncrementTimestampChecker.java 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 da0e8b1..6fd90d3 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 @@ -206,7 +206,7 @@ public abstract class CoprocessorHost { try { implClass = getClass().getClassLoader().loadClass(className); } catch (ClassNotFoundException e) { - throw new IOException("No jar path specified for " + className); + throw new IOException("No jar path specified for " + className, e); } } else { cl = CoprocessorClassLoader.getClassLoader( diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/IncrementTimestampChecker.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/IncrementTimestampChecker.java new file mode 100644 index 0000000..f1e8949 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/IncrementTimestampChecker.java @@ -0,0 +1,55 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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 License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.coprocessor; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.Increment; +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.io.TimeRange; + +import java.io.IOException; + +/** + * verify if a particular timestamp range has been seen. + * used in TestRegionObserverInterface. + */ +public class IncrementTimestampChecker extends BaseRegionObserver { + + public static final String TIMERANGE_START = "expected-timerange-start"; + public static final String TIMERANGE_END = "expected-timerange-end"; + + volatile boolean seenCustomTimestamp = false; + + public boolean sawCustomTimestamp() { + return seenCustomTimestamp; + } + + @Override + public Result preIncrement(final ObserverContext e, + final Increment increment) throws IOException { + final Configuration conf = e.getEnvironment().getConfiguration(); + final long start = conf.getLong(TIMERANGE_START, -1L); + final long end = conf.getLong(TIMERANGE_END, -1L); + final TimeRange tr = increment.getTimeRange(); + if (start == tr.getMin() && end == tr.getMax()) { + seenCustomTimestamp = true; + } + return null; + } +} diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java index abfadec..b31a6e3 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestRegionObserverInterface.java @@ -27,7 +27,9 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -108,13 +110,17 @@ public class TestRegionObserverInterface { "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver", "org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver$Legacy"); + LOG.debug("starting minicluster."); util.startMiniCluster(); cluster = util.getMiniHBaseCluster(); + LOG.debug("done starting minicluster."); } @AfterClass public static void tearDownAfterClass() throws Exception { + LOG.debug("shutting down minicluster"); util.shutdownMiniCluster(); + LOG.debug("done shutting down minicluster"); } @Test (timeout=300000) @@ -243,6 +249,64 @@ public class TestRegionObserverInterface { } @Test (timeout=300000) + public void testIncrementSeesTimestamp() throws IOException { + LOG.info("ensure that coprocessors see custom time ranges on increments."); + final long customTimestampStart = 0xdeadbeefL; + final long customTimestampEnd = 0xdeadfeedL; + TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testIncrementHook"); + HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName); + Map args = new HashMap(); + args.put(IncrementTimestampChecker.TIMERANGE_START, Long.toString(customTimestampStart)); + args.put(IncrementTimestampChecker.TIMERANGE_END, Long.toString(customTimestampEnd)); + hTableDescriptor.addCoprocessor(IncrementTimestampChecker.class.getCanonicalName(), null, Coprocessor.PRIORITY_USER, args); + Table table = util.createTable(hTableDescriptor, new byte[][] {A, B, C}, util.getConfiguration()); + try { + Increment inc = new Increment(Bytes.toBytes(0)); + inc.addColumn(A, A, 1); + + // false before any increments + verifyMethodResult(IncrementTimestampChecker.class, + new String[] {"sawCustomTimestamp"}, + tableName, + new Boolean[] {false} + ); + + table.increment(inc); + + // false after a default timerange increment + verifyMethodResult(IncrementTimestampChecker.class, + new String[] {"sawCustomTimestamp"}, + tableName, + new Boolean[] {false} + ); + + inc.setTimeRange(0L, customTimestampStart); + table.increment(inc); + + // false after a timerange that isn't the one we're checking for + verifyMethodResult(IncrementTimestampChecker.class, + new String[] {"sawCustomTimestamp"}, + tableName, + new Boolean[] {false} + ); + + inc.setTimeRange(customTimestampStart, customTimestampEnd); + table.increment(inc); + + // true after our custom range is used + verifyMethodResult(IncrementTimestampChecker.class, + new String[] {"sawCustomTimestamp"}, + tableName, + new Boolean[] {true} + ); + + } finally { + util.deleteTable(tableName); + table.close(); + } + } + + @Test (timeout=300000) public void testCheckAndPutHooks() throws IOException { TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + ".testCheckAndPutHooks"); -- 2.7.2