From a9898c80e563c66486366cd6a9a2ebfb358c13b8 Mon Sep 17 00:00:00 2001 From: Guangxu Cheng Date: Sat, 26 Aug 2017 20:17:02 +0800 Subject: [PATCH] HBASE-18671 Support Append/Increment in rest api --- .../hadoop/hbase/rest/MetricsRESTSource.java | 38 +++- .../hadoop/hbase/rest/MetricsRESTSourceImpl.java | 28 +++ .../org/apache/hadoop/hbase/rest/MetricsREST.java | 28 +++ .../org/apache/hadoop/hbase/rest/RowResource.java | 218 ++++++++++++++++++++- .../apache/hadoop/hbase/rest/TableResource.java | 10 +- .../apache/hadoop/hbase/rest/RowResourceBase.java | 109 ++++++++++- .../hadoop/hbase/rest/TestGetAndPutResource.java | 105 ++++++++++ 7 files changed, 524 insertions(+), 12 deletions(-) diff --git a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/rest/MetricsRESTSource.java b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/rest/MetricsRESTSource.java index ceec41d..a5101e0 100644 --- a/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/rest/MetricsRESTSource.java +++ b/hbase-hadoop-compat/src/main/java/org/apache/hadoop/hbase/rest/MetricsRESTSource.java @@ -52,6 +52,14 @@ public interface MetricsRESTSource extends BaseSource, JvmPauseMonitorSource { String FAILED_SCAN_KEY = "failedScanCount"; + String SUCCESSFUL_APPEND_KEY = "successfulAppendCount"; + + String FAILED_APPEND_KEY = "failedAppendCount"; + + String SUCCESSFUL_INCREMENT_KEY = "successfulIncrementCount"; + + String FAILED_INCREMENT_KEY = "failedIncrementCount"; + /** * Increment the number of requests * @@ -111,7 +119,35 @@ public interface MetricsRESTSource extends BaseSource, JvmPauseMonitorSource { /** * Increment the number failed scan requests. * - * @param inc the inc + * @param inc Number of failed scan requests. */ void incrementFailedScanRequests(final int inc); + + /** + * Increment the number of successful append requests. + * + * @param inc Number of successful append requests. + */ + void incrementSucessfulAppendRequests(final int inc); + + /** + * Increment the number failed append requests. + * + * @param inc Number of failed append requests. + */ + void incrementFailedAppendRequests(final int inc); + + /** + * Increment the number of successful increment requests. + * + * @param inc Number of successful increment requests. + */ + void incrementSucessfulIncrementRequests(final int inc); + + /** + * Increment the number failed increment requests. + * + * @param inc Number of failed increment requests. + */ + void incrementFailedIncrementRequests(final int inc); } diff --git a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/rest/MetricsRESTSourceImpl.java b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/rest/MetricsRESTSourceImpl.java index 30625f8..9360e32 100644 --- a/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/rest/MetricsRESTSourceImpl.java +++ b/hbase-hadoop2-compat/src/main/java/org/apache/hadoop/hbase/rest/MetricsRESTSourceImpl.java @@ -37,10 +37,14 @@ public class MetricsRESTSourceImpl extends BaseSourceImpl implements MetricsREST private MutableFastCounter sucPut; private MutableFastCounter sucDel; private MutableFastCounter sucScan; + private MutableFastCounter sucAppend; + private MutableFastCounter sucIncrement; private MutableFastCounter fGet; private MutableFastCounter fPut; private MutableFastCounter fDel; private MutableFastCounter fScan; + private MutableFastCounter fAppend; + private MutableFastCounter fIncrement; // pause monitor metrics private final MutableFastCounter infoPauseThresholdExceeded; @@ -76,11 +80,15 @@ public class MetricsRESTSourceImpl extends BaseSourceImpl implements MetricsREST sucPut = getMetricsRegistry().getCounter(SUCCESSFUL_PUT_KEY, 0l); sucDel = getMetricsRegistry().getCounter(SUCCESSFUL_DELETE_KEY, 0l); sucScan = getMetricsRegistry().getCounter(SUCCESSFUL_SCAN_KEY, 0L); + sucAppend = getMetricsRegistry().getCounter(SUCCESSFUL_APPEND_KEY, 0l); + sucIncrement = getMetricsRegistry().getCounter(SUCCESSFUL_INCREMENT_KEY, 0L); fGet = getMetricsRegistry().getCounter(FAILED_GET_KEY, 0l); fPut = getMetricsRegistry().getCounter(FAILED_PUT_KEY, 0l); fDel = getMetricsRegistry().getCounter(FAILED_DELETE_KEY, 0l); fScan = getMetricsRegistry().getCounter(FAILED_SCAN_KEY, 0l); + fAppend = getMetricsRegistry().getCounter(FAILED_APPEND_KEY, 0l); + fIncrement = getMetricsRegistry().getCounter(FAILED_INCREMENT_KEY, 0L); } @Override @@ -129,6 +137,26 @@ public class MetricsRESTSourceImpl extends BaseSourceImpl implements MetricsREST } @Override + public void incrementSucessfulAppendRequests(int inc) { + sucAppend.incr(inc); + } + + @Override + public void incrementFailedAppendRequests(int inc) { + fAppend.incr(inc); + } + + @Override + public void incrementSucessfulIncrementRequests(int inc) { + sucIncrement.incr(inc); + } + + @Override + public void incrementFailedIncrementRequests(int inc) { + fIncrement.incr(inc); + } + + @Override public void incInfoThresholdExceeded(int count) { infoPauseThresholdExceeded.incr(count); } diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/MetricsREST.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/MetricsREST.java index e31037a..8389ed1 100644 --- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/MetricsREST.java +++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/MetricsREST.java @@ -100,4 +100,32 @@ public class MetricsREST { source.incrementFailedScanRequests(inc); } + /** + * @param inc How much to add to sucessfulAppendCount. + */ + public synchronized void incrementSucessfulAppendRequests(final int inc) { + source.incrementSucessfulAppendRequests(inc); + } + + /** + * @param inc How much to add to failedAppendCount. + */ + public void incrementFailedAppendRequests(final int inc) { + source.incrementFailedAppendRequests(inc); + } + + /** + * @param inc How much to add to sucessfulIncrementCount. + */ + public synchronized void incrementSucessfulIncrementRequests(final int inc) { + source.incrementSucessfulIncrementRequests(inc); + } + + /** + * @param inc How much to add to failedIncrementCount. + */ + public void incrementFailedIncrementRequests(final int inc) { + source.incrementFailedIncrementRequests(inc); + } + } 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 61cc795..bb28b1b 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 @@ -44,8 +44,11 @@ import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.client.Append; import org.apache.hadoop.hbase.client.Delete; +import org.apache.hadoop.hbase.client.Increment; import org.apache.hadoop.hbase.client.Put; +import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.rest.model.CellModel; import org.apache.hadoop.hbase.rest.model.CellSetModel; @@ -56,22 +59,27 @@ import org.apache.hadoop.hbase.util.Bytes; public class RowResource extends ResourceBase { private static final Log LOG = LogFactory.getLog(RowResource.class); - static final String CHECK_PUT = "put"; - static final String CHECK_DELETE = "delete"; + private static final String CHECK_PUT = "put"; + private static final String CHECK_DELETE = "delete"; + private static final String CHECK_APPEND = "append"; + private static final String CHECK_INCREMENT = "increment"; - TableResource tableResource; - RowSpec rowspec; + private TableResource tableResource; + private RowSpec rowspec; private String check = null; + private boolean returnResult = false; /** * Constructor * @param tableResource * @param rowspec * @param versions + * @param check + * @param returnResult * @throws IOException */ public RowResource(TableResource tableResource, String rowspec, - String versions, String check) throws IOException { + String versions, String check, String returnResult) throws IOException { super(); this.tableResource = tableResource; this.rowspec = new RowSpec(rowspec); @@ -79,6 +87,9 @@ public class RowResource extends ResourceBase { this.rowspec.setMaxVersions(Integer.parseInt(versions)); } this.check = check; + if (returnResult != null) { + this.returnResult = Boolean.valueOf(returnResult); + } } @GET @@ -182,6 +193,10 @@ public class RowResource extends ResourceBase { return checkAndPut(model); } else if (CHECK_DELETE.equalsIgnoreCase(check)) { return checkAndDelete(model); + } else if (CHECK_APPEND.equalsIgnoreCase(check)) { + return append(model); + } else if (CHECK_INCREMENT.equalsIgnoreCase(check)) { + return increment(model); } else if (check != null && check.length() > 0) { return Response.status(Response.Status.BAD_REQUEST) .type(MIMETYPE_TEXT).entity("Invalid check value '" + check + "'" + CRLF) @@ -544,7 +559,7 @@ public class RowResource extends ResourceBase { if (model.getRows().size() != 1) { servlet.getMetrics().incrementFailedDeleteRequests(1); return Response.status(Response.Status.BAD_REQUEST) - .type(MIMETYPE_TEXT).entity("Bad request" + CRLF) + .type(MIMETYPE_TEXT).entity("Bad request: Number of rows specified is not 1." + CRLF) .build(); } RowModel rowModel = model.getRows().get(0); @@ -658,4 +673,195 @@ public class RowResource extends ResourceBase { } } } + + /** + * Validates the input request parameters, parses columns from CellSetModel, + * and invokes Append on HTable. + * + * @param model instance of CellSetModel + * @return Response 200 OK, 304 Not modified, 400 Bad request + */ + Response append(final CellSetModel model) { + Table table = null; + Append append = null; + try { + table = servlet.getTable(tableResource.getName()); + if (model.getRows().size() != 1) { + servlet.getMetrics().incrementFailedAppendRequests(1); + return Response.status(Response.Status.BAD_REQUEST) + .type(MIMETYPE_TEXT).entity("Bad request: Number of rows specified is not 1." + CRLF) + .build(); + } + RowModel rowModel = model.getRows().get(0); + byte[] key = rowModel.getKey(); + if (key == null) { + key = rowspec.getRow(); + } + if (key == null) { + servlet.getMetrics().incrementFailedAppendRequests(1); + return Response.status(Response.Status.BAD_REQUEST) + .type(MIMETYPE_TEXT).entity("Bad request: Row key found to be null." + CRLF) + .build(); + } + + append = new Append(key); + append.setReturnResults(returnResult); + int i = 0; + for (CellModel cell: rowModel.getCells()) { + byte[] col = cell.getColumn(); + if (col == null) { + try { + col = rowspec.getColumns()[i++]; + } catch (ArrayIndexOutOfBoundsException e) { + col = null; + } + } + if (col == null) { + servlet.getMetrics().incrementFailedAppendRequests(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) { + servlet.getMetrics().incrementFailedAppendRequests(1); + return Response.status(Response.Status.BAD_REQUEST) + .type(MIMETYPE_TEXT).entity("Bad request: Column incorrectly specified." + CRLF) + .build(); + } + append.add(parts[0], parts[1], cell.getValue()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("APPEND " + append.toString()); + } + Result result = table.append(append); + if (returnResult) { + if (result.isEmpty()) { + servlet.getMetrics().incrementFailedAppendRequests(1); + return Response.status(Response.Status.NOT_MODIFIED) + .type(MIMETYPE_TEXT).entity("Append return empty." + CRLF) + .build(); + } + + CellSetModel rModel = new CellSetModel(); + RowModel rRowModel = new RowModel(result.getRow()); + for (Cell cell : result.listCells()) { + rRowModel.addCell(new CellModel(CellUtil.cloneFamily(cell), CellUtil.cloneQualifier(cell), + cell.getTimestamp(), CellUtil.cloneValue(cell))); + } + rModel.addRow(rRowModel); + servlet.getMetrics().incrementSucessfulAppendRequests(1); + return Response.ok(rModel).build(); + } + servlet.getMetrics().incrementSucessfulAppendRequests(1); + return Response.ok().build(); + } catch (Exception e) { + servlet.getMetrics().incrementFailedAppendRequests(1); + return processException(e); + } finally { + if (table != null) try { + table.close(); + } catch (IOException ioe) { + LOG.debug("Exception received while closing the table" + table.getName(), ioe); + } + } + } + + /** + * Validates the input request parameters, parses columns from CellSetModel, + * and invokes Increment on HTable. + * + * @param model instance of CellSetModel + * @return Response 200 OK, 304 Not modified, 400 Bad request + */ + Response increment(final CellSetModel model) { + Table table = null; + Increment increment = null; + try { + table = servlet.getTable(tableResource.getName()); + if (model.getRows().size() != 1) { + servlet.getMetrics().incrementFailedIncrementRequests(1); + return Response.status(Response.Status.BAD_REQUEST) + .type(MIMETYPE_TEXT).entity("Bad request: Number of rows specified is not 1." + CRLF) + .build(); + } + RowModel rowModel = model.getRows().get(0); + byte[] key = rowModel.getKey(); + if (key == null) { + key = rowspec.getRow(); + } + if (key == null) { + servlet.getMetrics().incrementFailedIncrementRequests(1); + return Response.status(Response.Status.BAD_REQUEST) + .type(MIMETYPE_TEXT).entity("Bad request: Row key found to be null." + CRLF) + .build(); + } + + increment = new Increment(key); + increment.setReturnResults(returnResult); + int i = 0; + for (CellModel cell: rowModel.getCells()) { + byte[] col = cell.getColumn(); + if (col == null) { + try { + col = rowspec.getColumns()[i++]; + } catch (ArrayIndexOutOfBoundsException e) { + col = null; + } + } + if (col == null) { + servlet.getMetrics().incrementFailedIncrementRequests(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) { + servlet.getMetrics().incrementFailedIncrementRequests(1); + return Response.status(Response.Status.BAD_REQUEST) + .type(MIMETYPE_TEXT).entity("Bad request: Column incorrectly specified." + CRLF) + .build(); + } + increment.addColumn(parts[0], parts[1], Long.parseLong(Bytes.toStringBinary(cell.getValue()))); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("INCREMENT " + increment.toString()); + } + Result result = table.increment(increment); + + if (returnResult) { + if (result.isEmpty()) { + servlet.getMetrics().incrementFailedIncrementRequests(1); + return Response.status(Response.Status.NOT_MODIFIED) + .type(MIMETYPE_TEXT).entity("Increment return empty." + CRLF) + .build(); + } + + CellSetModel rModel = new CellSetModel(); + RowModel rRowModel = new RowModel(result.getRow()); + for (Cell cell : result.listCells()) { + rRowModel.addCell(new CellModel(CellUtil.cloneFamily(cell), CellUtil.cloneQualifier(cell), + cell.getTimestamp(), CellUtil.cloneValue(cell))); + } + rModel.addRow(rowModel); + servlet.getMetrics().incrementSucessfulIncrementRequests(1); + return Response.ok(rModel).build(); + } + + ResponseBuilder response = Response.ok(); + servlet.getMetrics().incrementSucessfulIncrementRequests(1); + return response.build(); + } catch (Exception e) { + servlet.getMetrics().incrementFailedIncrementRequests(1); + return processException(e); + } finally { + if (table != null) try { + table.close(); + } catch (IOException ioe) { + LOG.debug("Exception received while closing the table " + table.getName(), ioe); + } + } + } } diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/TableResource.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/TableResource.java index 2127dad..a1a60bb 100644 --- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/TableResource.java +++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/TableResource.java @@ -105,8 +105,9 @@ public class TableResource extends ResourceBase { // the RowSpec constructor has a chance to parse final @PathParam("rowspec") @Encoded String rowspec, final @QueryParam("v") String versions, - final @QueryParam("check") String check) throws IOException { - return new RowResource(this, rowspec, versions, check); + final @QueryParam("check") String check, + final @QueryParam("rr") String returnResult) throws IOException { + return new RowResource(this, rowspec, versions, check, returnResult); } @Path("{suffixglobbingspec: .*\\*/.+}") @@ -115,8 +116,9 @@ public class TableResource extends ResourceBase { // the RowSpec constructor has a chance to parse final @PathParam("suffixglobbingspec") @Encoded String suffixglobbingspec, final @QueryParam("v") String versions, - final @QueryParam("check") String check) throws IOException { - return new RowResource(this, suffixglobbingspec, versions, check); + final @QueryParam("check") String check, + final @QueryParam("rr") String returnResult) throws IOException { + return new RowResource(this, suffixglobbingspec, versions, check, returnResult); } @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="REC_CATCH_EXCEPTION") 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 060409e..00abe3a 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 @@ -30,7 +30,6 @@ 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; @@ -45,6 +44,7 @@ import org.apache.hadoop.hbase.rest.model.CellSetModel; import org.apache.hadoop.hbase.rest.model.RowModel; import org.apache.hadoop.hbase.rest.provider.JacksonProvider; import org.apache.hadoop.hbase.util.Bytes; +import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider; import org.codehaus.jackson.map.ObjectMapper; import org.junit.After; import org.junit.AfterClass; @@ -67,6 +67,8 @@ public class RowResourceBase { protected static final String VALUE_3 = "testvalue3"; protected static final String ROW_4 = "testrow4"; protected static final String VALUE_4 = "testvalue4"; + protected static final String VALUE_5 = "5"; + protected static final String VALUE_6 = "6"; protected static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); protected static final HBaseRESTTestingUtility REST_TEST_UTIL = @@ -172,6 +174,19 @@ public class RowResourceBase { assertEquals(Bytes.toString(cell.getValue()), value); } + protected static void checkIncrementValueXML(String table, String row, String column, + long value) throws IOException, JAXBException { + Response response1 = getValueXML(table, row, column); + assertEquals(response1.getCode(), 200); + assertEquals(Constants.MIMETYPE_XML, response1.getHeader("content-type")); + CellSetModel cellSet = (CellSetModel) + xmlUnmarshaller.unmarshal(new ByteArrayInputStream(response1.getBody())); + RowModel rowModel = cellSet.getRows().get(0); + CellModel cell = rowModel.getCells().get(0); + assertEquals(Bytes.toString(cell.getColumn()), column); + assertEquals(Bytes.toLong(cell.getValue()), value); + } + protected static Response getValuePB(String url) throws IOException { Response response = client.get(url, Constants.MIMETYPE_PROTOBUF); return response; @@ -229,6 +244,19 @@ public class RowResourceBase { assertEquals(Bytes.toString(cell.getValue()), value); } + protected static void checkIncrementValuePB(String table, String row, String column, + long value) throws IOException { + Response response = getValuePB(table, row, column); + assertEquals(response.getCode(), 200); + assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type")); + CellSetModel cellSet = new CellSetModel(); + cellSet.getObjectFromMessage(response.getBody()); + RowModel rowModel = cellSet.getRows().get(0); + CellModel cell = rowModel.getCells().get(0); + assertEquals(Bytes.toString(cell.getColumn()), column); + assertEquals(Bytes.toLong(cell.getValue()), value); + } + protected static Response checkAndPutValuePB(String url, String table, String row, String column, String valueToCheck, String valueToPut, HashMap otherCells) throws IOException { @@ -516,6 +544,20 @@ public class RowResourceBase { assertEquals(Bytes.toString(cell.getValue()), value); } + protected static void checkIncrementValueJSON(String table, String row, String column, + long value) throws IOException, JAXBException { + Response response = getValueJson(table, row, column); + assertEquals(response.getCode(), 200); + assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type")); + ObjectMapper mapper = new JacksonJaxbJsonProvider() + .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE); + CellSetModel cellSet = mapper.readValue(response.getBody(), CellSetModel.class); + RowModel rowModel = cellSet.getRows().get(0); + CellModel cell = rowModel.getCells().get(0); + assertEquals(Bytes.toString(cell.getColumn()), column); + assertEquals(Bytes.toLong(cell.getValue()), value); + } + protected static Response putValueJson(String table, String row, String column, String value) throws IOException, JAXBException { StringBuilder path = new StringBuilder(); @@ -542,4 +584,69 @@ public class RowResourceBase { return response; } + protected static Response appendValueXML(String table, String row, String column, + String value) throws IOException, JAXBException { + StringBuilder path = new StringBuilder(); + path.append('/'); + path.append(table); + path.append('/'); + path.append(row); + path.append("?check=append"); + return putValueXML(path.toString(), table, row, column, value); + } + + protected static Response appendValuePB(String table, String row, String column, + String value) throws IOException, JAXBException { + StringBuilder path = new StringBuilder(); + path.append('/'); + path.append(table); + path.append('/'); + path.append(row); + path.append("?check=append"); + return putValuePB(path.toString(), table, row, column, value); + } + + protected static Response appendValueJson(String table, String row, String column, + String value) throws IOException, JAXBException { + StringBuilder path = new StringBuilder(); + path.append('/'); + path.append(table); + path.append('/'); + path.append(row); + path.append("?check=append"); + return putValueJson(path.toString(), table, row, column, value); + } + + protected static Response incrementValueXML(String table, String row, String column, + String value) throws IOException, JAXBException { + StringBuilder path = new StringBuilder(); + path.append('/'); + path.append(table); + path.append('/'); + path.append(row); + path.append("?check=increment"); + return putValueXML(path.toString(), table, row, column, value); + } + + protected static Response incrementValuePB(String table, String row, String column, + String value) throws IOException, JAXBException { + StringBuilder path = new StringBuilder(); + path.append('/'); + path.append(table); + path.append('/'); + path.append(row); + path.append("?check=increment"); + return putValuePB(path.toString(), table, row, column, value); + } + + protected static Response incrementValueJson(String table, String row, String column, + String value) throws IOException, JAXBException { + StringBuilder path = new StringBuilder(); + path.append('/'); + path.append(table); + path.append('/'); + path.append(row); + path.append("?check=increment"); + return putValueJson(path.toString(), table, row, column, value); + } } 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 5c6fd91..25b445e 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 @@ -701,5 +701,110 @@ public class TestGetAndPutResource extends RowResourceBase { response = deleteRow(TABLE, ROW_2); assertEquals(response.getCode(), 200); } + + @Test + public void testAppendXML() throws IOException, JAXBException { + Response response = getValueXML(TABLE, ROW_1, COLUMN_1); + assertEquals(response.getCode(), 404); + + //append cell + response = appendValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); + assertEquals(response.getCode(), 200); + checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1); + response = appendValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2); + assertEquals(response.getCode(), 200); + checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2); + + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } + + @Test + public void testAppendPB() throws IOException, JAXBException { + Response response = getValuePB(TABLE, ROW_1, COLUMN_1); + assertEquals(response.getCode(), 404); + + //append cell + response = appendValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); + assertEquals(response.getCode(), 200); + checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1); + response = appendValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2); + assertEquals(response.getCode(), 200); + checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2); + + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } + + @Test + public void testAppendJSON() throws IOException, JAXBException { + Response response = getValueJson(TABLE, ROW_1, COLUMN_1); + assertEquals(response.getCode(), 404); + + //append cell + response = appendValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1); + assertEquals(response.getCode(), 200); + putValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1); + response = appendValueJson(TABLE, ROW_1, COLUMN_1, VALUE_2); + assertEquals(response.getCode(), 200); + putValueJson(TABLE, ROW_1, COLUMN_1, VALUE_1 + VALUE_2); + + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } + + @Test + public void testIncrementXML() throws IOException, JAXBException { + Response response = getValueXML(TABLE, ROW_1, COLUMN_1); + assertEquals(response.getCode(), 404); + + //append single cell + response = incrementValueXML(TABLE, ROW_1, COLUMN_1, VALUE_5); + assertEquals(response.getCode(), 200); + checkIncrementValueXML(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5)); + response = incrementValueXML(TABLE, ROW_1, COLUMN_1, VALUE_6); + assertEquals(response.getCode(), 200); + checkIncrementValueXML(TABLE, ROW_1, COLUMN_1, + Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6)); + + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } + + @Test + public void testIncrementPB() throws IOException, JAXBException { + Response response = getValuePB(TABLE, ROW_1, COLUMN_1); + assertEquals(response.getCode(), 404); + + //append cell + response = incrementValuePB(TABLE, ROW_1, COLUMN_1, VALUE_5); + assertEquals(response.getCode(), 200); + checkIncrementValuePB(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5)); + response = incrementValuePB(TABLE, ROW_1, COLUMN_1, VALUE_6); + assertEquals(response.getCode(), 200); + checkIncrementValuePB(TABLE, ROW_1, COLUMN_1, + Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6)); + + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } + + @Test + public void testIncrementJSON() throws IOException, JAXBException { + Response response = getValueJson(TABLE, ROW_1, COLUMN_1); + assertEquals(response.getCode(), 404); + + //append cell + response = incrementValueJson(TABLE, ROW_1, COLUMN_1, VALUE_5); + assertEquals(response.getCode(), 200); + checkIncrementValueJSON(TABLE, ROW_1, COLUMN_1, Long.parseLong(VALUE_5)); + response = incrementValueJson(TABLE, ROW_1, COLUMN_1, VALUE_6); + assertEquals(response.getCode(), 200); + checkIncrementValueJSON(TABLE, ROW_1, COLUMN_1, + Long.parseLong(VALUE_5) + Long.parseLong(VALUE_6)); + + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } } -- 1.9.5.msysgit.0