HBASE-19774 incorrect behavior of locateRegionInMeta

This commit is contained in:
Sergey Soldatov 2018-01-11 13:40:38 -08:00 committed by Michael Stack
parent 5f62041cb1
commit 6f8c31242a
2 changed files with 49 additions and 24 deletions

View File

@ -786,11 +786,14 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
// build the key of the meta region we should be looking for. // build the key of the meta region we should be looking for.
// the extra 9's on the end are necessary to allow "exact" matches // the extra 9's on the end are necessary to allow "exact" matches
// without knowing the precise region names. // without knowing the precise region names.
byte[] metaKey = RegionInfo.createRegionName(tableName, row, HConstants.NINES, false); byte[] metaStartKey = RegionInfo.createRegionName(tableName, row, HConstants.NINES, false);
byte[] metaStopKey =
RegionInfo.createRegionName(tableName, HConstants.EMPTY_START_ROW, "", false);
Scan s = new Scan(); Scan s = new Scan();
s.setReversed(true); s.setReversed(true);
s.withStartRow(metaKey); s.withStartRow(metaStartKey);
s.withStopRow(metaStopKey, true);
s.addFamily(HConstants.CATALOG_FAMILY); s.addFamily(HConstants.CATALOG_FAMILY);
if (this.useMetaReplicas) { if (this.useMetaReplicas) {
@ -840,12 +843,11 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
// convert the row result into the HRegionLocation we need! // convert the row result into the HRegionLocation we need!
RegionLocations locations = MetaTableAccessor.getRegionLocations(regionInfoRow); RegionLocations locations = MetaTableAccessor.getRegionLocations(regionInfoRow);
if (locations == null || locations.getRegionLocation(replicaId) == null) { if (locations == null || locations.getRegionLocation(replicaId) == null) {
throw new IOException("HRegionInfo was null in " + throw new IOException("RegionInfo null in " + tableName + ", row=" + regionInfoRow);
tableName + ", row=" + regionInfoRow);
} }
RegionInfo regionInfo = locations.getRegionLocation(replicaId).getRegion(); RegionInfo regionInfo = locations.getRegionLocation(replicaId).getRegion();
if (regionInfo == null) { if (regionInfo == null) {
throw new IOException("HRegionInfo was null or empty in " + throw new IOException("RegionInfo null or empty in " +
TableName.META_TABLE_NAME + ", row=" + regionInfoRow); TableName.META_TABLE_NAME + ", row=" + regionInfoRow);
} }
@ -857,13 +859,12 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
"hbase:meta might be damaged."); "hbase:meta might be damaged.");
} }
if (regionInfo.isSplit()) { if (regionInfo.isSplit()) {
throw new RegionOfflineException( throw new RegionOfflineException ("Region for row is a split parent, daughters not online: " +
"the only available region for the required row is a split parent," regionInfo.getRegionNameAsString());
+ " the daughters should be online soon: " + regionInfo.getRegionNameAsString());
} }
if (regionInfo.isOffline()) { if (regionInfo.isOffline()) {
throw new RegionOfflineException("the region is offline, could" throw new RegionOfflineException("Region offline; disable table call? " +
+ " be caused by a disable table call: " + regionInfo.getRegionNameAsString()); regionInfo.getRegionNameAsString());
} }
ServerName serverName = locations.getRegionLocation(replicaId).getServerName(); ServerName serverName = locations.getRegionLocation(replicaId).getServerName();
@ -908,7 +909,7 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
// Only relocate the parent region if necessary // Only relocate the parent region if necessary
if(!(e instanceof RegionOfflineException || if(!(e instanceof RegionOfflineException ||
e instanceof NoServerForRegionException)) { e instanceof NoServerForRegionException)) {
relocateRegion(TableName.META_TABLE_NAME, metaKey, replicaId); relocateRegion(TableName.META_TABLE_NAME, metaStartKey, replicaId);
} }
} finally { } finally {
userRegionLock.unlock(); userRegionLock.unlock();

View File

@ -16,19 +16,6 @@
*/ */
package org.apache.hadoop.hbase.client; package org.apache.hadoop.hbase.client;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CompareOperator; import org.apache.hadoop.hbase.CompareOperator;
@ -41,6 +28,7 @@ import org.apache.hadoop.hbase.HTestConst;
import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.MiniHBaseCluster; import org.apache.hadoop.hbase.MiniHBaseCluster;
import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.TableNotFoundException;
import org.apache.hadoop.hbase.filter.BinaryComparator; import org.apache.hadoop.hbase.filter.BinaryComparator;
import org.apache.hadoop.hbase.filter.ColumnPrefixFilter; import org.apache.hadoop.hbase.filter.ColumnPrefixFilter;
import org.apache.hadoop.hbase.filter.ColumnRangeFilter; import org.apache.hadoop.hbase.filter.ColumnRangeFilter;
@ -61,6 +49,21 @@ import org.junit.rules.TestName;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/** /**
* A client-side test, mostly testing scanners with various parameters. * A client-side test, mostly testing scanners with various parameters.
*/ */
@ -236,6 +239,27 @@ public class TestScannersFromClientSide {
clientScanner.getCacheSize() <= 1); clientScanner.getCacheSize() <= 1);
} }
/**
* Scan on not existing table should throw the exception with correct message
*/
@Test
public void testScannerForNotExistingTable() {
String[] tableNames = {"A", "Z", "A:A", "Z:Z"};
for(String tableName : tableNames) {
try {
Table table = TEST_UTIL.getConnection().getTable(TableName.valueOf(tableName));
testSmallScan(table, true, 1, 5);
fail("TableNotFoundException was not thrown");
} catch (TableNotFoundException e) {
// We expect that the message for TableNotFoundException would have only the table name only
// Otherwise that would mean that localeRegionInMeta doesn't work properly
assertEquals(e.getMessage(), tableName);
} catch (Exception e) {
fail("Unexpected exception " + e.getMessage());
}
}
}
@Test @Test
public void testSmallScan() throws Exception { public void testSmallScan() throws Exception {
final TableName tableName = TableName.valueOf(name.getMethodName()); final TableName tableName = TableName.valueOf(name.getMethodName());