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

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

commit 4b497247bae31bf6fecb200c3debf9899f054746
Author: sainadh777 <[email protected]>
AuthorDate: Mon Aug 17 03:52:34 2026 -0700

    Use LRU order for persistent session swaps (#1045)
---
 .../catalina/session/PersistentManagerBase.java    |  3 +-
 .../catalina/session/TestPersistentManager.java    | 54 ++++++++++++++++++++++
 webapps/docs/changelog.xml                         |  5 ++
 3 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/catalina/session/PersistentManagerBase.java 
b/java/org/apache/catalina/session/PersistentManagerBase.java
index b994ca4a5f..7595f14f67 100644
--- a/java/org/apache/catalina/session/PersistentManagerBase.java
+++ b/java/org/apache/catalina/session/PersistentManagerBase.java
@@ -21,6 +21,7 @@ import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -928,7 +929,6 @@ public abstract class PersistentManagerBase extends 
ManagerBase implements Store
 
         Session[] sessions = findSessions();
 
-        // FIXME: Smarter algorithm (LRU)
         int limit = (int) (getMaxActiveSessions() * 0.9);
 
         if (limit >= sessions.length) {
@@ -940,6 +940,7 @@ public abstract class PersistentManagerBase extends 
ManagerBase implements Store
         }
 
         int toswap = sessions.length - limit;
+        Arrays.sort(sessions, 
Comparator.comparingLong(Session::getLastAccessedTimeInternal));
 
         for (int i = 0; i < sessions.length && toswap > 0; i++) {
             StandardSession session = (StandardSession) sessions[i];
diff --git a/test/org/apache/catalina/session/TestPersistentManager.java 
b/test/org/apache/catalina/session/TestPersistentManager.java
index ac179463ed..eeabcbc9ad 100644
--- a/test/org/apache/catalina/session/TestPersistentManager.java
+++ b/test/org/apache/catalina/session/TestPersistentManager.java
@@ -71,6 +71,38 @@ public class TestPersistentManager {
         Assert.assertEquals(3, manager.getActiveSessionsFull());
     }
 
+    @Test
+    public void testMaxActiveSwapUsesLeastRecentlyUsed() throws Exception {
+        OrderedPersistentManager manager = new OrderedPersistentManager();
+        TesterStore store = new TesterStore();
+        manager.setStore(store);
+
+        Host host = new TesterHost();
+        Context context = new TesterContext();
+        context.setParent(host);
+
+        manager.setContext(context);
+        manager.setMaxActiveSessions(3);
+        manager.setMinIdleSwap(0);
+
+        manager.start();
+
+        StandardSession oldest = (StandardSession) 
manager.createSession("oldest");
+        StandardSession middle = (StandardSession) 
manager.createSession("middle");
+        StandardSession newest = (StandardSession) 
manager.createSession("newest");
+
+        long now = System.currentTimeMillis();
+        oldest.lastAccessedTime = now - 30000;
+        middle.lastAccessedTime = now - 20000;
+        newest.lastAccessedTime = now - 10000;
+
+        manager.setOrderedSessions(newest, middle, oldest);
+        manager.processMaxActiveSwaps();
+
+        Assert.assertEquals(1, store.getSavedIds().size());
+        Assert.assertEquals("oldest", store.getSavedIds().get(0));
+    }
+
     @Test
     public void testBug62175() throws Exception {
         PersistentManager manager = new PersistentManager();
@@ -138,6 +170,28 @@ public class TestPersistentManager {
         }
     }
 
+    private static class OrderedPersistentManager extends 
PersistentManagerBase {
+
+        private Session[] orderedSessions;
+
+        void setOrderedSessions(Session... orderedSessions) {
+            this.orderedSessions = orderedSessions;
+        }
+
+        @Override
+        public Session[] findSessions() {
+            if (orderedSessions == null) {
+                return super.findSessions();
+            }
+            return orderedSessions;
+        }
+
+        @Override
+        public String getName() {
+            return "OrderedPersistentManager";
+        }
+    }
+
     private StandardSession timedOutSession(PersistentManager manager, 
AtomicInteger counter) {
         StandardSession timedOutSession = new StandardSession(manager) {
             private static final long serialVersionUID = -5910605558747844210L;
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index eeee4747b5..a9a3b4d8ad 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -113,6 +113,11 @@
       <fix>
         Fix async path building. (markt)
       </fix>
+      <fix>
+        When a <code>PersistentManager</code> needs to reduce the number of
+        active sessions, swap out the least recently used eligible sessions
+        first. Pull request <pr>1045</pr> provided by sainadh777. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="WebSocket">


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

Reply via email to