diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/favored/FavoredNodesManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/favored/FavoredNodesManager.java index cfb9befdaaf..b055509cf57 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/favored/FavoredNodesManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/favored/FavoredNodesManager.java @@ -165,7 +165,7 @@ public class FavoredNodesManager { teritiaryRSToRegionMap.put(serverToUse, regionList); } - private synchronized void deleteFavoredNodesForRegions(Collection regionInfoList) { + public synchronized void deleteFavoredNodesForRegions(Collection regionInfoList) { for (HRegionInfo hri : regionInfoList) { List favNodes = getFavoredNodes(hri); if (favNodes != null) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CatalogJanitor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CatalogJanitor.java index e748c3b9149..d2863e387bd 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CatalogJanitor.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CatalogJanitor.java @@ -27,6 +27,7 @@ import java.util.TreeMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import com.google.common.collect.Lists; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.fs.FileSystem; @@ -42,6 +43,7 @@ import org.apache.hadoop.hbase.backup.HFileArchiver; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.favored.FavoredNodesManager; import org.apache.hadoop.hbase.regionserver.HRegionFileSystem; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.FSUtils; @@ -215,6 +217,10 @@ public class CatalogJanitor extends ScheduledChore { MetaTableAccessor.deleteMergeQualifiers(services.getConnection(), mergedRegion); services.getServerManager().removeRegion(regionA); services.getServerManager().removeRegion(regionB); + FavoredNodesManager fnm = this.services.getFavoredNodesManager(); + if (fnm != null) { + fnm.deleteFavoredNodesForRegions(Lists.newArrayList(regionA, regionB)); + } return true; } return false; @@ -360,6 +366,10 @@ public class CatalogJanitor extends ScheduledChore { HFileArchiver.archiveRegion(this.services.getConfiguration(), fs, parent); MetaTableAccessor.deleteRegion(this.connection, parent); services.getServerManager().removeRegion(parent); + FavoredNodesManager fnm = this.services.getFavoredNodesManager(); + if (fnm != null) { + fnm.deleteFavoredNodesForRegions(Lists.newArrayList(parent)); + } result = true; } return result; diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java index ffe86317051..06b666b47e0 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/DeleteTableProcedure.java @@ -43,6 +43,7 @@ import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.exceptions.HBaseException; +import org.apache.hadoop.hbase.favored.FavoredNodesManager; import org.apache.hadoop.hbase.master.AssignmentManager; import org.apache.hadoop.hbase.master.MasterCoprocessorHost; import org.apache.hadoop.hbase.master.MasterFileSystem; @@ -365,6 +366,12 @@ public class DeleteTableProcedure // clean region references from the server manager env.getMasterServices().getServerManager().removeRegions(regions); + + // Clear Favored Nodes for this table + FavoredNodesManager fnm = env.getMasterServices().getFavoredNodesManager(); + if (fnm != null) { + fnm.deleteFavoredNodesForRegions(regions); + } } protected static void deleteAssignmentState(final MasterProcedureEnv env, diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestTableFavoredNodes.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestTableFavoredNodes.java index 184d80e504a..957e04a2389 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestTableFavoredNodes.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestTableFavoredNodes.java @@ -23,6 +23,7 @@ import static org.apache.hadoop.hbase.favored.FavoredNodesPlan.Position.TERTIARY import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; @@ -99,6 +100,7 @@ public class TestTableFavoredNodes { fnm = TEST_UTIL.getMiniHBaseCluster().getMaster().getFavoredNodesManager(); admin = TEST_UTIL.getAdmin(); admin.setBalancerRunning(false, true); + admin.enableCatalogJanitor(false); regionStates = TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStates(); } @@ -116,6 +118,36 @@ public class TestTableFavoredNodes { // All regions should have favored nodes checkIfFavoredNodeInformationIsCorrect(tableName); + List regions = admin.getTableRegions(tableName); + + TEST_UTIL.deleteTable(tableName); + + checkNoFNForDeletedTable(regions); + } + + /* + * Checks if favored node information is removed on table truncation. + */ + @Test + public void testTruncateTable() throws Exception { + + TableName tableName = TableName.valueOf("truncateTable"); + TEST_UTIL.createTable(tableName, Bytes.toBytes("f"), splitKeys); + TEST_UTIL.waitUntilAllRegionsAssigned(tableName); + + // All regions should have favored nodes + checkIfFavoredNodeInformationIsCorrect(tableName); + + List regions = admin.getTableRegions(tableName); + TEST_UTIL.truncateTable(tableName, true); + + checkNoFNForDeletedTable(regions); + checkIfFavoredNodeInformationIsCorrect(tableName); + + regions = admin.getTableRegions(tableName); + TEST_UTIL.truncateTable(tableName, false); + checkNoFNForDeletedTable(regions); + TEST_UTIL.deleteTable(tableName); } @@ -156,16 +188,25 @@ public class TestTableFavoredNodes { checkIfDaughterInherits2FN(parentFN, daughter2FN); assertEquals("Daughter's PRIMARY FN should be PRIMARY of parent", - parentFN.get(PRIMARY.ordinal()), daughter1FN.get(PRIMARY.ordinal())); + parentFN.get(PRIMARY.ordinal()), daughter1FN.get(PRIMARY.ordinal())); assertEquals("Daughter's SECONDARY FN should be SECONDARY of parent", - parentFN.get(SECONDARY.ordinal()), daughter1FN.get(SECONDARY.ordinal())); + parentFN.get(SECONDARY.ordinal()), daughter1FN.get(SECONDARY.ordinal())); assertEquals("Daughter's PRIMARY FN should be PRIMARY of parent", parentFN.get(PRIMARY.ordinal()), daughter2FN.get(PRIMARY.ordinal())); assertEquals("Daughter's SECONDARY FN should be TERTIARY of parent", parentFN.get(TERTIARY.ordinal()), daughter2FN.get(SECONDARY.ordinal())); + // Major compact table and run catalog janitor. Parent's FN should be removed + TEST_UTIL.getMiniHBaseCluster().compact(tableName, true); + assertEquals("Parent region should have been cleaned", 1, admin.runCatalogScan()); + assertNull("Parent FN should be null", fnm.getFavoredNodes(parent)); + + List regions = admin.getTableRegions(tableName); + TEST_UTIL.deleteTable(tableName); + + checkNoFNForDeletedTable(regions); } /* @@ -204,7 +245,23 @@ public class TestTableFavoredNodes { assertArrayEquals("Merged region doesn't match regionA's FN", regionAFN.toArray(), mergedFN.toArray()); + // Major compact table and run catalog janitor. Parent FN should be removed + TEST_UTIL.getMiniHBaseCluster().compact(tableName, true); + assertEquals("Merge parents should have been cleaned", 1, admin.runCatalogScan()); + assertNull("Parent FN should be null", fnm.getFavoredNodes(regionA)); + assertNull("Parent FN should be null", fnm.getFavoredNodes(regionB)); + + List regions = admin.getTableRegions(tableName); + TEST_UTIL.deleteTable(tableName); + + checkNoFNForDeletedTable(regions); + } + + private void checkNoFNForDeletedTable(List regions) { + for (HRegionInfo region : regions) { + assertNull("FN not null for deleted table's region: " + region, fnm.getFavoredNodes(region)); + } } /*