diff --git a/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java b/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java index b4ba5ab..d21375a 100644 --- a/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java +++ b/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java @@ -28,9 +28,11 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NavigableMap; +import java.util.NavigableSet; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -204,7 +206,7 @@ public class RegionManager { // figure out what regions need to be assigned and aren't currently being // worked on elsewhere. - Set regionsToAssign = + NavigableSet regionsToAssign = regionsAwaitingAssignment(info.getServerAddress(), isSingleServer); if (regionsToAssign.size() == 0) { // There are no regions waiting to be assigned. @@ -236,7 +238,7 @@ public class RegionManager { * @param returnMsgs */ private void assignRegionsToMultipleServers(final HServerLoad thisServersLoad, - final Set regionsToAssign, final HServerInfo info, + final NavigableSet regionsToAssign, final HServerInfo info, final ArrayList returnMsgs) { boolean isMetaAssign = false; for (RegionState s : regionsToAssign) { @@ -299,7 +301,19 @@ public class RegionManager { if (count > this.maxAssignInOneGo) { count = this.maxAssignInOneGo; } + HRegionInfo previous = null; for (RegionState s: regionsToAssign) { + if (previous != null && previous.getEndKey() != null && + Bytes.equals(previous.getEndKey(), s.getRegionInfo().getStartKey())) { + // If contiguous regions, do not assign adjacent regions in this + // one assignment session. We do this to break daughters of splits so + // its more likely they endup on different clusters on the cluster. + LOG.info("Passing on " + s.getRegionInfo().getRegionNameAsString() + + " because contiguous with " + previous.getRegionNameAsString() + + " (will assign next server that checks in)"); + continue; + } + previous = s.getRegionInfo(); doRegionAssignment(s, info, returnMsgs); if (--count <= 0) { break; @@ -318,7 +332,7 @@ public class RegionManager { * @param serverName * @param returnMsgs */ - private void assignRegionsToOneServer(final Set regionsToAssign, + private void assignRegionsToOneServer(final NavigableSet regionsToAssign, final HServerInfo info, final ArrayList returnMsgs) { for (RegionState s: regionsToAssign) { doRegionAssignment(s, info, returnMsgs); @@ -389,10 +403,10 @@ public class RegionManager { * only caller (assignRegions, whose caller is ServerManager.processMsgs) owns * the monitor for RegionManager */ - private Set regionsAwaitingAssignment(HServerAddress addr, - boolean isSingleServer) { + private NavigableSet regionsAwaitingAssignment(HServerAddress addr, + boolean isSingleServer) { // set of regions we want to assign to this server - Set regionsToAssign = new HashSet(); + NavigableSet regionsToAssign = new TreeSet(); boolean isMetaServer = isMetaServer(addr); RegionState rootState = null; diff --git a/src/test/java/org/apache/hadoop/hbase/master/TestRegionServerOperationQueue.java b/src/test/java/org/apache/hadoop/hbase/master/TestRegionServerOperationQueue.java index dea4edd..bf63e1a 100644 --- a/src/test/java/org/apache/hadoop/hbase/master/TestRegionServerOperationQueue.java +++ b/src/test/java/org/apache/hadoop/hbase/master/TestRegionServerOperationQueue.java @@ -18,9 +18,13 @@ * limitations under the License. */ package org.apache.hadoop.hbase.master; +import static org.junit.Assert.*; + import java.util.concurrent.atomic.AtomicBoolean; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.master.RegionServerOperationQueue.ProcessingResultCode; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -47,6 +51,8 @@ public class TestRegionServerOperationQueue { } @Test - public void testNothing() throws Exception { + public void testWeDoNotGetStuckInDelayQueue() throws Exception { + ProcessingResultCode code = this.queue.process(); + assertTrue(ProcessingResultCode.NOOP == code); } }