Index: src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (revision 1333533) +++ src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (working copy) @@ -2069,30 +2069,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); } /** @@ -2149,29 +2127,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 1333533) +++ src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java (working copy) @@ -53,6 +53,8 @@ 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.filter.CompareFilter.CompareOp; import org.apache.hadoop.hbase.io.TimeRange; import org.apache.hadoop.hbase.rest.Constants; import org.apache.hadoop.hbase.rest.model.CellModel; @@ -588,11 +590,22 @@ throw new IOException("checkAndPut not supported"); } + public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, CompareOp 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, + CompareOp 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 1333533) +++ src/main/java/org/apache/hadoop/hbase/coprocessor/CoprocessorHost.java (working copy) @@ -32,6 +32,8 @@ 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.filter.CompareFilter.CompareOp; import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.SortedCopyOnWriteSet; @@ -418,11 +420,22 @@ return table.checkAndPut(row, family, qualifier, value, put); } + public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, + CompareOp 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, + CompareOp 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 1333533) +++ src/main/java/org/apache/hadoop/hbase/client/HTableInterface.java (working copy) @@ -27,6 +27,8 @@ 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.CompareFilter.CompareOp; +import org.apache.hadoop.hbase.filter.WritableByteArrayComparable; import org.apache.hadoop.hbase.ipc.CoprocessorProtocol; import java.util.Map; @@ -218,11 +220,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, CompareOp 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; @@ -265,6 +285,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, CompareOp 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 1333533) +++ src/main/java/org/apache/hadoop/hbase/client/HTable.java (working copy) @@ -51,6 +51,9 @@ import org.apache.hadoop.hbase.client.HConnectionManager.HConnectable; import org.apache.hadoop.hbase.client.MetaScanner.MetaScannerVisitor; import org.apache.hadoop.hbase.client.coprocessor.Batch; +import org.apache.hadoop.hbase.filter.CompareFilter; +import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp; +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.util.Addressing; @@ -902,11 +905,42 @@ }.withRetries(); } + /** + * {@inheritDoc} + */ + @Override + public boolean checkAndPut(final byte[] row, final byte[] family, final byte[] qualifier, + final CompareOp compareType, final WritableByteArrayComparable comparator, final Put put) + throws IOException { + return new ServerCallable(connection, tableName, row, operationTimeout) { + public Boolean call() throws IOException { + return server.checkAndPut(location.getRegionInfo().getRegionName(), + row, family, qualifier, compareType, comparator, put) ? Boolean.TRUE : Boolean.FALSE; + } + }.withRetries(); + } /** * {@inheritDoc} */ @Override + public boolean checkAndDelete(final byte[] row, final byte[] family, final byte[] qualifier, + final CompareOp compareType, final WritableByteArrayComparable comparator, final Delete delete) + throws IOException { + return new ServerCallable(connection, tableName, row, operationTimeout) { + public Boolean call() throws IOException { + return server.checkAndDelete( + location.getRegionInfo().getRegionName(), + row, family, qualifier, compareType, comparator, delete) + ? Boolean.TRUE : Boolean.FALSE; + } + }.withRetries(); + } + + /** + * {@inheritDoc} + */ + @Override public boolean checkAndDelete(final byte [] row, final byte [] family, final byte [] qualifier, final byte [] value, final Delete delete) Index: src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java (revision 1333533) +++ src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java (working copy) @@ -4416,6 +4416,10 @@ fail("trying to check and modify different rows should have failed."); } catch(Exception e) {} + ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.LESS, new BinaryComparator(VALUE), put2); + assertEquals(ok, false); + ok = table.checkAndPut(ROW, FAMILY, QUALIFIER, CompareOp.GREATER, new BinaryComparator(VALUE), put2); + assertEquals(ok, true); } /**