HBASE-15290 Hbase Rest CheckAndAPI should save other cells along with compared cell (Ajith)
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/d233e09c Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/d233e09c Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/d233e09c Branch: refs/heads/branch-1 Commit: d233e09c1479ab0e46adf7bfc27cb890b493ae23 Parents: 46ffa85 Author: Enis Soztutar <e...@apache.org> Authored: Fri Feb 26 15:05:59 2016 -0800 Committer: Enis Soztutar <e...@apache.org> Committed: Fri Feb 26 15:06:05 2016 -0800 ---------------------------------------------------------------------- .../apache/hadoop/hbase/rest/RowResource.java | 32 +++++++-- .../hadoop/hbase/rest/RowResourceBase.java | 39 +++++++++-- .../hbase/rest/TestGetAndPutResource.java | 69 ++++++++++++++++++++ 3 files changed, 129 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/d233e09c/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java ---------------------------------------------------------------------- diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java index dad5a32..39a4128 100644 --- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java +++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java @@ -455,20 +455,40 @@ public class RowResource extends ResourceBase { byte[][] valueToPutParts = KeyValue.parseColumn(valueToCheckColumn); if (valueToPutParts.length == 2 && valueToPutParts[1].length > 0) { CellModel valueToPutCell = null; + + // Copy all the cells to the Put request + // and track if the check cell's latest value is also sent for (int i = 0, n = cellModelCount - 1; i < n ; i++) { - if(Bytes.equals(cellModels.get(i).getColumn(), - valueToCheckCell.getColumn())) { - valueToPutCell = cellModels.get(i); - break; + CellModel cell = cellModels.get(i); + byte[] col = cell.getColumn(); + + if (col == null) { + servlet.getMetrics().incrementFailedPutRequests(1); + return Response.status(Response.Status.BAD_REQUEST) + .type(MIMETYPE_TEXT).entity("Bad request: Column found to be null." + CRLF) + .build(); + } + + byte [][] parts = KeyValue.parseColumn(col); + + if (parts.length != 2) { + return Response.status(Response.Status.BAD_REQUEST) + .type(MIMETYPE_TEXT).entity("Bad request" + CRLF) + .build(); + } + put.addImmutable(parts[0], parts[1], cell.getTimestamp(), cell.getValue()); + + if(Bytes.equals(col, + valueToCheckCell.getColumn())) { + valueToPutCell = cell; } } + if (valueToPutCell == null) { servlet.getMetrics().incrementFailedPutRequests(1); return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT) .entity("Bad request: The column to put and check do not match." + CRLF).build(); } else { - put.addImmutable(valueToPutParts[0], valueToPutParts[1], valueToPutCell.getTimestamp(), - valueToPutCell.getValue()); retValue = table.checkAndPut(key, valueToPutParts[0], valueToPutParts[1], valueToCheckCell.getValue(), put); } http://git-wip-us.apache.org/repos/asf/hbase/blob/d233e09c/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java ---------------------------------------------------------------------- diff --git a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java index 0e74b46..c88bd4c 100644 --- a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java +++ b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/RowResourceBase.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringWriter; +import java.util.*; import javax.ws.rs.core.MediaType; import javax.xml.bind.JAXBContext; @@ -29,6 +30,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; +import org.apache.commons.collections.keyvalue.AbstractMapEntry; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HColumnDescriptor; @@ -228,13 +230,22 @@ public class RowResourceBase { } protected static Response checkAndPutValuePB(String url, String table, - String row, String column, String valueToCheck, String valueToPut) + String row, String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells) throws IOException { RowModel rowModel = new RowModel(row); rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes.toBytes(valueToPut))); + + if(otherCells != null) { + for (Map.Entry<String,String> entry :otherCells.entrySet()) { + rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue()))); + } + } + + // This Cell need to be added as last cell. rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes.toBytes(valueToCheck))); + CellSetModel cellSetModel = new CellSetModel(); cellSetModel.addRow(rowModel); Response response = client.put(url, Constants.MIMETYPE_PROTOBUF, @@ -245,6 +256,10 @@ public class RowResourceBase { protected static Response checkAndPutValuePB(String table, String row, String column, String valueToCheck, String valueToPut) throws IOException { + return checkAndPutValuePB(table,row,column,valueToCheck,valueToPut,null); + } + protected static Response checkAndPutValuePB(String table, String row, + String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells) throws IOException { StringBuilder path = new StringBuilder(); path.append('/'); path.append(table); @@ -252,15 +267,23 @@ public class RowResourceBase { path.append(row); path.append("?check=put"); return checkAndPutValuePB(path.toString(), table, row, column, - valueToCheck, valueToPut); + valueToCheck, valueToPut, otherCells); } protected static Response checkAndPutValueXML(String url, String table, - String row, String column, String valueToCheck, String valueToPut) + String row, String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells) throws IOException, JAXBException { RowModel rowModel = new RowModel(row); rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes.toBytes(valueToPut))); + + if(otherCells != null) { + for (Map.Entry<String,String> entry :otherCells.entrySet()) { + rowModel.addCell(new CellModel(Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue()))); + } + } + + // This Cell need to be added as last cell. rowModel.addCell(new CellModel(Bytes.toBytes(column), Bytes.toBytes(valueToCheck))); CellSetModel cellSetModel = new CellSetModel(); @@ -274,7 +297,13 @@ public class RowResourceBase { } protected static Response checkAndPutValueXML(String table, String row, - String column, String valueToCheck, String valueToPut) + String column, String valueToCheck, String valueToPut) + throws IOException, JAXBException { + return checkAndPutValueXML(table,row,column,valueToCheck,valueToPut, null); + } + + protected static Response checkAndPutValueXML(String table, String row, + String column, String valueToCheck, String valueToPut, HashMap<String,String> otherCells) throws IOException, JAXBException { StringBuilder path = new StringBuilder(); path.append('/'); @@ -283,7 +312,7 @@ public class RowResourceBase { path.append(row); path.append("?check=put"); return checkAndPutValueXML(path.toString(), table, row, column, - valueToCheck, valueToPut); + valueToCheck, valueToPut, otherCells); } protected static Response checkAndDeleteXML(String url, String table, http://git-wip-us.apache.org/repos/asf/hbase/blob/d233e09c/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java ---------------------------------------------------------------------- diff --git a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java index 959cb50..2fc7035 100644 --- a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java +++ b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestGetAndPutResource.java @@ -25,7 +25,10 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringWriter; import java.net.URLEncoder; +import java.util.Dictionary; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.xml.bind.JAXBException; @@ -129,6 +132,72 @@ public class TestGetAndPutResource extends RowResourceBase { } @Test + public void testMultipleCellCheckPutPB() throws IOException, JAXBException { + Response response = getValuePB(TABLE, ROW_1, COLUMN_1); + assertEquals(response.getCode(), 404); + + // Add 2 Columns to setup the test + response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); + assertEquals(response.getCode(), 200); + checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); + + response = putValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); + assertEquals(response.getCode(), 200); + checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2); + + HashMap<String,String> otherCells = new HashMap<String, String>(); + otherCells.put(COLUMN_2,VALUE_3); + + // On Success update both the cells + response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_3, otherCells); + assertEquals(response.getCode(), 200); + checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3); + checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_3); + + // On Failure, we dont update any cells + response = checkAndPutValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_4, otherCells); + assertEquals(response.getCode(), 304); + checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_3); + checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_3); + + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } + + @Test + public void testMultipleCellCheckPutXML() throws IOException, JAXBException { + Response response = getValuePB(TABLE, ROW_1, COLUMN_1); + assertEquals(response.getCode(), 404); + + // Add 2 Columns to setup the test + response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); + assertEquals(response.getCode(), 200); + checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); + + response = putValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2); + assertEquals(response.getCode(), 200); + checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2); + + HashMap<String,String> otherCells = new HashMap<String, String>(); + otherCells.put(COLUMN_2,VALUE_3); + + // On Success update both the cells + response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_3, otherCells); + assertEquals(response.getCode(), 200); + checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3); + checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_3); + + // On Failure, we dont update any cells + response = checkAndPutValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1, VALUE_4, otherCells); + assertEquals(response.getCode(), 304); + checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_3); + checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_3); + + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } + + @Test public void testSingleCellGetPutBinary() throws IOException { final String path = "/" + TABLE + "/" + ROW_3 + "/" + COLUMN_1; final byte[] body = Bytes.toBytes(VALUE_3);