Index: src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java (revision 1332513) +++ src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java (working copy) @@ -66,6 +66,7 @@ import org.apache.hadoop.hbase.generated.master.table_jsp; import org.apache.hadoop.hbase.io.hfile.BlockCache; import org.apache.hadoop.hbase.io.hfile.CacheConfig; +import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Condition.CompareType; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.regionserver.Store; @@ -4488,6 +4489,10 @@ fail("trying to check and modify different rows should have failed."); } catch(Exception e) {} + ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareType.LESS, new BinaryComparator(VALUE), put2); + assertEquals(ok, false); + ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareType.GREATER, new BinaryComparator(VALUE), put2); + assertEquals(ok, true); } /** Index: src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (revision 1332513) +++ src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (working copy) @@ -1893,30 +1893,8 @@ public boolean checkAndPut(final byte[] regionName, final byte[] row, final byte[] family, final byte[] qualifier, final byte[] value, final Put put) throws IOException { - checkOpen(); - if (regionName == null) { - throw new IOException("Invalid arguments to checkAndPut " - + "regionName is null"); - } - HRegion region = getRegion(regionName); - Integer lock = getLockFromId(put.getLockId()); - WritableByteArrayComparable comparator = new BinaryComparator(value); - if (region.getCoprocessorHost() != null) { - Boolean result = region.getCoprocessorHost() - .preCheckAndPut(row, family, qualifier, CompareOp.EQUAL, comparator, - put); - if (result != null) { - return result.booleanValue(); - } - } - boolean result = checkAndMutate(regionName, row, family, qualifier, - CompareOp.EQUAL, new BinaryComparator(value), put, - lock); - if (region.getCoprocessorHost() != null) { - result = region.getCoprocessorHost().postCheckAndPut(row, family, - qualifier, CompareOp.EQUAL, comparator, put, result); - } - return result; + return checkAndPut(regionName, row, family, qualifier, CompareOp.EQUAL, new BinaryComparator( + value), put); } /** @@ -1973,29 +1951,8 @@ public boolean checkAndDelete(final byte[] regionName, final byte[] row, final byte[] family, final byte[] qualifier, final byte[] value, final Delete delete) throws IOException { - checkOpen(); - - if (regionName == null) { - throw new IOException("Invalid arguments to checkAndDelete " - + "regionName is null"); - } - HRegion region = getRegion(regionName); - Integer lock = getLockFromId(delete.getLockId()); - WritableByteArrayComparable comparator = new BinaryComparator(value); - if (region.getCoprocessorHost() != null) { - Boolean result = region.getCoprocessorHost().preCheckAndDelete(row, - family, qualifier, CompareOp.EQUAL, comparator, delete); - if (result != null) { - return result.booleanValue(); - } - } - boolean result = checkAndMutate(regionName, row, family, qualifier, - CompareOp.EQUAL, comparator, delete, lock); - if (region.getCoprocessorHost() != null) { - result = region.getCoprocessorHost().postCheckAndDelete(row, family, - qualifier, CompareOp.EQUAL, comparator, delete, result); - } - return result; + return checkAndDelete(regionName, row, family, qualifier, CompareOp.EQUAL, + new BinaryComparator(value), delete); } @Override Index: src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java (revision 1332513) +++ src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java (working copy) @@ -55,7 +55,9 @@ import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.RowLock; import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.io.TimeRange; +import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Condition.CompareType; import org.apache.hadoop.hbase.rest.Constants; import org.apache.hadoop.hbase.rest.model.CellModel; import org.apache.hadoop.hbase.rest.model.CellSetModel; @@ -592,11 +594,22 @@ throw new IOException("checkAndPut not supported"); } + public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, CompareType compareType, + WritableByteArrayComparable comparator, Put put) throws IOException { + throw new IOException("checkAndPut not supported"); + } + public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete) throws IOException { throw new IOException("checkAndDelete not supported"); } + public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, + CompareType compareType, WritableByteArrayComparable comparator, Delete delete) + throws IOException { + throw new IOException("checkAndDelete not supported"); + } + public Result increment(Increment increment) throws IOException { throw new IOException("Increment not supported"); } Index: src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java (revision 1332513) +++ src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java (working copy) @@ -34,7 +34,9 @@ import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.client.coprocessor.Batch; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; +import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Condition.CompareType; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.SortedCopyOnWriteSet; import org.apache.hadoop.hbase.util.VersionInfo; @@ -422,11 +424,22 @@ return table.checkAndPut(row, family, qualifier, value, put); } + public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, + CompareType compareType, WritableByteArrayComparable comparator, Put put) + throws IOException { + return table.checkAndPut(row, family, qualifier, compareType, comparator, put); + } + public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete) throws IOException { return table.checkAndDelete(row, family, qualifier, value, delete); } + public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, + CompareType compareType, WritableByteArrayComparable comparator, Delete delete) throws IOException { + return table.checkAndDelete(row, family, qualifier, compareType, comparator, delete); + } + public long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount) throws IOException { return table.incrementColumnValue(row, family, qualifier, amount); Index: src/main/java/org/apache/hadoop/hbase/client/HTableInterface.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HTableInterface.java (revision 1332513) +++ src/main/java/org/apache/hadoop/hbase/client/HTableInterface.java (working copy) @@ -29,7 +29,9 @@ import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.coprocessor.Batch; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; +import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Condition.CompareType; import java.util.Map; @@ -222,11 +224,29 @@ * @param row to check * @param family column family to check * @param qualifier column qualifier to check + * @param compareOp compare opertation to use + * @param comparator the comparator to use to comparisons * @param value the expected value * @param put data to put if check succeeds * @throws IOException e * @return true if the new put was executed, false otherwise */ + boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, CompareType compareType, + WritableByteArrayComparable comparator, Put put) throws IOException; + + /** + * Atomically checks if a row/family/qualifier value matches the expected + * value. If it does, it adds the put. If the passed value is null, the check + * is for the lack of column (ie: non-existance) + * + * @param row to check + * @param family column family to check + * @param qualifier column qualifier to check + * @param value the expected value + * @param put data to put if check succeeds + * @throws IOException e + * @return true if the new put was executed, false otherwise + */ boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put) throws IOException; @@ -269,6 +289,24 @@ byte[] value, Delete delete) throws IOException; /** + * Atomically checks if a row/family/qualifier value matches the expected + * value. If it does, it adds the delete. If the passed value is null, the + * check is for the lack of column (ie: non-existance) + * + * @param row to check + * @param family column family to check + * @param qualifier column qualifier to check + * @param compareOp compare opertation to use + * @param comparator the comparator to use to comparisons + * @param value the expected value + * @param delete data to delete if check succeeds + * @throws IOException e + * @return true if the new delete was executed, false otherwise + */ + boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, CompareType compareType, + WritableByteArrayComparable comparator, Delete delete) throws IOException; + + /** * Performs multiple mutations atomically on a single row. Currently * {@link Put} and {@link Delete} are supported. * Index: src/main/java/org/apache/hadoop/hbase/client/HTable.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HTable.java (revision 1332513) +++ src/main/java/org/apache/hadoop/hbase/client/HTable.java (working copy) @@ -54,6 +54,7 @@ import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor; import org.apache.hadoop.hbase.client.coprocessor.Batch; import org.apache.hadoop.hbase.filter.BinaryComparator; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; import org.apache.hadoop.hbase.ipc.ExecRPCInvoker; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; @@ -947,16 +948,24 @@ * {@inheritDoc} */ @Override - public boolean checkAndPut(final byte [] row, - final byte [] family, final byte [] qualifier, final byte [] value, - final Put put) - throws IOException { + public boolean checkAndPut(final byte[] row, final byte[] family, final byte[] qualifier, + final byte[] value, final Put put) throws IOException { + return checkAndPut(row, family, qualifier, CompareType.EQUAL, new BinaryComparator(value), put); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean checkAndPut(final byte[] row, final byte[] family, final byte[] qualifier, + final CompareType compareType, final WritableByteArrayComparable comparator, final Put put) + throws IOException { return new ServerCallable(connection, tableName, row, operationTimeout) { public Boolean call() throws IOException { try { MutateRequest request = RequestConverter.buildMutateRequest( location.getRegionInfo().getRegionName(), row, family, qualifier, - new BinaryComparator(value), CompareType.EQUAL, put); + comparator, compareType, put); MutateResponse response = server.mutate(null, request); return Boolean.valueOf(response.getProcessed()); } catch (ServiceException se) { @@ -966,28 +975,35 @@ }.withRetries(); } + /** + * {@inheritDoc} + */ + @Override + public boolean checkAndDelete(final byte[] row, final byte[] family, final byte[] qualifier, + final byte[] value, final Delete delete) throws IOException { + return checkAndDelete(row, family, qualifier, CompareType.EQUAL, new BinaryComparator(value), + delete); + } /** * {@inheritDoc} */ @Override - public boolean checkAndDelete(final byte [] row, - final byte [] family, final byte [] qualifier, final byte [] value, - final Delete delete) - throws IOException { + public boolean checkAndDelete(final byte[] row, final byte[] family, final byte[] qualifier, + final CompareType compareType, final WritableByteArrayComparable comparator, + final Delete delete) throws IOException { return new ServerCallable(connection, tableName, row, operationTimeout) { - public Boolean call() throws IOException { - try { - MutateRequest request = RequestConverter.buildMutateRequest( - location.getRegionInfo().getRegionName(), row, family, qualifier, - new BinaryComparator(value), CompareType.EQUAL, delete); - MutateResponse response = server.mutate(null, request); - return Boolean.valueOf(response.getProcessed()); - } catch (ServiceException se) { - throw ProtobufUtil.getRemoteException(se); - } - } - }.withRetries(); + public Boolean call() throws IOException { + try { + MutateRequest request = RequestConverter.buildMutateRequest(location.getRegionInfo() + .getRegionName(), row, family, qualifier, comparator, compareType, delete); + MutateResponse response = server.mutate(null, request); + return Boolean.valueOf(response.getProcessed()); + } catch (ServiceException se) { + throw ProtobufUtil.getRemoteException(se); + } + } + }.withRetries(); } /**