This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 7b21f72d4a8e7c74fbbbcddf2bf9589ccadf94de Author: opencode <[email protected]> AuthorDate: Fri Oct 9 14:39:40 2026 +0200 Fix inverted comparison in NonBlockingCoordinator.hasHigherPriority The method's contract is to return true when the complete membership has a higher priority leader than the local membership. With the AbsoluteOrder comparator, a lower value means a higher rank, so the comparison against the two sorted leaders must be smaller than zero. The inverted larger-than comparison made the only call site in handleViewConf() dead: mergeOnArrive() seeds the merged membership with the complete local membership, so the merged leader can never outrank the local one and the re-election triggered when a confirmed view contained a higher priority leader never fired. With the comparison fixed, the branch fires exactly when the local member outranks every other known member and a view was confirmed under a lower priority leader, letting the highest priority member assert its leadership immediately, as intended by the algorithm and consistent with the isHighest() gated elections on member events and heartbeats. The existing election guards keep this from causing election storms. --- .../group/interceptors/NonBlockingCoordinator.java | 2 +- .../TestNonBlockingCoordinatorPriority.java | 48 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java b/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java index 5e65d41719..baada05d1f 100644 --- a/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java +++ b/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java @@ -606,7 +606,7 @@ public class NonBlockingCoordinator extends ChannelInterceptorBase { } AbsoluteOrder.absoluteOrder(complete); AbsoluteOrder.absoluteOrder(local); - return (AbsoluteOrder.comp.compare(complete[0], local[0]) > 0); + return (AbsoluteOrder.comp.compare(complete[0], local[0]) < 0); } diff --git a/test/org/apache/catalina/tribes/group/interceptors/TestNonBlockingCoordinatorPriority.java b/test/org/apache/catalina/tribes/group/interceptors/TestNonBlockingCoordinatorPriority.java new file mode 100644 index 0000000000..5716e87971 --- /dev/null +++ b/test/org/apache/catalina/tribes/group/interceptors/TestNonBlockingCoordinatorPriority.java @@ -0,0 +1,48 @@ +/* + * 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.catalina.tribes.group.interceptors; + +import org.junit.Assert; +import org.junit.Test; + +import org.apache.catalina.tribes.Member; +import org.apache.catalina.tribes.membership.MemberImpl; + +public class TestNonBlockingCoordinatorPriority { + + @Test + public void testHasHigherPriority() throws Exception { + NonBlockingCoordinator coordinator = new NonBlockingCoordinator(); + + // Under absolute ordering, lower host bytes mean a higher rank + Member high = new MemberImpl("10.0.0.1", 4000, -1); + Member low = new MemberImpl("10.0.0.2", 4000, -1); + + Assert.assertTrue("A membership with the higher priority member must win", + coordinator.hasHigherPriority(new Member[] { low, high }, new Member[] { low })); + Assert.assertFalse("A membership with the lower priority member must not win", + coordinator.hasHigherPriority(new Member[] { low }, new Member[] { high, low })); + Assert.assertFalse("Identical leaders must not win", + coordinator.hasHigherPriority(new Member[] { high }, new Member[] { high })); + Assert.assertFalse("An empty local membership must never be outranked", + coordinator.hasHigherPriority(new Member[] { high }, new Member[0])); + Assert.assertTrue("An empty complete membership is treated as higher priority", + coordinator.hasHigherPriority(null, new Member[] { high })); + Assert.assertFalse("A null local membership must never be outranked", + coordinator.hasHigherPriority(new Member[] { high }, null)); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
