This is an automated email from the ASF dual-hosted git repository. brfrn169 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/master by this push: new 5fa15cf HBASE-25575 Should validate Puts in RowMutations (#2954) 5fa15cf is described below commit 5fa15cfde3d77e77ffb1f09d60dce4db264f3831 Author: Toshihiro Suzuki <brfrn...@gmail.com> AuthorDate: Mon Feb 22 10:46:16 2021 +0900 HBASE-25575 Should validate Puts in RowMutations (#2954) Signed-off-by: Duo Zhang <zhang...@apache.org> --- .../hadoop/hbase/client/ConnectionUtils.java | 10 ++++- .../hadoop/hbase/client/RawAsyncTableImpl.java | 13 ++++-- .../apache/hadoop/hbase/client/TestAsyncTable.java | 43 +++++++++++++++++++ .../hadoop/hbase/client/TestAsyncTableBatch.java | 50 ++++++++++++++++++++++ 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java index 5b8cb84..70312aa 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionUtils.java @@ -482,7 +482,7 @@ public final class ConnectionUtils { } // validate for well-formedness - static void validatePut(Put put, int maxKeyValueSize) throws IllegalArgumentException { + static void validatePut(Put put, int maxKeyValueSize) { if (put.isEmpty()) { throw new IllegalArgumentException("No columns to insert"); } @@ -497,6 +497,14 @@ public final class ConnectionUtils { } } + static void validatePutsInRowMutations(RowMutations rowMutations, int maxKeyValueSize) { + for (Mutation mutation : rowMutations.getMutations()) { + if (mutation instanceof Put) { + validatePut((Put) mutation, maxKeyValueSize); + } + } + } + /** * Select the priority for the rpc call. * <p/> diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncTableImpl.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncTableImpl.java index 3cffad8..187ecf1 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncTableImpl.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncTableImpl.java @@ -22,6 +22,7 @@ import static org.apache.hadoop.hbase.client.ConnectionUtils.checkHasFamilies; import static org.apache.hadoop.hbase.client.ConnectionUtils.isEmptyStopRow; import static org.apache.hadoop.hbase.client.ConnectionUtils.timelineConsistentRead; import static org.apache.hadoop.hbase.client.ConnectionUtils.validatePut; +import static org.apache.hadoop.hbase.client.ConnectionUtils.validatePutsInRowMutations; import static org.apache.hadoop.hbase.util.FutureUtils.addListener; import java.io.IOException; @@ -343,6 +344,7 @@ class RawAsyncTableImpl implements AsyncTable<AdvancedScanResultConsumer> { @Override public CompletableFuture<Boolean> thenMutate(RowMutations mutation) { preCheck(); + validatePutsInRowMutations(mutation, conn.connConf.getMaxKeyValueSize()); return RawAsyncTableImpl.this.<Boolean> newCaller(row, mutation.getMaxPriority(), rpcTimeoutNs) .action((controller, loc, stub) -> RawAsyncTableImpl.this.mutateRow(controller, @@ -403,6 +405,7 @@ class RawAsyncTableImpl implements AsyncTable<AdvancedScanResultConsumer> { @Override public CompletableFuture<Boolean> thenMutate(RowMutations mutation) { + validatePutsInRowMutations(mutation, conn.connConf.getMaxKeyValueSize()); return RawAsyncTableImpl.this.<Boolean> newCaller(row, mutation.getMaxPriority(), rpcTimeoutNs) .action((controller, loc, stub) -> RawAsyncTableImpl.this.mutateRow(controller, @@ -420,9 +423,6 @@ class RawAsyncTableImpl implements AsyncTable<AdvancedScanResultConsumer> { @Override public CompletableFuture<CheckAndMutateResult> checkAndMutate(CheckAndMutate checkAndMutate) { - if (checkAndMutate.getAction() instanceof Put) { - validatePut((Put) checkAndMutate.getAction(), conn.connConf.getMaxKeyValueSize()); - } if (checkAndMutate.getAction() instanceof Put || checkAndMutate.getAction() instanceof Delete || checkAndMutate.getAction() instanceof Increment || checkAndMutate.getAction() instanceof Append) { @@ -442,6 +442,7 @@ class RawAsyncTableImpl implements AsyncTable<AdvancedScanResultConsumer> { .call(); } else if (checkAndMutate.getAction() instanceof RowMutations) { RowMutations rowMutations = (RowMutations) checkAndMutate.getAction(); + validatePutsInRowMutations(rowMutations, conn.connConf.getMaxKeyValueSize()); return RawAsyncTableImpl.this.<CheckAndMutateResult> newCaller(checkAndMutate.getRow(), rowMutations.getMaxPriority(), rpcTimeoutNs) .action((controller, loc, stub) -> @@ -514,6 +515,7 @@ class RawAsyncTableImpl implements AsyncTable<AdvancedScanResultConsumer> { @Override public CompletableFuture<Result> mutateRow(RowMutations mutations) { + validatePutsInRowMutations(mutations, conn.connConf.getMaxKeyValueSize()); return this.<Result> newCaller(mutations.getRow(), mutations.getMaxPriority(), writeRpcTimeoutNs).action((controller, loc, stub) -> this.<Result, Result> mutateRow(controller, loc, stub, mutations, @@ -615,7 +617,12 @@ class RawAsyncTableImpl implements AsyncTable<AdvancedScanResultConsumer> { CheckAndMutate checkAndMutate = (CheckAndMutate) action; if (checkAndMutate.getAction() instanceof Put) { validatePut((Put) checkAndMutate.getAction(), conn.connConf.getMaxKeyValueSize()); + } else if (checkAndMutate.getAction() instanceof RowMutations) { + validatePutsInRowMutations((RowMutations) checkAndMutate.getAction(), + conn.connConf.getMaxKeyValueSize()); } + } else if (action instanceof RowMutations) { + validatePutsInRowMutations((RowMutations) action, conn.connConf.getMaxKeyValueSize()); } } return conn.callerFactory.batch().table(tableName).actions(actions) diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTable.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTable.java index f76c923..2952fa3 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTable.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTable.java @@ -1673,4 +1673,47 @@ public class TestAsyncTable { assertThat(e.getMessage(), containsString("KeyValue size too large")); } } + + @Test + public void testInvalidPutInRowMutations() throws IOException { + final byte[] row = Bytes.toBytes(0); + try { + getTable.get().mutateRow(new RowMutations(row).add(new Put(row))); + fail("Should fail since the put does not contain any cells"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("No columns to insert")); + } + + try { + getTable.get() + .mutateRow(new RowMutations(row).add(new Put(row) + .addColumn(FAMILY, QUALIFIER, new byte[MAX_KEY_VALUE_SIZE]))); + fail("Should fail since the put exceeds the max key value size"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("KeyValue size too large")); + } + } + + @Test + public void testInvalidPutInRowMutationsInCheckAndMutate() throws IOException { + final byte[] row = Bytes.toBytes(0); + try { + getTable.get().checkAndMutate(CheckAndMutate.newBuilder(row) + .ifNotExists(FAMILY, QUALIFIER) + .build(new RowMutations(row).add(new Put(row)))); + fail("Should fail since the put does not contain any cells"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("No columns to insert")); + } + + try { + getTable.get().checkAndMutate(CheckAndMutate.newBuilder(row) + .ifNotExists(FAMILY, QUALIFIER) + .build(new RowMutations(row).add(new Put(row) + .addColumn(FAMILY, QUALIFIER, new byte[MAX_KEY_VALUE_SIZE])))); + fail("Should fail since the put exceeds the max key value size"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("KeyValue size too large")); + } + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableBatch.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableBatch.java index 4fb050e..78dbf0b 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableBatch.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncTableBatch.java @@ -336,6 +336,56 @@ public class TestAsyncTableBatch { } @Test + public void testInvalidPutInRowMutations() throws IOException { + final byte[] row = Bytes.toBytes(0); + + AsyncTable<?> table = tableGetter.apply(TABLE_NAME); + try { + table.batch(Arrays.asList(new Delete(row), new RowMutations(row).add(new Put(row)))); + fail("Should fail since the put does not contain any cells"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("No columns to insert")); + } + + try { + table.batch( + Arrays.asList(new RowMutations(row).add(new Put(row) + .addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE])), + new Delete(row))); + fail("Should fail since the put exceeds the max key value size"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("KeyValue size too large")); + } + } + + @Test + public void testInvalidPutInRowMutationsInCheckAndMutate() throws IOException { + final byte[] row = Bytes.toBytes(0); + + AsyncTable<?> table = tableGetter.apply(TABLE_NAME); + try { + table.batch(Arrays.asList(new Delete(row), CheckAndMutate.newBuilder(row) + .ifNotExists(FAMILY, CQ) + .build(new RowMutations(row).add(new Put(row))))); + fail("Should fail since the put does not contain any cells"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("No columns to insert")); + } + + try { + table.batch( + Arrays.asList(CheckAndMutate.newBuilder(row) + .ifNotExists(FAMILY, CQ) + .build(new RowMutations(row).add(new Put(row) + .addColumn(FAMILY, CQ, new byte[MAX_KEY_VALUE_SIZE]))), + new Delete(row))); + fail("Should fail since the put exceeds the max key value size"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("KeyValue size too large")); + } + } + + @Test public void testWithCheckAndMutate() throws Exception { AsyncTable<?> table = tableGetter.apply(TABLE_NAME);