diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java index 3a587f8..f3fc679 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowResource.java @@ -92,6 +92,7 @@ public class RowResource extends ResourceBase { ResultGenerator generator = ResultGenerator.fromRowSpec(tableResource.getName(), rowspec, null); if (!generator.hasNext()) { + servlet.getMetrics().incrementFailedGetRequests(1); return Response.status(Response.Status.NOT_FOUND) .type(MIMETYPE_TEXT).entity("Not found" + CRLF) .build(); @@ -118,7 +119,7 @@ public class RowResource extends ResourceBase { servlet.getMetrics().incrementSucessfulGetRequests(1); return Response.ok(model).build(); } catch (RuntimeException e) { - servlet.getMetrics().incrementFailedPutRequests(1); + servlet.getMetrics().incrementFailedGetRequests(1); if (e.getCause() instanceof TableNotFoundException) { return Response.status(Response.Status.NOT_FOUND) .type(MIMETYPE_TEXT).entity("Not found" + CRLF) @@ -128,7 +129,7 @@ public class RowResource extends ResourceBase { .type(MIMETYPE_TEXT).entity("Bad request" + CRLF) .build(); } catch (Exception e) { - servlet.getMetrics().incrementFailedPutRequests(1); + servlet.getMetrics().incrementFailedGetRequests(1); return Response.status(Response.Status.SERVICE_UNAVAILABLE) .type(MIMETYPE_TEXT).entity("Unavailable" + CRLF) .build(); @@ -153,6 +154,7 @@ public class RowResource extends ResourceBase { ResultGenerator generator = ResultGenerator.fromRowSpec(tableResource.getName(), rowspec, null); if (!generator.hasNext()) { + servlet.getMetrics().incrementFailedGetRequests(1); return Response.status(Response.Status.NOT_FOUND) .type(MIMETYPE_TEXT).entity("Not found" + CRLF) .build(); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowSpec.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowSpec.java index 5e25260..53d6e78 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowSpec.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/RowSpec.java @@ -106,8 +106,7 @@ public class RowSpec { return i; } - private int parseColumns(final String path, int i) - throws IllegalArgumentException { + private int parseColumns(final String path, int i) throws IllegalArgumentException { if (i >= path.length()) { return i; } @@ -119,8 +118,7 @@ public class RowSpec { if (column.length() < 1) { throw new IllegalArgumentException("invalid path"); } - String s = URLDecoder.decode(column.toString(), - HConstants.UTF8_ENCODING); + String s = URLDecoder.decode(column.toString(), HConstants.UTF8_ENCODING); this.columns.add(Bytes.toBytes(s)); column.setLength(0); i++; @@ -132,8 +130,7 @@ public class RowSpec { i++; // trailing list entry if (column.length() > 0) { - String s = URLDecoder.decode(column.toString(), - HConstants.UTF8_ENCODING); + String s = URLDecoder.decode(column.toString(), HConstants.UTF8_ENCODING); this.columns.add(Bytes.toBytes(s)); } } catch (IndexOutOfBoundsException e) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java index fb16769..6352c4a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rest/client/RemoteHTable.java @@ -97,7 +97,10 @@ public class RemoteHTable implements HTableInterface { while (i.hasNext()) { Map.Entry e = (Map.Entry)i.next(); Collection quals = (Collection)e.getValue(); - if (quals != null && !quals.isEmpty()) { + if (quals == null || quals.isEmpty()) { + // this is an unqualified family. append the family name and NO ':' + sb.append(Bytes.toStringBinary((byte[])e.getKey())); + } else { Iterator ii = quals.iterator(); while (ii.hasNext()) { sb.append(Bytes.toStringBinary((byte[])e.getKey())); @@ -115,9 +118,6 @@ public class RemoteHTable implements HTableInterface { sb.append(','); } } - } else { - // this is an unqualified family. append the family name and NO ':' - sb.append(Bytes.toStringBinary((byte[])e.getKey())); } if (i.hasNext()) { sb.append(','); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestRowResource.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestRowResource.java index eb8a41f..ceff180 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestRowResource.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/TestRowResource.java @@ -26,6 +26,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringWriter; import java.net.URLEncoder; +import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -66,6 +67,7 @@ public class TestRowResource { private static final String CFB = "b"; private static final String COLUMN_1 = CFA + ":1"; private static final String COLUMN_2 = CFB + ":2"; + private static final String COLUMN_3 = CFA + ":"; private static final String ROW_1 = "testrow1"; private static final String VALUE_1 = "testvalue1"; private static final String ROW_2 = "testrow2"; @@ -711,7 +713,7 @@ public class TestRowResource { for (CellModel cell: rowModel.getCells()) { assertEquals(COLUMN_1, Bytes.toString(cell.getColumn())); assertEquals(values[i], Bytes.toString(cell.getValue())); - } + } } for (String row : rows) { response = deleteRow(TABLE, row); @@ -764,5 +766,52 @@ public class TestRowResource { assertEquals(response.getCode(), 200); } + @Test + public void testMultiColumnGetXML() throws Exception { + String path = "/" + TABLE + "/fakerow"; + CellSetModel cellSetModel = new CellSetModel(); + RowModel rowModel = new RowModel(ROW_1); + rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1), Bytes.toBytes(VALUE_1))); + rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2), Bytes.toBytes(VALUE_2))); + rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_3), Bytes.toBytes(VALUE_2))); + cellSetModel.addRow(rowModel); + StringWriter writer = new StringWriter(); + marshaller.marshal(cellSetModel, writer); + + Response response = client.put(path, Constants.MIMETYPE_XML, Bytes.toBytes(writer.toString())); + Thread.yield(); + + // make sure the fake row was not actually created + response = client.get(path, Constants.MIMETYPE_XML); + assertEquals(response.getCode(), 404); + + // Try getting all the column values at once. + path = "/" + TABLE + "/" + ROW_1 + "/" + COLUMN_1 + "," + COLUMN_2 + "," + COLUMN_3; + response = client.get(path, Constants.MIMETYPE_XML); + assertEquals(200, response.getCode()); + CellSetModel cellSet = (CellSetModel) unmarshaller.unmarshal(new ByteArrayInputStream(response + .getBody())); + assertTrue(cellSet.getRows().size() == 1); + assertTrue(cellSet.getRows().get(0).getCells().size() == 3); + List cells = cellSet.getRows().get(0).getCells(); + + assertTrue(containsCellModel(cells, COLUMN_1, VALUE_1)); + assertTrue(containsCellModel(cells, COLUMN_2, VALUE_2)); + assertTrue(containsCellModel(cells, COLUMN_3, VALUE_2)); + response = deleteRow(TABLE, ROW_1); + assertEquals(response.getCode(), 200); + } + + private boolean containsCellModel(List cells, String column, String value) { + boolean contains = false; + for (CellModel cell : cells) { + if (Bytes.toString(cell.getColumn()).equals(column) + && Bytes.toString(cell.getValue()).equals(value)) { + contains = true; + return contains; + } + } + return contains; + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java index 4f24cc9..deffbd9 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/rest/client/TestRemoteTable.java @@ -157,7 +157,7 @@ public class TestRemoteTable { assertNull(value2); get = new Get(ROW_2); - result = remoteTable.get(get); + result = remoteTable.get(get); value1 = result.getValue(COLUMN_1, QUALIFIER_1); value2 = result.getValue(COLUMN_2, QUALIFIER_2); assertNotNull(value1); @@ -167,7 +167,7 @@ public class TestRemoteTable { get = new Get(ROW_2); get.addFamily(COLUMN_1); - result = remoteTable.get(get); + result = remoteTable.get(get); value1 = result.getValue(COLUMN_1, QUALIFIER_1); value2 = result.getValue(COLUMN_2, QUALIFIER_2); assertNotNull(value1); @@ -177,7 +177,7 @@ public class TestRemoteTable { get = new Get(ROW_2); get.addColumn(COLUMN_1, QUALIFIER_1); get.addColumn(COLUMN_2, QUALIFIER_2); - result = remoteTable.get(get); + result = remoteTable.get(get); value1 = result.getValue(COLUMN_1, QUALIFIER_1); value2 = result.getValue(COLUMN_2, QUALIFIER_2); assertNotNull(value1); @@ -191,7 +191,7 @@ public class TestRemoteTable { get.addFamily(COLUMN_1); get.addFamily(COLUMN_2); get.setTimeStamp(TS_1); - result = remoteTable.get(get); + result = remoteTable.get(get); value1 = result.getValue(COLUMN_1, QUALIFIER_1); value2 = result.getValue(COLUMN_2, QUALIFIER_2); assertNotNull(value1); @@ -204,7 +204,7 @@ public class TestRemoteTable { get.addFamily(COLUMN_1); get.addFamily(COLUMN_2); get.setTimeRange(0, TS_1 + 1); - result = remoteTable.get(get); + result = remoteTable.get(get); value1 = result.getValue(COLUMN_1, QUALIFIER_1); value2 = result.getValue(COLUMN_2, QUALIFIER_2); assertNotNull(value1); @@ -334,7 +334,7 @@ public class TestRemoteTable { Delete delete = new Delete(ROW_3); delete.deleteColumn(COLUMN_2, QUALIFIER_2); remoteTable.delete(delete); - + get = new Get(ROW_3); get.addFamily(COLUMN_1); get.addFamily(COLUMN_2); @@ -358,7 +358,7 @@ public class TestRemoteTable { assertNotNull(value1); assertTrue(Bytes.equals(VALUE_1, value1)); assertNull(value2); - + delete = new Delete(ROW_3); remoteTable.delete(delete); @@ -369,7 +369,7 @@ public class TestRemoteTable { value1 = result.getValue(COLUMN_1, QUALIFIER_1); value2 = result.getValue(COLUMN_2, QUALIFIER_2); assertNull(value1); - assertNull(value2); + assertNull(value2); } public void testScanner() throws IOException {