You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by dd...@apache.org on 2014/02/19 19:05:55 UTC
svn commit: r1569861 - in /hbase/branches/hbase-10070:
hbase-client/src/main/java/org/apache/hadoop/hbase/catalog/
hbase-client/src/main/java/org/apache/hadoop/hbase/client/
hbase-server/src/main/java/org/apache/hadoop/hbase/catalog/
hbase-server/src/m...
Author: ddas
Date: Wed Feb 19 18:05:54 2014
New Revision: 1569861
URL: http://svn.apache.org/r1569861
Log:
HBASE-10350. Master/AM/RegionStates changes to create and assign region replicas (ddas)
Added:
hbase/branches/hbase-10070/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterOperationsForRegionReplicas.java
Modified:
hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java
hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java
hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/catalog/MetaEditor.java
hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RackManager.java
hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java
hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/SnapshotOfRegionAssignmentFromMeta.java
hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/util/ModifyRegionUtils.java
Modified: hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java (original)
+++ hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/catalog/MetaReader.java Wed Feb 19 18:05:54 2014
@@ -629,7 +629,8 @@ public class MetaReader {
* @param replicaId the replicaId of the region
* @return a byte[] for server column qualifier
*/
- protected static byte[] getServerColumn(int replicaId) {
+ @VisibleForTesting
+ public static byte[] getServerColumn(int replicaId) {
return replicaId == 0
? HConstants.SERVER_QUALIFIER
: Bytes.toBytes(HConstants.SERVER_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
@@ -641,7 +642,8 @@ public class MetaReader {
* @param replicaId the replicaId of the region
* @return a byte[] for server start code column qualifier
*/
- protected static byte[] getStartCodeColumn(int replicaId) {
+ @VisibleForTesting
+ public static byte[] getStartCodeColumn(int replicaId) {
return replicaId == 0
? HConstants.STARTCODE_QUALIFIER
: Bytes.toBytes(HConstants.STARTCODE_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
@@ -653,7 +655,8 @@ public class MetaReader {
* @param replicaId the replicaId of the region
* @return a byte[] for seqNum column qualifier
*/
- protected static byte[] getSeqNumColumn(int replicaId) {
+ @VisibleForTesting
+ public static byte[] getSeqNumColumn(int replicaId) {
return replicaId == 0
? HConstants.SEQNUM_QUALIFIER
: Bytes.toBytes(HConstants.SEQNUM_QUALIFIER_STR + META_REPLICA_ID_DELIMITER
Modified: hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (original)
+++ hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java Wed Feb 19 18:05:54 2014
@@ -39,6 +39,7 @@ import org.apache.hadoop.classification.
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Abortable;
import org.apache.hadoop.hbase.ClusterStatus;
+import org.apache.hadoop.hbase.RegionLocations;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseIOException;
@@ -500,7 +501,7 @@ public class HBaseAdmin implements Abort
} catch (SocketTimeoutException ste) {
LOG.warn("Creating " + desc.getTableName() + " took too long", ste);
}
- int numRegs = splitKeys == null ? 1 : splitKeys.length + 1;
+ int numRegs = (splitKeys == null ? 1 : splitKeys.length + 1) * desc.getRegionReplication();
int prevRegCount = 0;
boolean doneWithMetaScan = false;
for (int tries = 0; tries < this.numRetries * this.retryLongerMultiplier;
@@ -511,19 +512,27 @@ public class HBaseAdmin implements Abort
MetaScannerVisitor visitor = new MetaScannerVisitorBase() {
@Override
public boolean processRow(Result rowResult) throws IOException {
- HRegionInfo info = HRegionInfo.getHRegionInfo(rowResult);
- if (info == null) {
+ RegionLocations list = MetaReader.getRegionLocations(rowResult);
+ if (list == null) {
LOG.warn("No serialized HRegionInfo in " + rowResult);
return true;
}
- if (!info.getTable().equals(desc.getTableName())) {
+ HRegionLocation l = list.getRegionLocation();
+ if (l == null) {
+ return true;
+ }
+ if (!l.getRegionInfo().getTable().equals(desc.getTableName())) {
return false;
}
- ServerName serverName = HRegionInfo.getServerName(rowResult);
- // Make sure that regions are assigned to server
- if (!(info.isOffline() || info.isSplit()) && serverName != null
- && serverName.getHostAndPort() != null) {
- actualRegCount.incrementAndGet();
+ if (l.getRegionInfo().isOffline() || l.getRegionInfo().isSplit()) return true;
+ HRegionLocation[] locations = list.getRegionLocations();
+ for (HRegionLocation location : locations) {
+ if (location == null) continue;
+ ServerName serverName = location.getServerName();
+ // Make sure that regions are assigned to server
+ if (serverName != null && serverName.getHostAndPort() != null) {
+ actualRegCount.incrementAndGet();
+ }
}
return true;
}
Modified: hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java (original)
+++ hbase/branches/hbase-10070/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RegionReplicaUtil.java Wed Feb 19 18:05:54 2014
@@ -62,7 +62,13 @@ public class RegionReplicaUtil {
return getRegionInfoForReplica(regionInfo, DEFAULT_REPLICA_ID);
}
+ /** @return true if this replicaId corresponds to default replica for the region */
public static boolean isDefaultReplica(int replicaId) {
return DEFAULT_REPLICA_ID == replicaId;
}
+
+ /** @return true if this region is a default replica for the region */
+ public static boolean isDefaultReplica(HRegionInfo hri) {
+ return hri.getReplicaId() == DEFAULT_REPLICA_ID;
+ }
}
Modified: hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/catalog/MetaEditor.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/catalog/MetaEditor.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/catalog/MetaEditor.java (original)
+++ hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/catalog/MetaEditor.java Wed Feb 19 18:05:54 2014
@@ -34,6 +34,7 @@ import org.apache.hadoop.hbase.client.De
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Mutation;
import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.RegionReplicaUtil;
import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType;
@@ -270,7 +271,9 @@ public class MetaEditor extends MetaRead
throws IOException {
List<Put> puts = new ArrayList<Put>();
for (HRegionInfo regionInfo : regionInfos) {
- puts.add(makePutFromRegionInfo(regionInfo));
+ if (RegionReplicaUtil.isDefaultReplica(regionInfo)) {
+ puts.add(makePutFromRegionInfo(regionInfo));
+ }
}
putsToMetaTable(catalogTracker, puts);
LOG.info("Added " + puts.size());
Modified: hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (original)
+++ hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java Wed Feb 19 18:05:54 2014
@@ -48,6 +48,8 @@ import org.apache.hadoop.hbase.Chore;
import org.apache.hadoop.hbase.HBaseIOException;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.HRegionLocation;
+import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.NotServingRegionException;
import org.apache.hadoop.hbase.RegionTransition;
import org.apache.hadoop.hbase.Server;
@@ -57,6 +59,7 @@ import org.apache.hadoop.hbase.TableName
import org.apache.hadoop.hbase.TableNotFoundException;
import org.apache.hadoop.hbase.catalog.CatalogTracker;
import org.apache.hadoop.hbase.catalog.MetaReader;
+import org.apache.hadoop.hbase.client.RegionReplicaUtil;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.executor.EventHandler;
@@ -2553,19 +2556,50 @@ public class AssignmentManager extends Z
boolean retainAssignment = server.getConfiguration().
getBoolean("hbase.master.startup.retainassign", true);
+ Set<HRegionInfo> regionsFromMetaScan = allRegions.keySet();
if (retainAssignment) {
assign(allRegions);
} else {
- List<HRegionInfo> regions = new ArrayList<HRegionInfo>(allRegions.keySet());
+ List<HRegionInfo> regions = new ArrayList<HRegionInfo>(regionsFromMetaScan);
assign(regions);
}
- for (HRegionInfo hri : allRegions.keySet()) {
+ for (HRegionInfo hri : regionsFromMetaScan) {
TableName tableName = hri.getTable();
if (!zkTable.isEnabledTable(tableName)) {
setEnabledTable(tableName);
}
}
+ // assign all the replicas that were not recorded in the meta
+ assign(replicaRegionsNotRecordedInMeta(regionsFromMetaScan, (MasterServices)server));
+ }
+
+ /**
+ * Get a list of replica regions that are:
+ * not recorded in meta yet. We might not have recorded the locations
+ * for the replicas since the replicas may not have been online yet, master restarted
+ * in the middle of assigning, ZK erased, etc.
+ * @param regionsRecordedInMeta the list of regions we know are recorded in meta
+ * either as a default, or, as the location of a replica
+ * @param master
+ * @return list of replica regions
+ * @throws IOException
+ */
+ public static List<HRegionInfo> replicaRegionsNotRecordedInMeta(
+ Set<HRegionInfo> regionsRecordedInMeta, MasterServices master)throws IOException {
+ List<HRegionInfo> regionsNotRecordedInMeta = new ArrayList<HRegionInfo>();
+ for (HRegionInfo hri : regionsRecordedInMeta) {
+ TableName table = hri.getTable();
+ HTableDescriptor htd = master.getTableDescriptors().get(table);
+ // look at the HTD for the replica count. That's the source of truth
+ int desiredRegionReplication = htd.getRegionReplication();
+ for (int i = 0; i < desiredRegionReplication; i++) {
+ HRegionInfo replica = RegionReplicaUtil.getRegionInfoForReplica(hri, i);
+ if (regionsRecordedInMeta.contains(replica)) continue;
+ regionsNotRecordedInMeta.add(replica);
+ }
+ }
+ return regionsNotRecordedInMeta;
}
/**
@@ -2617,62 +2651,66 @@ public class AssignmentManager extends Z
new TreeMap<ServerName, List<HRegionInfo>>();
// Iterate regions in META
for (Result result : results) {
- Pair<HRegionInfo, ServerName> region = HRegionInfo.getHRegionInfoAndServerName(result);
- if (region == null) continue;
- HRegionInfo regionInfo = region.getFirst();
- ServerName regionLocation = region.getSecond();
- if (regionInfo == null) continue;
- regionStates.createRegionState(regionInfo);
- if (regionStates.isRegionInState(regionInfo, State.SPLIT)) {
- // Split is considered to be completed. If the split znode still
- // exists, the region will be put back to SPLITTING state later
- LOG.debug("Region " + regionInfo.getRegionNameAsString()
- + " split is completed. Hence need not add to regions list");
- continue;
- }
- TableName tableName = regionInfo.getTable();
- if (regionLocation == null) {
- // regionLocation could be null if createTable didn't finish properly.
- // When createTable is in progress, HMaster restarts.
- // Some regions have been added to hbase:meta, but have not been assigned.
- // When this happens, the region's table must be in ENABLING state.
- // It can't be in ENABLED state as that is set when all regions are
- // assigned.
- // It can't be in DISABLING state, because DISABLING state transitions
- // from ENABLED state when application calls disableTable.
- // It can't be in DISABLED state, because DISABLED states transitions
- // from DISABLING state.
- if (!enablingTables.contains(tableName)) {
- LOG.warn("Region " + regionInfo.getEncodedName() +
- " has null regionLocation." + " But its table " + tableName +
- " isn't in ENABLING state.");
- }
- } else if (!onlineServers.contains(regionLocation)) {
- // Region is located on a server that isn't online
- List<HRegionInfo> offlineRegions = offlineServers.get(regionLocation);
- if (offlineRegions == null) {
- offlineRegions = new ArrayList<HRegionInfo>(1);
- offlineServers.put(regionLocation, offlineRegions);
- }
- offlineRegions.add(regionInfo);
- // need to enable the table if not disabled or disabling or enabling
- // this will be used in rolling restarts
- if (!disabledOrDisablingOrEnabling.contains(tableName)
- && !getZKTable().isEnabledTable(tableName)) {
- setEnabledTable(tableName);
+ HRegionInfo regionInfo;
+ HRegionLocation[] locations = MetaReader.getRegionLocations(result).getRegionLocations();
+ if (locations == null) continue;
+ // Do the operations for all the replicas
+ for (HRegionLocation hrl : locations) {
+ if (hrl == null) continue;
+ ServerName regionLocation = hrl.getServerName();
+ regionInfo = hrl.getRegionInfo();
+ regionStates.createRegionState(regionInfo);
+ if (regionStates.isRegionInState(regionInfo, State.SPLIT)) {
+ // Split is considered to be completed. If the split znode still
+ // exists, the region will be put back to SPLITTING state later
+ LOG.debug("Region " + regionInfo.getRegionNameAsString()
+ + " split is completed. Hence need not add to regions list");
+ continue;
}
- } else {
- // Region is being served and on an active server
- // add only if region not in disabled or enabling table
- if (!disabledOrEnablingTables.contains(tableName)) {
- regionStates.updateRegionState(regionInfo, State.OPEN, regionLocation);
- regionStates.regionOnline(regionInfo, regionLocation);
- }
- // need to enable the table if not disabled or disabling or enabling
- // this will be used in rolling restarts
- if (!disabledOrDisablingOrEnabling.contains(tableName)
- && !getZKTable().isEnabledTable(tableName)) {
- setEnabledTable(tableName);
+ TableName tableName = regionInfo.getTable();
+ if (regionLocation == null) {
+ // regionLocation could be null if createTable didn't finish properly.
+ // When createTable is in progress, HMaster restarts.
+ // Some regions have been added to hbase:meta, but have not been assigned.
+ // When this happens, the region's table must be in ENABLING state.
+ // It can't be in ENABLED state as that is set when all regions are
+ // assigned.
+ // It can't be in DISABLING state, because DISABLING state transitions
+ // from ENABLED state when application calls disableTable.
+ // It can't be in DISABLED state, because DISABLED states transitions
+ // from DISABLING state.
+ if (!enablingTables.contains(tableName)) {
+ LOG.warn("Region " + regionInfo.getEncodedName() +
+ " has null regionLocation." + " But its table " + tableName +
+ " isn't in ENABLING state.");
+ }
+ } else if (!onlineServers.contains(regionLocation)) {
+ // Region is located on a server that isn't online
+ List<HRegionInfo> offlineRegions = offlineServers.get(regionLocation);
+ if (offlineRegions == null) {
+ offlineRegions = new ArrayList<HRegionInfo>(1);
+ offlineServers.put(regionLocation, offlineRegions);
+ }
+ offlineRegions.add(regionInfo);
+ // need to enable the table if not disabled or disabling or enabling
+ // this will be used in rolling restarts
+ if (!disabledOrDisablingOrEnabling.contains(tableName)
+ && !getZKTable().isEnabledTable(tableName)) {
+ setEnabledTable(tableName);
+ }
+ } else {
+ // Region is being served and on an active server
+ // add only if region not in disabled or enabling table
+ if (!disabledOrEnablingTables.contains(tableName)) {
+ regionStates.updateRegionState(regionInfo, State.OPEN, regionLocation);
+ regionStates.regionOnline(regionInfo, regionLocation);
+ }
+ // need to enable the table if not disabled or disabling or enabling
+ // this will be used in rolling restarts
+ if (!disabledOrDisablingOrEnabling.contains(tableName)
+ && !getZKTable().isEnabledTable(tableName)) {
+ setEnabledTable(tableName);
+ }
}
}
}
@@ -3522,4 +3560,8 @@ public class AssignmentManager extends Z
public LoadBalancer getBalancer() {
return this.balancer;
}
+
+ public Map<ServerName, List<HRegionInfo>> getSnapShotOfAssignment(List<HRegionInfo> infos) {
+ return getRegionStates().getRegionAssignments(infos);
+ }
}
Modified: hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (original)
+++ hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java Wed Feb 19 18:05:54 2014
@@ -1787,18 +1787,30 @@ MasterServices, Server {
private HRegionInfo[] getHRegionInfos(HTableDescriptor hTableDescriptor,
byte[][] splitKeys) {
HRegionInfo[] hRegionInfos = null;
+ int numRegionReplicas = hTableDescriptor.getRegionReplication();
+ if (numRegionReplicas <= 0) {
+ LOG.warn("Invalid number of replicas per region in the table descriptor. Setting it to 1.");
+ numRegionReplicas = 1;
+ }
+ long regionId = System.currentTimeMillis();
if (splitKeys == null || splitKeys.length == 0) {
- hRegionInfos = new HRegionInfo[]{
- new HRegionInfo(hTableDescriptor.getTableName(), null, null)};
+ hRegionInfos = new HRegionInfo[numRegionReplicas];
+ for (int i = 0; i < numRegionReplicas; i++) {
+ hRegionInfos[i] = new HRegionInfo(hTableDescriptor.getTableName(), null, null,
+ false, regionId, (short)i);
+ }
} else {
int numRegions = splitKeys.length + 1;
- hRegionInfos = new HRegionInfo[numRegions];
+ hRegionInfos = new HRegionInfo[numRegions * numRegionReplicas];
byte[] startKey = null;
byte[] endKey = null;
for (int i = 0; i < numRegions; i++) {
endKey = (i == splitKeys.length) ? null : splitKeys[i];
- hRegionInfos[i] =
- new HRegionInfo(hTableDescriptor.getTableName(), startKey, endKey);
+ for (int j = 0; j < numRegionReplicas; j++) {
+ hRegionInfos[i*numRegionReplicas + j] =
+ new HRegionInfo(hTableDescriptor.getTableName(), startKey, endKey,
+ false, regionId, (short)j);
+ }
startKey = endKey;
}
}
Modified: hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RackManager.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RackManager.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RackManager.java (original)
+++ hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RackManager.java Wed Feb 19 18:05:54 2014
@@ -17,6 +17,7 @@
*/
package org.apache.hadoop.hbase.master;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -66,4 +67,20 @@ public class RackManager {
return UNKNOWN_RACK;
}
+
+ /**
+ * Same as {@link #getRack(ServerName)} except that a list is passed
+ * @param servers
+ * @return
+ */
+ public List<String> getRack(List<ServerName> servers) {
+ // just a note - switchMapping caches results (at least the implementation should unless the
+ // resolution is really a lightweight process)
+ List<String> serversAsString = new ArrayList<String>(servers.size());
+ for (ServerName server : servers) {
+ serversAsString.add(server.getHostname());
+ }
+ List<String> racks = switchMapping.resolve(serversAsString);
+ return racks;
+ }
}
Modified: hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java (original)
+++ hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/RegionStates.java Wed Feb 19 18:05:54 2014
@@ -38,6 +38,7 @@ import org.apache.hadoop.hbase.ServerLoa
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.catalog.MetaReader;
+import org.apache.hadoop.hbase.client.RegionReplicaUtil;
import org.apache.hadoop.hbase.master.RegionState.State;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
@@ -75,6 +76,11 @@ public class RegionStates {
private final Map<ServerName, Set<HRegionInfo>> serverHoldings;
/**
+ * Maintains the mapping from the default region to the replica regions.
+ */
+ private final Map<HRegionInfo, Set<HRegionInfo>> defaultReplicaToOtherReplicas;
+
+ /**
* Region to server assignment map.
* Contains the server a given region is currently assigned to.
*/
@@ -120,6 +126,7 @@ public class RegionStates {
regionStates = new HashMap<String, RegionState>();
regionsInTransition = new HashMap<String, RegionState>();
serverHoldings = new HashMap<ServerName, Set<HRegionInfo>>();
+ defaultReplicaToOtherReplicas = new HashMap<HRegionInfo, Set<HRegionInfo>>();
regionAssignments = new TreeMap<HRegionInfo, ServerName>();
lastAssignments = new HashMap<String, ServerName>();
processedServers = new HashMap<ServerName, Long>();
@@ -136,6 +143,43 @@ public class RegionStates {
return (Map<HRegionInfo, ServerName>)regionAssignments.clone();
}
+ /**
+ * Return the replicas (including default) for the regions grouped by ServerName
+ * @param regions
+ * @return a pair containing the groupings as a map
+ */
+ synchronized Map<ServerName, List<HRegionInfo>> getRegionAssignments(List<HRegionInfo> regions) {
+ Map<ServerName, List<HRegionInfo>> map = new HashMap<ServerName, List<HRegionInfo>>();
+ for (HRegionInfo region : regions) {
+ HRegionInfo defaultReplica = RegionReplicaUtil.getRegionInfoForDefaultReplica(region);
+ ServerName server = regionAssignments.get(defaultReplica);
+ List<HRegionInfo> regionsOnServer;
+ if (server != null) {
+ regionsOnServer = map.get(server);
+ if (regionsOnServer == null) {
+ regionsOnServer = new ArrayList<HRegionInfo>(1);
+ map.put(server, regionsOnServer);
+ }
+ regionsOnServer.add(defaultReplica);
+ }
+ Set<HRegionInfo> allReplicas = defaultReplicaToOtherReplicas.get(defaultReplica);
+ if (allReplicas != null) {
+ for (HRegionInfo hri : allReplicas) {
+ server = regionAssignments.get(hri);
+ if (server != null) {
+ regionsOnServer = map.get(server);
+ if (regionsOnServer == null) {
+ regionsOnServer = new ArrayList<HRegionInfo>(1);
+ map.put(server, regionsOnServer);
+ }
+ regionsOnServer.add(hri);
+ }
+ }
+ }
+ }
+ return map;
+ }
+
public synchronized ServerName getRegionServerOfRegion(HRegionInfo hri) {
return regionAssignments.get(hri);
}
@@ -375,23 +419,46 @@ public class RegionStates {
ServerName oldServerName = regionAssignments.put(hri, serverName);
if (!serverName.equals(oldServerName)) {
LOG.info("Onlined " + hri.getShortNameToLog() + " on " + serverName);
- Set<HRegionInfo> regions = serverHoldings.get(serverName);
- if (regions == null) {
- regions = new HashSet<HRegionInfo>();
- serverHoldings.put(serverName, regions);
- }
- regions.add(hri);
+ addToServerHoldings(serverName, hri);
if (oldServerName != null) {
LOG.info("Offlined " + hri.getShortNameToLog() + " from " + oldServerName);
- Set<HRegionInfo> oldRegions = serverHoldings.get(oldServerName);
- oldRegions.remove(hri);
- if (oldRegions.isEmpty()) {
- serverHoldings.remove(oldServerName);
- }
+ removeFromServerHoldings(oldServerName, hri);
}
}
}
+ private void addToServerHoldings(ServerName serverName, HRegionInfo hri) {
+ Set<HRegionInfo> regions = serverHoldings.get(serverName);
+ if (regions == null) {
+ regions = new HashSet<HRegionInfo>();
+ serverHoldings.put(serverName, regions);
+ }
+ regions.add(hri);
+
+ HRegionInfo defaultReplica = RegionReplicaUtil.getRegionInfoForDefaultReplica(hri);
+ Set<HRegionInfo> replicas =
+ defaultReplicaToOtherReplicas.get(defaultReplica);
+ if (replicas == null) {
+ replicas = new HashSet<HRegionInfo>();
+ defaultReplicaToOtherReplicas.put(defaultReplica, replicas);
+ }
+ replicas.add(hri);
+ }
+
+ private void removeFromServerHoldings(ServerName serverName, HRegionInfo hri) {
+ Set<HRegionInfo> oldRegions = serverHoldings.get(serverName);
+ oldRegions.remove(hri);
+ if (oldRegions.isEmpty()) {
+ serverHoldings.remove(serverName);
+ }
+ HRegionInfo defaultReplica = RegionReplicaUtil.getRegionInfoForDefaultReplica(hri);
+ Set<HRegionInfo> replicas = defaultReplicaToOtherReplicas.get(defaultReplica);
+ replicas.remove(hri);
+ if (replicas.isEmpty()) {
+ defaultReplicaToOtherReplicas.remove(defaultReplica);
+ }
+ }
+
/**
* A dead server's hlogs have been split so that all the regions
* used to be open on it can be safely assigned now. Mark them assignable.
@@ -459,11 +526,7 @@ public class RegionStates {
ServerName oldServerName = regionAssignments.remove(hri);
if (oldServerName != null) {
LOG.info("Offlined " + hri.getShortNameToLog() + " from " + oldServerName);
- Set<HRegionInfo> oldRegions = serverHoldings.get(oldServerName);
- oldRegions.remove(hri);
- if (oldRegions.isEmpty()) {
- serverHoldings.remove(oldServerName);
- }
+ removeFromServerHoldings(oldServerName, hri);
}
}
Modified: hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/SnapshotOfRegionAssignmentFromMeta.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/SnapshotOfRegionAssignmentFromMeta.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/SnapshotOfRegionAssignmentFromMeta.java (original)
+++ hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/master/SnapshotOfRegionAssignmentFromMeta.java Wed Feb 19 18:05:54 2014
@@ -33,6 +33,8 @@ import org.apache.commons.logging.LogFac
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.HRegionLocation;
+import org.apache.hadoop.hbase.RegionLocations;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.catalog.CatalogTracker;
@@ -41,7 +43,6 @@ import org.apache.hadoop.hbase.catalog.M
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.master.balancer.FavoredNodeAssignmentHelper;
import org.apache.hadoop.hbase.master.balancer.FavoredNodesPlan;
-import org.apache.hadoop.hbase.util.Pair;
/**
* Used internally for reading meta and constructing datastructures that are
@@ -100,20 +101,27 @@ public class SnapshotOfRegionAssignmentF
public boolean visit(Result result) throws IOException {
try {
if (result == null || result.isEmpty()) return true;
- Pair<HRegionInfo, ServerName> regionAndServer =
- HRegionInfo.getHRegionInfoAndServerName(result);
- HRegionInfo hri = regionAndServer.getFirst();
- if (hri == null) return true;
+ RegionLocations rl = MetaReader.getRegionLocations(result);
+ if (rl == null) return true;
+ HRegionInfo hri = rl.getRegionLocation(0).getRegionInfo();
+ if (hri == null) return true;
if (hri.getTable() == null) return true;
if (disabledTables.contains(hri.getTable())) {
return true;
}
// Are we to include split parents in the list?
if (excludeOfflinedSplitParents && hri.isSplit()) return true;
- // Add the current assignment to the snapshot
- addAssignment(hri, regionAndServer.getSecond());
- addRegion(hri);
-
+ HRegionLocation[] hrls = rl.getRegionLocations();
+
+ // Add the current assignment to the snapshot for all replicas
+ for (int i = 0; i < hrls.length; i++) {
+ if (hrls[i] == null) continue;
+ hri = hrls[i].getRegionInfo();
+ if (hri == null) continue;
+ addAssignment(hri, hrls[i].getServerName());
+ addRegion(hri);
+ }
+
// the code below is to handle favored nodes
byte[] favoredNodes = result.getValue(HConstants.CATALOG_FAMILY,
FavoredNodeAssignmentHelper.FAVOREDNODES_QUALIFIER);
@@ -158,6 +166,8 @@ public class SnapshotOfRegionAssignmentF
// Process the region to region server map
regionToRegionServerMap.put(regionInfo, server);
+ if (server == null) return;
+
// Process the region server to region map
List<HRegionInfo> regionList = regionServerToRegionMap.get(server);
if (regionList == null) {
Modified: hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/util/ModifyRegionUtils.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/util/ModifyRegionUtils.java?rev=1569861&r1=1569860&r2=1569861&view=diff
==============================================================================
--- hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/util/ModifyRegionUtils.java (original)
+++ hbase/branches/hbase-10070/hbase-server/src/main/java/org/apache/hadoop/hbase/util/ModifyRegionUtils.java Wed Feb 19 18:05:54 2014
@@ -27,7 +27,6 @@ import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -39,6 +38,7 @@ import org.apache.hadoop.conf.Configurat
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.client.RegionReplicaUtil;
import org.apache.hadoop.hbase.regionserver.HRegion;
/**
@@ -111,7 +111,13 @@ public abstract class ModifyRegionUtils
CompletionService<HRegionInfo> completionService = new ExecutorCompletionService<HRegionInfo>(
regionOpenAndInitThreadPool);
List<HRegionInfo> regionInfos = new ArrayList<HRegionInfo>();
+ int defaultReplicas = 0;
for (final HRegionInfo newRegion : newRegions) {
+ regionInfos.add(newRegion);
+ if (!RegionReplicaUtil.isDefaultReplica(newRegion)) {
+ continue;
+ }
+ defaultReplicas++;
completionService.submit(new Callable<HRegionInfo>() {
@Override
public HRegionInfo call() throws IOException {
@@ -121,10 +127,8 @@ public abstract class ModifyRegionUtils
}
try {
// wait for all regions to finish creation
- for (int i = 0; i < regionNumber; i++) {
- Future<HRegionInfo> future = completionService.take();
- HRegionInfo regionInfo = future.get();
- regionInfos.add(regionInfo);
+ for (int i = 0; i < defaultReplicas; i++) {
+ completionService.take().get();
}
} catch (InterruptedException e) {
LOG.error("Caught " + e + " during region creation");
Added: hbase/branches/hbase-10070/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterOperationsForRegionReplicas.java
URL: http://svn.apache.org/viewvc/hbase/branches/hbase-10070/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterOperationsForRegionReplicas.java?rev=1569861&view=auto
==============================================================================
--- hbase/branches/hbase-10070/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterOperationsForRegionReplicas.java (added)
+++ hbase/branches/hbase-10070/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestMasterOperationsForRegionReplicas.java Wed Feb 19 18:05:54 2014
@@ -0,0 +1,328 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.master;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HRegionInfo;
+import org.apache.hadoop.hbase.HRegionLocation;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.MediumTests;
+import org.apache.hadoop.hbase.RegionLocations;
+import org.apache.hadoop.hbase.ServerName;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.catalog.CatalogTracker;
+import org.apache.hadoop.hbase.catalog.MetaReader;
+import org.apache.hadoop.hbase.catalog.MetaReader.Visitor;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.RegionReplicaUtil;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.Pair;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category(MediumTests.class)
+public class TestMasterOperationsForRegionReplicas {
+ final static Log LOG = LogFactory.getLog(TestRegionPlacement.class);
+ private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
+ private static HBaseAdmin admin;
+ private static int numSlaves = 2;
+
+ @BeforeClass
+ public static void setupBeforeClass() throws Exception {
+ Configuration conf = TEST_UTIL.getConfiguration();
+ conf.setBoolean("hbase.tests.use.shortcircuit.reads", false);
+ TEST_UTIL.startMiniCluster(numSlaves);
+ admin = new HBaseAdmin(conf);
+ while(admin.getClusterStatus().getServers().size() != numSlaves) {
+ Thread.sleep(100);
+ }
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ TEST_UTIL.shutdownMiniCluster();
+ }
+
+ @Test
+ public void testCreateTableWithSingleReplica() throws Exception {
+ final int numRegions = 3;
+ final int numReplica = 1;
+ final TableName table = TableName.valueOf("singleReplicaTable");
+ try {
+ HTableDescriptor desc = new HTableDescriptor(table);
+ desc.setRegionReplication(numReplica);
+ desc.addFamily(new HColumnDescriptor("family"));
+ admin.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), numRegions);
+
+ CatalogTracker ct = new CatalogTracker(TEST_UTIL.getConfiguration());
+ validateNumberOfRowsInMeta(table, numRegions, ct);
+ List<HRegionInfo> hris = MetaReader.getTableRegions(ct, table);
+ assert(hris.size() == numRegions * numReplica);
+ } finally {
+ admin.disableTable(table);
+ admin.deleteTable(table);
+ }
+ }
+
+ @Test
+ public void testCreateTableWithMultipleReplicas() throws Exception {
+ final TableName table = TableName.valueOf("fooTable");
+ final int numRegions = 3;
+ final int numReplica = 2;
+ try {
+ HTableDescriptor desc = new HTableDescriptor(table);
+ desc.setRegionReplication(numReplica);
+ desc.addFamily(new HColumnDescriptor("family"));
+ admin.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), numRegions);
+ TEST_UTIL.waitTableEnabled(table.getName());
+ CatalogTracker ct = new CatalogTracker(TEST_UTIL.getConfiguration());
+ validateNumberOfRowsInMeta(table, numRegions, ct);
+
+ List<HRegionInfo> hris = MetaReader.getTableRegions(ct, table);
+ assert(hris.size() == numRegions * numReplica);
+ // check that the master created expected number of RegionState objects
+ for (int i = 0; i < numRegions; i++) {
+ for (int j = 0; j < numReplica; j++) {
+ HRegionInfo replica = RegionReplicaUtil.getRegionInfoForReplica(hris.get(i), j);
+ RegionState state = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
+ .getRegionStates().getRegionState(replica);
+ assert (state != null);
+ }
+ }
+ // TODO: HBASE-10351 should uncomment the following tests (since the tests assume region placements are handled)
+// List<Result> metaRows = MetaReader.fullScan(ct);
+// int numRows = 0;
+// for (Result result : metaRows) {
+// RegionLocations locations = MetaReader.getRegionLocations(result);
+// HRegionInfo hri = locations.getRegionLocation().getRegionInfo();
+// if (!hri.getTable().equals(table)) continue;
+// numRows += 1;
+// HRegionLocation[] servers = locations.getRegionLocations();
+// // have two locations for the replicas of a region, and the locations should be different
+// assert(servers.length == 2);
+// assert(!servers[0].equals(servers[1]));
+// }
+// assert(numRows == numRegions);
+//
+// // The same verification of the meta as above but with the SnapshotOfRegionAssignmentFromMeta
+// // class
+// validateFromSnapshotFromMeta(table, numRegions, numReplica, ct);
+//
+// // Now kill the master, restart it and see if the assignments are kept
+// ServerName master = TEST_UTIL.getHBaseClusterInterface().getClusterStatus().getMaster();
+// TEST_UTIL.getHBaseClusterInterface().stopMaster(master);
+// TEST_UTIL.getHBaseClusterInterface().waitForMasterToStop(master, 30000);
+// TEST_UTIL.getHBaseClusterInterface().startMaster(master.getHostname());
+// TEST_UTIL.getHBaseClusterInterface().waitForActiveAndReadyMaster();
+// for (int i = 0; i < numRegions; i++) {
+// for (int j = 0; j < numReplica; j++) {
+// HRegionInfo replica = RegionReplicaUtil.getRegionInfoForReplica(hris.get(i), j);
+// RegionState state = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager()
+// .getRegionStates().getRegionState(replica);
+// assert (state != null);
+// }
+// }
+// validateFromSnapshotFromMeta(table, numRegions, numReplica, ct);
+//
+// // Now shut the whole cluster down, and verify the assignments are kept so that the
+// // availability constraints are met.
+// TEST_UTIL.getConfiguration().setBoolean("hbase.master.startup.retainassign", true);
+// TEST_UTIL.shutdownMiniHBaseCluster();
+// TEST_UTIL.startMiniHBaseCluster(1, numSlaves);
+// TEST_UTIL.waitTableEnabled(table.getName());
+// ct = new CatalogTracker(TEST_UTIL.getConfiguration());
+// validateFromSnapshotFromMeta(table, numRegions, numReplica, ct);
+//
+// // Now shut the whole cluster down, and verify regions are assigned even if there is only
+// // one server running
+// TEST_UTIL.shutdownMiniHBaseCluster();
+// TEST_UTIL.startMiniHBaseCluster(1, 1);
+// TEST_UTIL.waitTableEnabled(table.getName());
+// ct = new CatalogTracker(TEST_UTIL.getConfiguration());
+// validateSingleRegionServerAssignment(ct, numRegions, numReplica);
+// for (int i = 1; i < numSlaves; i++) { //restore the cluster
+// TEST_UTIL.getMiniHBaseCluster().startRegionServer();
+// }
+
+ //TODO: HBASE-10361 patch should uncomment the test below
+// //check on alter table
+// admin.disableTable(table);
+// assert(admin.isTableDisabled(table));
+// //increase the replica
+// desc.setRegionReplication(numReplica + 1);
+// admin.modifyTable(table, desc);
+// admin.enableTable(table);
+// assert(admin.isTableEnabled(table));
+// List<HRegionInfo> regions = TEST_UTIL.getMiniHBaseCluster().getMaster()
+// .getAssignmentManager().getRegionStates().getRegionsOfTable(table);
+// assert(regions.size() == numRegions * (numReplica + 1));
+//
+// //decrease the replica(earlier, table was modified to have a replica count of numReplica + 1)
+// admin.disableTable(table);
+// desc.setRegionReplication(numReplica);
+// admin.modifyTable(table, desc);
+// admin.enableTable(table);
+// assert(admin.isTableEnabled(table));
+// regions = TEST_UTIL.getMiniHBaseCluster().getMaster()
+// .getAssignmentManager().getRegionStates().getRegionsOfTable(table);
+// assert(regions.size() == numRegions * numReplica);
+// //also make sure the meta table has the replica locations removed
+// hris = MetaReader.getTableRegions(ct, table);
+// assert(hris.size() == numRegions * numReplica);
+// //just check that the number of default replica regions in the meta table are the same
+// //as the number of regions the table was created with, and the count of the
+// //replicas is numReplica for each region
+// Map<HRegionInfo, Integer> defaultReplicas = new HashMap<HRegionInfo, Integer>();
+// for (HRegionInfo hri : hris) {
+// Integer i;
+// HRegionInfo regionReplica0 = hri.getRegionInfoForReplica(0);
+// defaultReplicas.put(regionReplica0,
+// (i = defaultReplicas.get(regionReplica0)) == null ? 1 : i + 1);
+// }
+// assert(defaultReplicas.size() == numRegions);
+// Collection<Integer> counts = new HashSet<Integer>(defaultReplicas.values());
+// assert(counts.size() == 1 && counts.contains(new Integer(numReplica)));
+ } finally {
+ admin.disableTable(table);
+ admin.deleteTable(table);
+ }
+ }
+
+ //@Test (TODO: enable when we have support for alter_table- HBASE-10361).
+ public void testIncompleteMetaTableReplicaInformation() throws Exception {
+ final TableName table = TableName.valueOf("fooTableTest1");
+ final int numRegions = 3;
+ final int numReplica = 2;
+ try {
+ // Create a table and let the meta table be updated with the location of the
+ // region locations.
+ HTableDescriptor desc = new HTableDescriptor(table);
+ desc.setRegionReplication(numReplica);
+ desc.addFamily(new HColumnDescriptor("family"));
+ admin.createTable(desc, Bytes.toBytes("A"), Bytes.toBytes("Z"), numRegions);
+ TEST_UTIL.waitTableEnabled(table.getName());
+ CatalogTracker ct = new CatalogTracker(TEST_UTIL.getConfiguration());
+ Set<byte[]> tableRows = new HashSet<byte[]>();
+ List<HRegionInfo> hris = MetaReader.getTableRegions(ct, table);
+ for (HRegionInfo hri : hris) {
+ tableRows.add(hri.getRegionName());
+ }
+ admin.disableTable(table);
+ // now delete one replica info from all the rows
+ // this is to make the meta appear to be only partially updated
+ HTable metaTable = new HTable(TableName.META_TABLE_NAME, ct.getConnection());
+ for (byte[] row : tableRows) {
+ Delete deleteOneReplicaLocation = new Delete(row);
+ deleteOneReplicaLocation.deleteColumns(HConstants.CATALOG_FAMILY, MetaReader.getServerColumn(1));
+ deleteOneReplicaLocation.deleteColumns(HConstants.CATALOG_FAMILY, MetaReader.getSeqNumColumn(1));
+ deleteOneReplicaLocation.deleteColumns(HConstants.CATALOG_FAMILY, MetaReader.getStartCodeColumn(1));
+ metaTable.delete(deleteOneReplicaLocation);
+ }
+ metaTable.close();
+ // even if the meta table is partly updated, when we re-enable the table, we should
+ // get back the desired number of replicas for the regions
+ admin.enableTable(table);
+ assert(admin.isTableEnabled(table));
+ List<HRegionInfo> regions = TEST_UTIL.getMiniHBaseCluster().getMaster()
+ .getAssignmentManager().getRegionStates().getRegionsOfTable(table);
+ assert(regions.size() == numRegions * numReplica);
+ } finally {
+ admin.disableTable(table);
+ admin.deleteTable(table);
+ }
+ }
+
+ private String printRegions(List<HRegionInfo> regions) {
+ StringBuffer strBuf = new StringBuffer();
+ for (HRegionInfo r : regions) {
+ strBuf.append(" ____ " + r.toString());
+ }
+ return strBuf.toString();
+ }
+
+ private void validateNumberOfRowsInMeta(final TableName table, int numRegions, CatalogTracker ct)
+ throws IOException {
+ assert(admin.tableExists(table));
+ final AtomicInteger count = new AtomicInteger();
+ Visitor visitor = new Visitor() {
+ @Override
+ public boolean visit(Result r) throws IOException {
+ if (HRegionInfo.getHRegionInfo(r).getTable().equals(table)) count.incrementAndGet();
+ return true;
+ }
+ };
+ MetaReader.fullScan(ct, visitor);
+ assert(count.get() == numRegions);
+ }
+
+ private void validateFromSnapshotFromMeta(TableName table, int numRegions,
+ int numReplica, CatalogTracker ct) throws IOException {
+ SnapshotOfRegionAssignmentFromMeta snapshot = new SnapshotOfRegionAssignmentFromMeta(ct);
+ snapshot.initialize();
+ Map<HRegionInfo, ServerName> regionToServerMap = snapshot.getRegionToRegionServerMap();
+ assert(regionToServerMap.size() == numRegions * numReplica + 1); //'1' for the namespace
+ Map<ServerName, List<HRegionInfo>> serverToRegionMap = snapshot.getRegionServerToRegionMap();
+ for (Map.Entry<ServerName, List<HRegionInfo>> entry : serverToRegionMap.entrySet()) {
+ List<HRegionInfo> regions = entry.getValue();
+ Set<byte[]> setOfStartKeys = new HashSet<byte[]>();
+ for (HRegionInfo region : regions) {
+ byte[] startKey = region.getStartKey();
+ if (region.getTable().equals(table)) {
+ setOfStartKeys.add(startKey); //ignore other tables
+ LOG.info("--STARTKEY " + new String(startKey)+"--");
+ }
+ }
+ // the number of startkeys will be equal to the number of regions hosted in each server
+ // (each server will be hosting one replica of a region)
+ assertEquals(setOfStartKeys.size() , numRegions);
+ }
+ }
+
+ private void validateSingleRegionServerAssignment(CatalogTracker ct, int numRegions,
+ int numReplica) throws IOException {
+ SnapshotOfRegionAssignmentFromMeta snapshot = new SnapshotOfRegionAssignmentFromMeta(ct);
+ snapshot.initialize();
+ Map<HRegionInfo, ServerName> regionToServerMap = snapshot.getRegionToRegionServerMap();
+ assert(regionToServerMap.size() == numRegions * numReplica + 1); //'1' for the namespace
+ Map<ServerName, List<HRegionInfo>> serverToRegionMap = snapshot.getRegionServerToRegionMap();
+ assert(serverToRegionMap.keySet().size() == 1);
+ assert(serverToRegionMap.values().iterator().next().size() == numRegions * numReplica + 1);
+ }
+}