HBASE-13779 Calling table.exists() before table.get() end up with an empty Result

This commit is contained in:
Matteo Bertozzi 2015-05-29 16:39:03 +01:00
parent 93e475e5ba
commit 5b67c7a0da
3 changed files with 97 additions and 14 deletions

View File

@ -107,7 +107,18 @@ public class Get extends Query
this.tr = get.getTimeRange();
this.checkExistenceOnly = get.isCheckExistenceOnly();
this.closestRowBefore = get.isClosestRowBefore();
this.familyMap = get.getFamilyMap();
Map<byte[], NavigableSet<byte[]>> fams = get.getFamilyMap();
for (Map.Entry<byte[],NavigableSet<byte[]>> entry : fams.entrySet()) {
byte [] fam = entry.getKey();
NavigableSet<byte[]> cols = entry.getValue();
if (cols != null && cols.size() > 0) {
for (byte[] col : cols) {
addColumn(fam, col);
}
} else {
addFamily(fam);
}
}
for (Map.Entry<String, byte[]> attr : get.getAttributesMap().entrySet()) {
setAttribute(attr.getKey(), attr.getValue());
}

View File

@ -70,6 +70,7 @@ import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescripto
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.hbase.util.ReflectionUtils;
import org.apache.hadoop.hbase.util.Threads;
import com.google.common.annotations.VisibleForTesting;
@ -782,6 +783,7 @@ public class HTable implements HTableInterface, RegionLocator {
if (scan.getBatch() > 0 && scan.isSmall()) {
throw new IllegalArgumentException("Small scan should not be used with batching");
}
if (scan.getCaching() <= 0) {
scan.setCaching(getScannerCaching());
}
@ -840,18 +842,28 @@ public class HTable implements HTableInterface, RegionLocator {
*/
@Override
public Result get(final Get get) throws IOException {
if (get.getConsistency() == null){
get.setConsistency(defaultConsistency);
return get(get, false);
}
private Result get(Get get, final boolean checkExistenceOnly) throws IOException {
// if we are changing settings to the get, clone it.
if (get.isCheckExistenceOnly() != checkExistenceOnly || get.getConsistency() == null) {
get = ReflectionUtils.newInstance(get.getClass(), get);
get.setCheckExistenceOnly(checkExistenceOnly);
if (get.getConsistency() == null){
get.setConsistency(defaultConsistency);
}
}
if (get.getConsistency() == Consistency.STRONG) {
// Good old call.
final Get getReq = get;
RegionServerCallable<Result> callable = new RegionServerCallable<Result>(this.connection,
getName(), get.getRow()) {
@Override
public Result call(int callTimeout) throws IOException {
ClientProtos.GetRequest request =
RequestConverter.buildGetRequest(getLocation().getRegionInfo().getRegionName(), get);
RequestConverter.buildGetRequest(getLocation().getRegionInfo().getRegionName(), getReq);
PayloadCarryingRpcController controller = rpcControllerFactory.newController();
controller.setPriority(tableName);
controller.setCallTimeout(callTimeout);
@ -1362,8 +1374,7 @@ public class HTable implements HTableInterface, RegionLocator {
*/
@Override
public boolean exists(final Get get) throws IOException {
get.setCheckExistenceOnly(true);
Result r = get(get);
Result r = get(get, true);
assert r.getExists() != null;
return r.getExists();
}
@ -1376,13 +1387,16 @@ public class HTable implements HTableInterface, RegionLocator {
if (gets.isEmpty()) return new boolean[]{};
if (gets.size() == 1) return new boolean[]{exists(gets.get(0))};
ArrayList<Get> exists = new ArrayList<Get>(gets.size());
for (Get g: gets){
g.setCheckExistenceOnly(true);
Get ge = new Get(g);
ge.setCheckExistenceOnly(true);
exists.add(ge);
}
Object[] r1;
try {
r1 = batch(gets);
r1 = batch(exists);
} catch (InterruptedException e) {
throw (InterruptedIOException)new InterruptedIOException().initCause(e);
}

View File

@ -96,7 +96,10 @@ public class TestFromClientSide3 {
*/
@After
public void tearDown() throws Exception {
// Nothing to do.
for (HTableDescriptor htd: TEST_UTIL.getHBaseAdmin().listTables()) {
LOG.info("Tear down, remove table=" + htd.getTableName());
TEST_UTIL.deleteTable(htd.getTableName());
}
}
private void randomCFPuts(Table table, byte[] row, byte[] family, int nPuts)
@ -276,20 +279,20 @@ public class TestFromClientSide3 {
// create an empty Put
Put put1 = new Put(ROW);
actions.add(put1);
Put put2 = new Put(ANOTHERROW);
put2.add(FAMILY, QUALIFIER, VALUE);
actions.add(put2);
table.batch(actions, results);
fail("Empty Put should have failed the batch call");
} catch (IllegalArgumentException iae) {
} finally {
table.close();
}
}
@Test
public void testHTableExistsMethodSingleRegionSingleGet() throws Exception {
@ -332,6 +335,61 @@ public class TestFromClientSide3 {
assertEquals(results[2], false);
}
@Test
public void testHTableExistsBeforeGet() throws Exception {
Table table = TEST_UTIL.createTable(
Bytes.toBytes("testHTableExistsBeforeGet"), new byte[][] { FAMILY });
try {
Put put = new Put(ROW);
put.add(FAMILY, QUALIFIER, VALUE);
table.put(put);
Get get = new Get(ROW);
boolean exist = table.exists(get);
assertEquals(true, exist);
Result result = table.get(get);
assertEquals(false, result.isEmpty());
assertTrue(Bytes.equals(VALUE, result.getValue(FAMILY, QUALIFIER)));
} finally {
table.close();
}
}
@Test
public void testHTableExistsAllBeforeGet() throws Exception {
final byte[] ROW2 = Bytes.add(ROW, Bytes.toBytes("2"));
Table table = TEST_UTIL.createTable(
Bytes.toBytes("testHTableExistsAllBeforeGet"), new byte[][] { FAMILY });
try {
Put put = new Put(ROW);
put.add(FAMILY, QUALIFIER, VALUE);
table.put(put);
put = new Put(ROW2);
put.add(FAMILY, QUALIFIER, VALUE);
table.put(put);
Get get = new Get(ROW);
Get get2 = new Get(ROW2);
ArrayList<Get> getList = new ArrayList(2);
getList.add(get);
getList.add(get2);
boolean[] exists = table.existsAll(getList);
assertEquals(true, exists[0]);
assertEquals(true, exists[1]);
Result[] result = table.get(getList);
assertEquals(false, result[0].isEmpty());
assertTrue(Bytes.equals(VALUE, result[0].getValue(FAMILY, QUALIFIER)));
assertEquals(false, result[1].isEmpty());
assertTrue(Bytes.equals(VALUE, result[1].getValue(FAMILY, QUALIFIER)));
} finally {
table.close();
}
}
@Test
public void testHTableExistsMethodMultipleRegionsSingleGet() throws Exception {
@ -355,7 +413,7 @@ public class TestFromClientSide3 {
@Test
public void testHTableExistsMethodMultipleRegionsMultipleGets() throws Exception {
HTable table = TEST_UTIL.createTable(
TableName.valueOf("testHTableExistsMethodMultipleRegionsMultipleGets"),
TableName.valueOf("testHTableExistsMethodMultipleRegionsMultipleGets"),
new byte[][] { FAMILY }, 1, new byte[] { 0x00 }, new byte[] { (byte) 0xff }, 255);
Put put = new Put(ROW);
put.add(FAMILY, QUALIFIER, VALUE);