HBASE-13779 Calling table.exists() before table.get() end up with an empty Result
This commit is contained in:
parent
93e475e5ba
commit
5b67c7a0da
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue