diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/Constants.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/Constants.java index 505dbb3a3c8..54ce1170846 100644 --- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/Constants.java +++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/Constants.java @@ -68,7 +68,8 @@ public interface Constants { String SCAN_BATCH_SIZE = "batchsize"; String SCAN_LIMIT = "limit"; String SCAN_FETCH_SIZE = "hbase.rest.scan.fetchsize"; - String SCAN_FILTER = "filter"; + String SCAN_FILTER = "filter"; + String SCAN_REVERSED = "reversed"; String CUSTOM_FILTERS = "hbase.rest.custom.filters"; String ROW_KEYS_PARAM_NAME = "row"; 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 45e7caf15dc..9eb21ecc8d9 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 @@ -134,6 +134,7 @@ public class TableResource extends ResourceBase { @DefaultValue("0") @QueryParam(Constants.SCAN_START_TIME) long startTime, @DefaultValue(Long.MAX_VALUE + "") @QueryParam(Constants.SCAN_END_TIME) long endTime, @DefaultValue("true") @QueryParam(Constants.SCAN_BATCH_SIZE) boolean cacheBlocks, + @DefaultValue("false") @QueryParam(Constants.SCAN_REVERSED) boolean reversed, @DefaultValue("") @QueryParam(Constants.SCAN_FILTER) String filters) { try { Filter filter = null; @@ -200,6 +201,7 @@ public class TableResource extends ResourceBase { } int fetchSize = this.servlet.getConfiguration().getInt(Constants.SCAN_FETCH_SIZE, 10); tableScan.setCaching(fetchSize); + tableScan.setReversed(reversed); return new TableScanResource(hTable.getScanner(tableScan), userRequestedLimit); } catch (IOException exp) { servlet.getMetrics().incrementFailedScanRequests(1); diff --git a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestTableScan.java b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestTableScan.java index 789e9e1f383..7924aed392b 100644 --- a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestTableScan.java +++ b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/TestTableScan.java @@ -29,6 +29,8 @@ import java.io.InputStream; import java.io.Serializable; import java.net.URLEncoder; import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import javax.ws.rs.core.MediaType; @@ -548,6 +550,56 @@ public class TestTableScan { assertEquals(0, count); } + @Test + public void testReversed() throws IOException, JAXBException { + StringBuilder builder = new StringBuilder(); + builder.append("/*"); + builder.append("?"); + builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1); + builder.append("&"); + builder.append(Constants.SCAN_START_ROW + "=aaa"); + builder.append("&"); + builder.append(Constants.SCAN_END_ROW + "=aay"); + Response response = client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML); + assertEquals(200, response.getCode()); + JAXBContext ctx = JAXBContext.newInstance(CellSetModel.class); + Unmarshaller ush = ctx.createUnmarshaller(); + CellSetModel model = (CellSetModel) ush.unmarshal(response.getStream()); + int count = TestScannerResource.countCellSet(model); + assertEquals(24, count); + List rowModels = model.getRows().subList(1, count); + + //reversed + builder = new StringBuilder(); + builder.append("/*"); + builder.append("?"); + builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1); + builder.append("&"); + builder.append(Constants.SCAN_START_ROW + "=aay"); + builder.append("&"); + builder.append(Constants.SCAN_END_ROW + "=aaa"); + builder.append("&"); + builder.append(Constants.SCAN_REVERSED + "=true"); + response = client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML); + assertEquals(200, response.getCode()); + model = (CellSetModel) ush.unmarshal(response.getStream()); + count = TestScannerResource.countCellSet(model); + assertEquals(24, count); + List reversedRowModels = model.getRows().subList(1, count); + + Collections.reverse(reversedRowModels); + assertEquals(rowModels.size(), reversedRowModels.size()); + for (int i = 0; i < rowModels.size(); i++) { + RowModel rowModel = rowModels.get(i); + RowModel reversedRowModel = reversedRowModels.get(i); + + assertEquals(new String(rowModel.getKey(), "UTF-8"), + new String(reversedRowModel.getKey(), "UTF-8")); + assertEquals(new String(rowModel.getCells().get(0).getValue(), "UTF-8"), + new String(reversedRowModel.getCells().get(0).getValue(), "UTF-8")); + } + } + public static class CustomFilter extends PrefixFilter { private byte[] key = null;