Index: src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (revision 1358907) +++ src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (working copy) @@ -140,8 +140,8 @@ // store all the table names in disabling state Set disablingTables = new HashSet(1); - // store all the enabling state tablenames. - Set enablingTables = new HashSet(1); + // store all the enabling state tablenames and corresponding online servers regions. + Map> enablingTables = new HashMap>(1); /** * Server to regions assignment map. @@ -259,6 +259,15 @@ return regions.get(hri); } } + + /** + * Gives enabling table regions. + * @param tableName + * @return list of regionInfos + */ + public List getEnablingTableRegions(String tableName) { + return this.enablingTables.get(tableName); + } /** * Add a regionPlan for the specified region. @@ -272,6 +281,23 @@ } /** + * Add a regionPlan for the specified region if not present. + * + * @param encodedName + * @param plan + * @return return true if plan adds else false. + */ + public boolean addPlanIfNotPresent(HRegionInfo hri, RegionPlan plan) { + synchronized (regionPlans) { + if (regionPlans.get(hri.getEncodedName()) == null) { + regionPlans.put(hri.getEncodedName(), plan); + return true; + } + return false; + } + } + + /** * Add a map of region plans. */ public void addPlans(Map plans) { @@ -351,7 +377,7 @@ // Recover the tables that were not fully moved to DISABLED state. // These tables are in DISABLING state when the master restarted/switched. boolean isWatcherCreated = recoverTableInDisablingState(this.disablingTables); - recoverTableInEnablingState(this.enablingTables, isWatcherCreated); + recoverTableInEnablingState(this.enablingTables.keySet(), isWatcherCreated); } /** @@ -419,6 +445,10 @@ this.failover = true; } + if(this.failover == false && this.enablingTables.size() > 0){ + this.failover = true; + } + // If we found user regions out on cluster, its a failover. if (this.failover) { LOG.info("Found regions out on cluster or in RIT; failover"); @@ -496,6 +526,13 @@ String encodedRegionName = regionInfo.getEncodedName(); LOG.info("Processing region " + regionInfo.getRegionNameAsString() + " in state " + data.getEventType()); + // remove the region from enabling table regions then EnableTableHandler dont consider the + // region for assignment. See HBASE-6317. + List hris = this.enablingTables.get(regionInfo.getTableNameAsString()); + if(hris != null && !hris.isEmpty()){ + hris.remove(regionInfo); + } + synchronized (regionsInTransition) { RegionState regionState = regionsInTransition.get(encodedRegionName); if (regionState != null || @@ -2541,8 +2578,8 @@ } // Region is being served and on an active server // add only if region not in disabled and enabling table - if (false == checkIfRegionBelongsToDisabled(regionInfo) - && false == checkIfRegionsBelongsToEnabling(regionInfo)) { + boolean isEnablingTable = checkIfRegionsBelongsToEnabling(regionInfo); + if (false == checkIfRegionBelongsToDisabled(regionInfo) && !isEnablingTable) { synchronized (this.regions) { regions.put(regionInfo, regionLocation); addToServers(regionLocation, regionInfo); @@ -2555,6 +2592,16 @@ // this will be used in rolling restarts enableTableIfNotDisabledOrDisablingOrEnabling(disabled, disablingOrEnabling, tableName); + if (isEnablingTable) { + List hris = this.enablingTables.get(tableName); + if (!hris.contains(regionInfo)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Adding region" + regionInfo.getRegionNameAsString() + + " to enabling table " + tableName + "."); + } + hris.add(regionInfo); + } + } } } return offlineServers; @@ -2569,15 +2616,16 @@ } private Boolean addTheTablesInPartialState(Set disablingTables, - Set enablingTables, HRegionInfo regionInfo, - String disablingTableName) { + Map> enablingTables, HRegionInfo regionInfo, String tableName) { if (checkIfRegionBelongsToDisabling(regionInfo)) { - disablingTables.add(disablingTableName); + disablingTables.add(tableName); return true; } else if (checkIfRegionsBelongsToEnabling(regionInfo)) { - enablingTables.add(disablingTableName); + if (!enablingTables.containsKey(tableName)) { + enablingTables.put(tableName, new ArrayList()); + } return true; - } + } return false; } Index: src/main/java/org/apache/hadoop/hbase/master/handler/EnableTableHandler.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/handler/EnableTableHandler.java (revision 1358907) +++ src/main/java/org/apache/hadoop/hbase/master/handler/EnableTableHandler.java (working copy) @@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.master.handler; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -27,6 +28,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.Server; +import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableNotDisabledException; import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.catalog.CatalogTracker; @@ -34,7 +36,9 @@ import org.apache.hadoop.hbase.executor.EventHandler; import org.apache.hadoop.hbase.master.AssignmentManager; import org.apache.hadoop.hbase.master.BulkAssigner; +import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.Pair; import org.apache.zookeeper.KeeperException; /** @@ -46,6 +50,7 @@ private final String tableNameStr; private final AssignmentManager assignmentManager; private final CatalogTracker ct; + private boolean masterRestart = false; public EnableTableHandler(Server server, byte [] tableName, CatalogTracker catalogTracker, AssignmentManager assignmentManager, @@ -56,6 +61,7 @@ this.tableNameStr = Bytes.toString(tableName); this.ct = catalogTracker; this.assignmentManager = assignmentManager; + this.masterRestart = skipTableStateCheck; // Check if table exists if (!MetaReader.tableExists(catalogTracker, this.tableNameStr)) { throw new TableNotFoundException(Bytes.toString(tableName)); @@ -99,10 +105,13 @@ LOG.error("Error trying to enable the table " + this.tableNameStr, e); } catch (KeeperException e) { LOG.error("Error trying to enable the table " + this.tableNameStr, e); + } catch (InterruptedException e) { + LOG.error("Error trying to enable the table " + this.tableNameStr, e); } + } - private void handleEnableTable() throws IOException, KeeperException { + private void handleEnableTable() throws IOException, KeeperException, InterruptedException { // I could check table is disabling and if so, not enable but require // that user first finish disabling but that might be obnoxious. @@ -111,18 +120,40 @@ boolean done = false; // Get the regions of this table. We're done when all listed // tables are onlined. - List regionsInMeta; - regionsInMeta = MetaReader.getTableRegions(this.ct, tableName, true); - int countOfRegionsInTable = regionsInMeta.size(); - List regions = regionsToAssign(regionsInMeta); - int regionsCount = regions.size(); + List> tableRegionsAndLocations = MetaReader + .getTableRegionsAndLocations(this.ct, tableName, true); + + int countOfRegionsInTable = tableRegionsAndLocations.size(); + List> regionsWithServerName = + regionsToAssignWithServerName(tableRegionsAndLocations); + + List regions = null; + if (masterRestart) { + List enablingTableRegions = assignmentManager + .getEnablingTableRegions(this.tableNameStr); + if (!enablingTableRegions.isEmpty()) { + regions = addToRegionPlans(regionsWithServerName, enablingTableRegions); + if (LOG.isDebugEnabled()) { + LOG.debug("Assigning " + regions.size() + " regions from " + enablingTableRegions.size() + + " regions of enabling table" + this.tableNameStr + "."); + } + enablingTableRegions.clear(); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No regions to assign for the table " + this.tableNameStr + + " during master restart."); + } + } + } else { + regions = addToRegionPlans(regionsWithServerName, null); + } + int regionsCount = (regions == null) ? 0 : regions.size(); if (regionsCount == 0) { done = true; } LOG.info("Table has " + countOfRegionsInTable + " regions of which " + regionsCount + " are offline."); - BulkEnabler bd = new BulkEnabler(this.server, regions, - countOfRegionsInTable); + BulkEnabler bd = new BulkEnabler(this.server, regions, countOfRegionsInTable, masterRestart); try { if (bd.bulkAssign()) { done = true; @@ -137,6 +168,32 @@ this.tableNameStr); LOG.info("Enabled table is done=" + done); } + + private List addToRegionPlans(List> regionPairs, + List enablingTableRegions) { + List regions = new ArrayList(regionPairs.size()); + for (Pair region : regionPairs) { + HRegionInfo hri = region.getFirst(); + if (masterRestart) { + if (enablingTableRegions.contains(hri)) { + boolean assign = this.assignmentManager.addPlanIfNotPresent(hri, + new RegionPlan(region.getFirst(), null, region.getSecond())); + if (assign) { + regions.add(hri); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Skipping assign for the region " + hri.getRegionNameAsString() + + " during enable table " + hri.getTableNameAsString() + + " because its already in tranition."); + } + } + } + } else { + regions.add(hri); + } + } + return regions; + } /** * @param regionsInMeta This datastructure is edited by this method. @@ -154,18 +211,41 @@ } /** + * @param regionsInMeta + * This datastructure is edited by this method. + * @return The regionsInMeta list minus the regions that have been onlined; i.e. List + * of regions that need onlining. + * @throws IOException + */ + private List> regionsToAssignWithServerName( + final List> regionsInMeta) throws IOException { + final List onlineRegions = this.assignmentManager.getRegionsOfTable(tableName); + List> regionsInMetaCopy = new ArrayList>( + regionsInMeta.size()); + + for (Pair regionLocation : regionsInMeta) { + if (!onlineRegions.contains(regionLocation.getFirst())) { + regionsInMetaCopy.add(regionLocation); + } + } + return regionsInMetaCopy; + } + + /** * Run bulk enable. */ class BulkEnabler extends BulkAssigner { private final List regions; // Count of regions in table at time this assign was launched. private final int countOfRegionsInTable; + private final boolean masterRestart; BulkEnabler(final Server server, final List regions, - final int countOfRegionsInTable) { + final int countOfRegionsInTable, boolean masterRestart) { super(server); this.regions = regions; this.countOfRegionsInTable = countOfRegionsInTable; + this.masterRestart = masterRestart; } @Override @@ -173,7 +253,7 @@ boolean roundRobinAssignment = this.server.getConfiguration().getBoolean( "hbase.master.enabletable.roundrobin", false); - if (!roundRobinAssignment) { + if (masterRestart || !roundRobinAssignment) { for (HRegionInfo region : regions) { if (assignmentManager.isRegionInTransition(region) != null) { continue; @@ -181,7 +261,11 @@ final HRegionInfo hri = region; pool.execute(new Runnable() { public void run() { - assignmentManager.assign(hri, true); + if (masterRestart) { + assignmentManager.assign(hri, true, false, false); + } else { + assignmentManager.assign(hri, true); + } } }); }