diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java index a7a9f17..cee0ace 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java @@ -504,7 +504,7 @@ public final class ProtobufUtil { MutationType type = proto.getMutateType(); assert type == MutationType.PUT: type.name(); long timestamp = proto.hasTimestamp()? proto.getTimestamp(): HConstants.LATEST_TIMESTAMP; - Put put = null; + Put put = proto.hasRow() ? new Put(proto.getRow().toByteArray(), timestamp) : null; int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0; if (cellCount > 0) { // The proto has metadata only and the data is separate to be found in the cellScanner. @@ -524,9 +524,7 @@ public final class ProtobufUtil { put.add(cell); } } else { - if (proto.hasRow()) { - put = new Put(proto.getRow().asReadOnlyByteBuffer(), timestamp); - } else { + if (put == null) { throw new IllegalArgumentException("row cannot be null"); } // The proto has the metadata and the data itself @@ -603,12 +601,8 @@ public final class ProtobufUtil { throws IOException { MutationType type = proto.getMutateType(); assert type == MutationType.DELETE : type.name(); - byte [] row = proto.hasRow()? proto.getRow().toByteArray(): null; - long timestamp = HConstants.LATEST_TIMESTAMP; - if (proto.hasTimestamp()) { - timestamp = proto.getTimestamp(); - } - Delete delete = null; + long timestamp = proto.hasTimestamp() ? proto.getTimestamp() : HConstants.LATEST_TIMESTAMP; + Delete delete = proto.hasRow() ? new Delete(proto.getRow().toByteArray(), timestamp) : null; int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0; if (cellCount > 0) { // The proto has metadata only and the data is separate to be found in the cellScanner. @@ -631,7 +625,9 @@ public final class ProtobufUtil { delete.addDeleteMarker(KeyValueUtil.ensureKeyValue(cell)); } } else { - delete = new Delete(row, timestamp); + if (delete == null) { + throw new IllegalArgumentException("row cannot be null"); + } for (ColumnValue column: proto.getColumnValueList()) { byte[] family = column.getFamily().toByteArray(); for (QualifierValue qv: column.getQualifierValueList()) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java index 5003f90..8c09416 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java @@ -3630,6 +3630,9 @@ public class HRegionServer implements ClientProtos.ClientService.BlockingInterfa rpcServer.getMetrics().exception(e); regionActionResultBuilder.setException(ResponseConverter.buildException(e)); responseBuilder.addRegionActionResult(regionActionResultBuilder.build()); + if (cellScanner != null) { + skipCellsForMutations(regionAction.getActionList(), cellScanner); + } continue; // For this region it's a failure. } @@ -3677,6 +3680,30 @@ public class HRegionServer implements ClientProtos.ClientService.BlockingInterfa return responseBuilder.build(); } + private void skipCellsForMutations(List actions, CellScanner cellScanner) { + for (ClientProtos.Action action : actions) { + skipCellsForMutation(action, cellScanner); + } + } + + private void skipCellsForMutation(ClientProtos.Action action, CellScanner cellScanner) { + try { + if (action.hasMutation()) { + MutationProto m = action.getMutation(); + if (m.hasAssociatedCellCount()) { + for (int i = 0; i < m.getAssociatedCellCount(); i++) { + cellScanner.advance(); + } + } + } + } catch (IOException e) { + // No need to handle these Individual Muatation level issue. Any way this entire RegionAction + // marked as failed as we could not see the Region here. At client side the top level + // RegionAction exception will be considered first. + LOG.error("Error while skipping Cells in CellScanner for invalid Region Mutations", e); + } + } + /** * Run through the regionMutation rm and per Mutation, do the work, and then when * done, add an instance of a {@link ResultOrException} that corresponds to each Mutation. diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestMultiParallel.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestMultiParallel.java index 8acc7d7..60fc674 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestMultiParallel.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestMultiParallel.java @@ -35,8 +35,10 @@ import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.Waiter; +import org.apache.hadoop.hbase.codec.KeyValueCodec; import org.apache.hadoop.hbase.exceptions.OperationConflictException; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.util.Bytes; @@ -70,6 +72,8 @@ public class TestMultiParallel { //((Log4JLogger)RpcServer.LOG).getLogger().setLevel(Level.ALL); //((Log4JLogger)RpcClient.LOG).getLogger().setLevel(Level.ALL); //((Log4JLogger)ScannerCallable.LOG).getLogger().setLevel(Level.ALL); + UTIL.getConfiguration().set(HConstants.RPC_CODEC_CONF_KEY, + KeyValueCodec.class.getCanonicalName()); UTIL.startMiniCluster(slaves); HTable t = UTIL.createTable(Bytes.toBytes(TEST_TABLE), Bytes.toBytes(FAMILY)); UTIL.createMultiRegions(t, Bytes.toBytes(FAMILY));