This is an automated email from the ASF dual-hosted git repository. dlmarion pushed a commit to branch 2.1 in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/2.1 by this push: new 8c3812bb3c Created HostRegexTableLoadBalancer test default pool, fixed bug (#5492) 8c3812bb3c is described below commit 8c3812bb3ceec92cff6ecb8a77f935c156397199 Author: Dave Marion <dlmar...@apache.org> AuthorDate: Tue Apr 22 11:23:16 2025 -0400 Created HostRegexTableLoadBalancer test default pool, fixed bug (#5492) Users can define a regex for the default pool. The code already supports this, but we didn't have tests for it. Also fixed a bug in the balance method with the out of bounds check. The code was using `Map.getOrDefault` which returns the default value, but doesn't insert it into the map. The side effect of this is that the out of bounds checks were not being performed because the condition could never be true. Modified the code to use `Map.computeIfAbsent` which will insert the value into the map for subsequent checks. Closes #5489 --- .../spi/balancer/HostRegexTableLoadBalancer.java | 5 +- .../balancer/HostRegexTableLoadBalancerTest.java | 174 +++++++++++++++++++++ 2 files changed, 176 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/apache/accumulo/core/spi/balancer/HostRegexTableLoadBalancer.java b/core/src/main/java/org/apache/accumulo/core/spi/balancer/HostRegexTableLoadBalancer.java index b64863fee1..aad49dc238 100644 --- a/core/src/main/java/org/apache/accumulo/core/spi/balancer/HostRegexTableLoadBalancer.java +++ b/core/src/main/java/org/apache/accumulo/core/spi/balancer/HostRegexTableLoadBalancer.java @@ -395,9 +395,8 @@ public class HostRegexTableLoadBalancer extends TableLoadBalancer { Map<String,SortedMap<TabletServerId,TServerStatus>> currentGrouped = splitCurrentByRegex(params.currentStatus()); - if ((now - - this.lastOOBCheckTimes.getOrDefault(params.partitionName(), System.currentTimeMillis())) - > myConf.oobCheckMillis) { + if ((now - this.lastOOBCheckTimes.computeIfAbsent(params.partitionName(), + (p) -> System.currentTimeMillis())) > myConf.oobCheckMillis) { try { // Check to see if a tablet is assigned outside the bounds of the pool. If so, migrate it. for (String table : tableIdMap.keySet()) { diff --git a/core/src/test/java/org/apache/accumulo/core/spi/balancer/HostRegexTableLoadBalancerTest.java b/core/src/test/java/org/apache/accumulo/core/spi/balancer/HostRegexTableLoadBalancerTest.java index 9c9de172c2..4af9708a03 100644 --- a/core/src/test/java/org/apache/accumulo/core/spi/balancer/HostRegexTableLoadBalancerTest.java +++ b/core/src/test/java/org/apache/accumulo/core/spi/balancer/HostRegexTableLoadBalancerTest.java @@ -186,6 +186,7 @@ public class HostRegexTableLoadBalancerTest extends BaseHostRegexTableLoadBalanc barHosts.containsKey(new TabletServerIdImpl("192.168.0.9", 9997, Integer.toHexString(1)))); assertTrue( barHosts.containsKey(new TabletServerIdImpl("192.168.0.10", 9997, Integer.toHexString(1)))); + // confirms that the default pool contains un-assigned tservers assertTrue(groups.containsKey(DEFAULT_POOL)); SortedMap<TabletServerId,TServerStatus> defHosts = groups.get(DEFAULT_POOL); assertEquals(5, defHosts.size()); @@ -201,6 +202,179 @@ public class HostRegexTableLoadBalancerTest extends BaseHostRegexTableLoadBalanc defHosts.containsKey(new TabletServerIdImpl("192.168.0.15", 9997, Integer.toHexString(1)))); } + @Test + public void testDefaultPoolAll() { + // If all tservers are included in regular expressions, the the default pool + // contains all tservers + HashMap<String,String> props = new HashMap<>(DEFAULT_TABLE_PROPERTIES); + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + FOO.getTableName(), "r01.*"); + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + BAR.getTableName(), "r02.*"); + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + BAZ.getTableName(), "r03.*"); + init(props); + Map<String,SortedMap<TabletServerId,TServerStatus>> groups = + this.splitCurrentByRegex(createCurrent(15)); + assertEquals(4, groups.size()); + assertTrue(groups.containsKey(FOO.getTableName())); + SortedMap<TabletServerId,TServerStatus> fooHosts = groups.get(FOO.getTableName()); + assertEquals(5, fooHosts.size()); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.1", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.2", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.3", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.4", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.5", 9997, Integer.toHexString(1)))); + assertTrue(groups.containsKey(BAR.getTableName())); + SortedMap<TabletServerId,TServerStatus> barHosts = groups.get(BAR.getTableName()); + assertEquals(5, barHosts.size()); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.6", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.7", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.8", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.9", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.10", 9997, Integer.toHexString(1)))); + assertTrue(groups.containsKey(BAZ.getTableName())); + SortedMap<TabletServerId,TServerStatus> bazHosts = groups.get(BAZ.getTableName()); + assertEquals(5, bazHosts.size()); + assertTrue( + bazHosts.containsKey(new TabletServerIdImpl("192.168.0.11", 9997, Integer.toHexString(1)))); + assertTrue( + bazHosts.containsKey(new TabletServerIdImpl("192.168.0.12", 9997, Integer.toHexString(1)))); + assertTrue( + bazHosts.containsKey(new TabletServerIdImpl("192.168.0.13", 9997, Integer.toHexString(1)))); + assertTrue( + bazHosts.containsKey(new TabletServerIdImpl("192.168.0.14", 9997, Integer.toHexString(1)))); + assertTrue( + bazHosts.containsKey(new TabletServerIdImpl("192.168.0.15", 9997, Integer.toHexString(1)))); + assertTrue(groups.containsKey(DEFAULT_POOL)); + SortedMap<TabletServerId,TServerStatus> defHosts = groups.get(DEFAULT_POOL); + assertEquals(15, defHosts.size()); + } + + @Test + public void testSplitCurrentByRegexDefineDefaultPoolOverlapping() { + HashMap<String,String> props = new HashMap<>(DEFAULT_TABLE_PROPERTIES); + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + FOO.getTableName(), "r01.*"); + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + BAR.getTableName(), "r02.*"); + // Normally the DEFAULT pool would be comprised of the hosts not included in a regex. + // Here we are going to define it as also being on rack1 + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + DEFAULT_POOL, "r01.*"); + init(props); + Map<String,SortedMap<TabletServerId,TServerStatus>> groups = + this.splitCurrentByRegex(createCurrent(15)); + assertEquals(3, groups.size()); + assertTrue(groups.containsKey(FOO.getTableName())); + SortedMap<TabletServerId,TServerStatus> fooHosts = groups.get(FOO.getTableName()); + assertEquals(5, fooHosts.size()); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.1", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.2", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.3", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.4", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.5", 9997, Integer.toHexString(1)))); + assertTrue(groups.containsKey(BAR.getTableName())); + SortedMap<TabletServerId,TServerStatus> barHosts = groups.get(BAR.getTableName()); + assertEquals(5, barHosts.size()); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.6", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.7", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.8", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.9", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.10", 9997, Integer.toHexString(1)))); + assertTrue(groups.containsKey(DEFAULT_POOL)); + SortedMap<TabletServerId,TServerStatus> defHosts = groups.get(DEFAULT_POOL); + assertEquals(10, defHosts.size()); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.1", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.2", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.3", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.4", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.5", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.11", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.12", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.13", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.14", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.15", 9997, Integer.toHexString(1)))); + } + + @Test + public void testSplitCurrentByRegexDefineDefaultPoolNonOverlapping() { + HashMap<String,String> props = new HashMap<>(DEFAULT_TABLE_PROPERTIES); + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + FOO.getTableName(), "r01.*"); + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + BAR.getTableName(), "r02.*"); + // Normally the DEFAULT pool would be comprised of the hosts not included in a regex. + // Here we are going to define it as also being on rack3 + props.put(HostRegexTableLoadBalancer.HOST_BALANCER_PREFIX + DEFAULT_POOL, "r03.*"); + init(props); + Map<String,SortedMap<TabletServerId,TServerStatus>> groups = + this.splitCurrentByRegex(createCurrent(15)); + assertEquals(3, groups.size()); + assertTrue(groups.containsKey(FOO.getTableName())); + SortedMap<TabletServerId,TServerStatus> fooHosts = groups.get(FOO.getTableName()); + assertEquals(5, fooHosts.size()); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.1", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.2", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.3", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.4", 9997, Integer.toHexString(1)))); + assertTrue( + fooHosts.containsKey(new TabletServerIdImpl("192.168.0.5", 9997, Integer.toHexString(1)))); + assertTrue(groups.containsKey(BAR.getTableName())); + SortedMap<TabletServerId,TServerStatus> barHosts = groups.get(BAR.getTableName()); + assertEquals(5, barHosts.size()); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.6", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.7", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.8", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.9", 9997, Integer.toHexString(1)))); + assertTrue( + barHosts.containsKey(new TabletServerIdImpl("192.168.0.10", 9997, Integer.toHexString(1)))); + assertTrue(groups.containsKey(DEFAULT_POOL)); + SortedMap<TabletServerId,TServerStatus> defHosts = groups.get(DEFAULT_POOL); + assertEquals(5, defHosts.size()); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.11", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.12", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.13", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.14", 9997, Integer.toHexString(1)))); + assertTrue( + defHosts.containsKey(new TabletServerIdImpl("192.168.0.15", 9997, Integer.toHexString(1)))); + + } + @Test public void testSplitCurrentByRegexUsingOverlappingPools() { HashMap<String,String> props = new HashMap<>(DEFAULT_TABLE_PROPERTIES);