This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new ef289e3925 Review "Do not re-start already started services on 
overlapping starts"
ef289e3925 is described below

commit ef289e39256918858da0eece0b10aad63d4f9fa0
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Oct 21 10:37:30 2026 +0100

    Review "Do not re-start already started services on overlapping starts"
    
    Update start state as soon as a component starts.
---
 .../catalina/tribes/group/ChannelCoordinator.java  |  5 +-
 .../tribes/group/TestGroupChannelStartStop.java    | 60 ++++++++++++++++++++++
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/catalina/tribes/group/ChannelCoordinator.java 
b/java/org/apache/catalina/tribes/group/ChannelCoordinator.java
index 1794441d74..89436af4cc 100644
--- a/java/org/apache/catalina/tribes/group/ChannelCoordinator.java
+++ b/java/org/apache/catalina/tribes/group/ChannelCoordinator.java
@@ -175,6 +175,7 @@ public class ChannelCoordinator extends 
ChannelInterceptorBase implements Messag
                 clusterReceiver.setMessageListener(this);
                 clusterReceiver.setChannel(getChannel());
                 clusterReceiver.start();
+                startLevel = startLevel | Channel.SND_RX_SEQ;
                 // synchronize, big time FIXME
                 Member localMember = getChannel().getLocalMember(false);
                 if (localMember instanceof StaticMember) {
@@ -194,6 +195,7 @@ public class ChannelCoordinator extends 
ChannelInterceptorBase implements Messag
             if (Channel.SND_TX_SEQ == (toStart & Channel.SND_TX_SEQ)) {
                 clusterSender.setChannel(getChannel());
                 clusterSender.start();
+                startLevel = startLevel | Channel.SND_TX_SEQ;
                 valid = true;
             }
 
@@ -204,18 +206,19 @@ public class ChannelCoordinator extends 
ChannelInterceptorBase implements Messag
                     ((McastService) 
membershipService).setMessageListener(this);
                 }
                 membershipService.start(MembershipService.MBR_RX);
+                startLevel = startLevel | Channel.MBR_RX_SEQ;
                 valid = true;
             }
             if (Channel.MBR_TX_SEQ == (toStart & Channel.MBR_TX_SEQ)) {
                 membershipService.setChannel(getChannel());
                 membershipService.start(MembershipService.MBR_TX);
+                startLevel = startLevel | Channel.MBR_TX_SEQ;
                 valid = true;
             }
 
             if (!valid) {
                 throw new 
IllegalArgumentException(sm.getString("channelCoordinator.invalid.startLevel"));
             }
-            startLevel = (startLevel | svc);
         } catch (ChannelException cx) {
             throw cx;
         } catch (Exception e) {
diff --git 
a/test/org/apache/catalina/tribes/group/TestGroupChannelStartStop.java 
b/test/org/apache/catalina/tribes/group/TestGroupChannelStartStop.java
index 4460f5dc1b..cd6f2765a4 100644
--- a/test/org/apache/catalina/tribes/group/TestGroupChannelStartStop.java
+++ b/test/org/apache/catalina/tribes/group/TestGroupChannelStartStop.java
@@ -24,7 +24,9 @@ import org.junit.Before;
 import org.junit.Test;
 
 import org.apache.catalina.tribes.Channel;
+import org.apache.catalina.tribes.membership.McastService;
 import org.apache.catalina.tribes.transport.ReceiverBase;
+import org.apache.catalina.tribes.transport.ReplicationTransmitter;
 
 public class TestGroupChannelStartStop {
     private GroupChannel channel = null;
@@ -185,6 +187,30 @@ public class TestGroupChannelStartStop {
         channel.stop(Channel.DEFAULT);
     }
 
+    @Test
+    public void testFailedStartRecordsServicesThatStarted() throws Exception {
+        CountingSender sender = new CountingSender();
+        FailingMembershipService membershipService = new 
FailingMembershipService();
+        channel.setChannelSender(sender);
+        channel.setMembershipService(membershipService);
+        channel.coordinator.setChannel(channel);
+
+        int services = Channel.SND_TX_SEQ | Channel.MBR_RX_SEQ;
+        try {
+            channel.coordinator.internalStart(services);
+            Assert.fail("The first membership start should fail");
+        } catch (Exception expected) {
+            // Expected
+        }
+        Assert.assertEquals(Channel.SND_TX_SEQ, 
channel.coordinator.getStartLevel());
+        Assert.assertEquals(1, sender.startCount);
+
+        channel.coordinator.internalStart(services);
+        Assert.assertEquals(services, channel.coordinator.getStartLevel());
+        Assert.assertEquals(1, sender.startCount);
+        channel.coordinator.internalStop(services);
+    }
+
     @Test
     public void testFalseOption() throws Exception {
         int flag = 0xFFF0;//should get ignored by the underlying components
@@ -211,4 +237,38 @@ public class TestGroupChannelStartStop {
         Thread.sleep(1000);
         channel.stop(Channel.DEFAULT);
     }
+
+    private static class CountingSender extends ReplicationTransmitter {
+
+        private volatile int startCount;
+
+        @Override
+        public synchronized void start() {
+            startCount++;
+        }
+
+        @SuppressWarnings("sync-override")
+        @Override
+        public void stop() {
+            // NO-OP
+        }
+    }
+
+    private static class FailingMembershipService extends McastService {
+
+        private boolean fail = true;
+
+        @Override
+        public void start(int level) throws Exception {
+            if (fail) {
+                fail = false;
+                throw new Exception("Test failure");
+            }
+        }
+
+        @Override
+        public void stop(int level) {
+            // NO-OP
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to