HBASE-15290 Hbase Rest CheckAndAPI should save other cells along with compared cell (Ajith)

This commit is contained in:
Enis Soztutar 2016-02-26 15:05:59 -08:00
parent 8f6e29785a
commit 793babf4a4
3 changed files with 129 additions and 11 deletions

View File

@ -455,20 +455,40 @@ public class RowResource extends ResourceBase {
byte[][] valueToPutParts = KeyValue.parseColumn(valueToCheckColumn); byte[][] valueToPutParts = KeyValue.parseColumn(valueToCheckColumn);
if (valueToPutParts.length == 2 && valueToPutParts[1].length > 0) { if (valueToPutParts.length == 2 && valueToPutParts[1].length > 0) {
CellModel valueToPutCell = null; 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++) { for (int i = 0, n = cellModelCount - 1; i < n ; i++) {
if(Bytes.equals(cellModels.get(i).getColumn(), CellModel cell = cellModels.get(i);
valueToCheckCell.getColumn())) { byte[] col = cell.getColumn();
valueToPutCell = cellModels.get(i);
break; 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) { if (valueToPutCell == null) {
servlet.getMetrics().incrementFailedPutRequests(1); servlet.getMetrics().incrementFailedPutRequests(1);
return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT) return Response.status(Response.Status.BAD_REQUEST).type(MIMETYPE_TEXT)
.entity("Bad request: The column to put and check do not match." + CRLF).build(); .entity("Bad request: The column to put and check do not match." + CRLF).build();
} else { } else {
put.addImmutable(valueToPutParts[0], valueToPutParts[1], valueToPutCell.getTimestamp(),
valueToPutCell.getValue());
retValue = table.checkAndPut(key, valueToPutParts[0], valueToPutParts[1], retValue = table.checkAndPut(key, valueToPutParts[0], valueToPutParts[1],
valueToCheckCell.getValue(), put); valueToCheckCell.getValue(), put);
} }

View File

@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.*;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBContext;
@ -29,6 +30,7 @@ import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller; import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller; import javax.xml.bind.Unmarshaller;
import org.apache.commons.collections.keyvalue.AbstractMapEntry;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HColumnDescriptor;
@ -232,13 +234,22 @@ public class RowResourceBase {
} }
protected static Response checkAndPutValuePB(String url, String table, 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 { throws IOException {
RowModel rowModel = new RowModel(row); RowModel rowModel = new RowModel(row);
rowModel.addCell(new CellModel(Bytes.toBytes(column), rowModel.addCell(new CellModel(Bytes.toBytes(column),
Bytes.toBytes(valueToPut))); 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), rowModel.addCell(new CellModel(Bytes.toBytes(column),
Bytes.toBytes(valueToCheck))); Bytes.toBytes(valueToCheck)));
CellSetModel cellSetModel = new CellSetModel(); CellSetModel cellSetModel = new CellSetModel();
cellSetModel.addRow(rowModel); cellSetModel.addRow(rowModel);
Response response = client.put(url, Constants.MIMETYPE_PROTOBUF, Response response = client.put(url, Constants.MIMETYPE_PROTOBUF,
@ -249,6 +260,10 @@ public class RowResourceBase {
protected static Response checkAndPutValuePB(String table, String row, protected static Response checkAndPutValuePB(String table, String row,
String column, String valueToCheck, String valueToPut) throws IOException { 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(); StringBuilder path = new StringBuilder();
path.append('/'); path.append('/');
path.append(table); path.append(table);
@ -256,15 +271,23 @@ public class RowResourceBase {
path.append(row); path.append(row);
path.append("?check=put"); path.append("?check=put");
return checkAndPutValuePB(path.toString(), table, row, column, return checkAndPutValuePB(path.toString(), table, row, column,
valueToCheck, valueToPut); valueToCheck, valueToPut, otherCells);
} }
protected static Response checkAndPutValueXML(String url, String table, 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 { throws IOException, JAXBException {
RowModel rowModel = new RowModel(row); RowModel rowModel = new RowModel(row);
rowModel.addCell(new CellModel(Bytes.toBytes(column), rowModel.addCell(new CellModel(Bytes.toBytes(column),
Bytes.toBytes(valueToPut))); 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), rowModel.addCell(new CellModel(Bytes.toBytes(column),
Bytes.toBytes(valueToCheck))); Bytes.toBytes(valueToCheck)));
CellSetModel cellSetModel = new CellSetModel(); CellSetModel cellSetModel = new CellSetModel();
@ -278,7 +301,13 @@ public class RowResourceBase {
} }
protected static Response checkAndPutValueXML(String table, String row, 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 { throws IOException, JAXBException {
StringBuilder path = new StringBuilder(); StringBuilder path = new StringBuilder();
path.append('/'); path.append('/');
@ -287,7 +316,7 @@ public class RowResourceBase {
path.append(row); path.append(row);
path.append("?check=put"); path.append("?check=put");
return checkAndPutValueXML(path.toString(), table, row, column, return checkAndPutValueXML(path.toString(), table, row, column,
valueToCheck, valueToPut); valueToCheck, valueToPut, otherCells);
} }
protected static Response checkAndDeleteXML(String url, String table, protected static Response checkAndDeleteXML(String url, String table,

View File

@ -24,7 +24,10 @@ import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
@ -128,6 +131,72 @@ public class TestGetAndPutResource extends RowResourceBase {
assertEquals(response.getCode(), 200); assertEquals(response.getCode(), 200);
} }
@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 @Test
public void testSingleCellGetPutBinary() throws IOException { public void testSingleCellGetPutBinary() throws IOException {
final String path = "/" + TABLE + "/" + ROW_3 + "/" + COLUMN_1; final String path = "/" + TABLE + "/" + ROW_3 + "/" + COLUMN_1;