This is an automated email from the ASF dual-hosted git repository. tv pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-jcs.git
commit 0be2e8e3ab695b99633e29401c3d48075138cde6 Author: Thomas Vandahl <[email protected]> AuthorDate: Mon Feb 16 13:50:00 2026 +0100 Fix JCS-242 by manually applying PR#368 --- .../auxiliary/lateral/LateralCacheMonitor.java | 19 +++++- .../lateral/socket/tcp/TestTCPLateralUnitTest.java | 77 ++++++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/lateral/LateralCacheMonitor.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/lateral/LateralCacheMonitor.java index 554ce8dc..deec07d0 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/lateral/LateralCacheMonitor.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/lateral/LateralCacheMonitor.java @@ -22,8 +22,8 @@ package org.apache.commons.jcs4.auxiliary.lateral; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.jcs4.auxiliary.AbstractAuxiliaryCacheMonitor; -import org.apache.commons.jcs4.auxiliary.lateral.socket.tcp.LateralTCPCacheNoWait; import org.apache.commons.jcs4.auxiliary.lateral.socket.tcp.LateralTCPCacheFactory; +import org.apache.commons.jcs4.auxiliary.lateral.socket.tcp.LateralTCPCacheNoWait; import org.apache.commons.jcs4.auxiliary.lateral.socket.tcp.behavior.ILateralTCPCacheAttributes; import org.apache.commons.jcs4.engine.CacheStatus; import org.apache.commons.jcs4.engine.ZombieCacheServiceNonLocal; @@ -73,6 +73,21 @@ public class LateralCacheMonitor extends AbstractAuxiliaryCacheMonitor { this.caches.put(cache.getCacheName(), (LateralTCPCacheNoWait<Object, Object>)cache); + // Fix a cache where an exception occurred before it was added to this monitor. + // For instance, where a cache failed to connect to lateral TCP server. + if (cache.getStatus() == CacheStatus.ERROR) + { + if (getState() == Thread.State.NEW) + { + // no need to signal trigger if monitor hasn't started + allright.compareAndSet(true, false); + } + else + { + notifyError(); + } + } + // if not yet started, go ahead if (getState() == Thread.State.NEW) { @@ -105,7 +120,7 @@ public class LateralCacheMonitor extends AbstractAuxiliaryCacheMonitor log.info( "Found LateralTCPCacheNoWait in error, " + cacheName ); final ILateralTCPCacheAttributes lca = - (ILateralTCPCacheAttributes) cache.getAuxiliaryCacheAttributes(); + cache.getAuxiliaryCacheAttributes(); // Get service instance final ICacheServiceNonLocal<Object, Object> cacheService = diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/lateral/socket/tcp/TestTCPLateralUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/lateral/socket/tcp/TestTCPLateralUnitTest.java index 57974894..fe03f324 100644 --- a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/lateral/socket/tcp/TestTCPLateralUnitTest.java +++ b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/lateral/socket/tcp/TestTCPLateralUnitTest.java @@ -27,15 +27,18 @@ import java.util.Map; import java.util.Set; import org.apache.commons.jcs4.JCS; +import org.apache.commons.jcs4.auxiliary.AbstractAuxiliaryCacheMonitor; import org.apache.commons.jcs4.auxiliary.lateral.LateralCommand; import org.apache.commons.jcs4.auxiliary.lateral.LateralElementDescriptor; import org.apache.commons.jcs4.engine.CacheElement; +import org.apache.commons.jcs4.engine.CacheStatus; import org.apache.commons.jcs4.engine.behavior.ICacheElement; import org.apache.commons.jcs4.engine.behavior.ICompositeCacheManager; import org.apache.commons.jcs4.engine.behavior.IElementSerializer; import org.apache.commons.jcs4.engine.control.CompositeCache; import org.apache.commons.jcs4.engine.control.CompositeCacheManager; import org.apache.commons.jcs4.engine.control.MockCompositeCacheManager; +import org.apache.commons.jcs4.engine.control.MockKeyMatcher; import org.apache.commons.jcs4.engine.control.group.GroupAttrName; import org.apache.commons.jcs4.engine.control.group.GroupId; import org.apache.commons.jcs4.utils.serialization.EncryptingSerializer; @@ -334,4 +337,78 @@ class TestTCPLateralUnitTest { simpleSend(new StandardSerializer(), 8111); } + + /** + * Test that the cache has an error status after failing to connect to a TCP server. + */ + @Test + void testCacheErrorStatusTcpConnectionFail() + { + final LateralTCPCacheAttributes lattr = new LateralTCPCacheAttributes(); + lattr.setCacheName("test"); + lattr.setTcpServer("localhost:1109"); + LateralTCPCacheFactory factory = new LateralTCPCacheFactory(); + factory.initialize(); + + LateralTCPCacheNoWait<String, String> lateralNoWait = factory.createCacheNoWait(lattr, + null, new StandardSerializer(), new MockKeyMatcher<>()); + + assertEquals(CacheStatus.ERROR, lateralNoWait.getStatus()); + } + + /** + * Test that the cache monitor can fix a cache that is in error state after failing to connect to a TCP server. + * + * @throws Exception + */ + @Test + void testCacheRecoveryUsingMonitor() throws Exception + { + final LateralTCPCacheAttributes lattr = new LateralTCPCacheAttributes(); + lattr.setCacheName("test"); + lattr.setTcpServer("localhost:1110"); + LateralTCPCacheFactory factory = new LateralTCPCacheFactory(); + factory.initialize(); + + // reduce the monitor idle period between 'fix' attempts for testing purposes + MyCacheMonitor.setIdle(500L); + LateralTCPCacheNoWait<String, String> lateralNoWait = factory.createCacheNoWait(lattr, + null, new StandardSerializer(), new MockKeyMatcher<>()); + + // start a TCP server for the cache to connect to + createCache(1110); + // adding the cache to the monitor releases the monitor 'fix' thread + factory.monitorCache(lateralNoWait); + + Thread.sleep(2000L); + + // verify that the monitor has fixed the cache + assertEquals(CacheStatus.ALIVE, lateralNoWait.getStatus()); + } + + // used to reduce the monitor idle period between 'fix' attempts for testing purposes + private static class MyCacheMonitor extends AbstractAuxiliaryCacheMonitor + { + public static void setIdle(long idlePeriod) + { + AbstractAuxiliaryCacheMonitor.idlePeriod = idlePeriod; + } + + public MyCacheMonitor() + { + super("test"); + } + + @Override + protected void dispose() + { + // nothing to dispose + } + + @Override + protected void doWork() + { + // nothing to do + } + } }
