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

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


The following commit(s) were added to refs/heads/main by this push:
     new 1959db41b4 Ensure evictions from the static resource cache are in the 
correct order
1959db41b4 is described below

commit 1959db41b42dc93fd71dd0ca2ad467ace943904d
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Sep 3 09:18:58 2026 +0100

    Ensure evictions from the static resource cache are in the correct order
---
 java/org/apache/catalina/webresources/Cache.java     | 10 ++++++----
 .../apache/catalina/webresources/CachedResource.java | 20 +++++++++++++++-----
 webapps/docs/changelog.xml                           |  4 ++++
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/java/org/apache/catalina/webresources/Cache.java 
b/java/org/apache/catalina/webresources/Cache.java
index f1b1076ea3..55ce6b649f 100644
--- a/java/org/apache/catalina/webresources/Cache.java
+++ b/java/org/apache/catalina/webresources/Cache.java
@@ -72,8 +72,9 @@ public class Cache {
     /**
      * Retrieves a single resource from the cache.
      *
-     * @param path resource path
+     * @param path                    resource path
      * @param useClassLoaderResources whether to use class loader resources
+     *
      * @return the web resource
      */
     protected WebResource getResource(String path, boolean 
useClassLoaderResources) {
@@ -170,8 +171,9 @@ public class Cache {
     /**
      * Retrieves multiple resources from the cache.
      *
-     * @param path resource path
+     * @param path                    resource path
      * @param useClassLoaderResources whether to use class loader resources
+     *
      * @return the web resources
      */
     protected WebResource[] getResources(String path, boolean 
useClassLoaderResources) {
@@ -243,8 +245,8 @@ public class Cache {
         // Create an ordered set of all cached resources with the least 
recently
         // used first. This is a background process so we can afford to take 
the
         // time to order the elements first
-        TreeSet<CachedResource> orderedResources =
-                new 
TreeSet<>(Comparator.comparingLong(CachedResource::getNextCheck));
+        TreeSet<CachedResource> orderedResources = new TreeSet<>(
+                
Comparator.comparingLong(CachedResource::getNextCheck).thenComparingLong(CachedResource::getUniqueId));
         orderedResources.addAll(resourceCache.values());
 
         Iterator<CachedResource> iter = orderedResources.iterator();
diff --git a/java/org/apache/catalina/webresources/CachedResource.java 
b/java/org/apache/catalina/webresources/CachedResource.java
index 9f401058d9..83b832692e 100644
--- a/java/org/apache/catalina/webresources/CachedResource.java
+++ b/java/org/apache/catalina/webresources/CachedResource.java
@@ -33,6 +33,7 @@ import java.text.Collator;
 import java.util.Arrays;
 import java.util.Locale;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
 
@@ -57,6 +58,10 @@ public class CachedResource implements WebResource {
     // based on profiler data.
     private static final long CACHE_ENTRY_SIZE = 500;
 
+    // The ordering process in cache eviction requires a unique ID for each 
cached resource
+    private static final AtomicLong uniqueIdSource = new AtomicLong(0);
+    private final long uniqueId = uniqueIdSource.getAndIncrement();
+
     private final Cache cache;
     private final StandardRoot root;
     private final String webAppPath;
@@ -82,11 +87,11 @@ public class CachedResource implements WebResource {
     /**
      * Construct a cached resource.
      *
-     * @param cache The cache
-     * @param root The standard root
-     * @param path The web application path
-     * @param ttl The time to live in milliseconds
-     * @param objectMaxSizeBytes The maximum size of objects to cache
+     * @param cache                    The cache
+     * @param root                     The standard root
+     * @param path                     The web application path
+     * @param ttl                      The time to live in milliseconds
+     * @param objectMaxSizeBytes       The maximum size of objects to cache
      * @param usesClassLoaderResources Whether class loader resources are used
      */
     public CachedResource(Cache cache, StandardRoot root, String path, long 
ttl, int objectMaxSizeBytes,
@@ -460,6 +465,11 @@ public class CachedResource implements WebResource {
     }
 
 
+    long getUniqueId() {
+        return uniqueId;
+    }
+
+
     /*
      * Mimics the behaviour of FileURLConnection.getInputStream for a 
directory. Deliberately uses default locale.
      */
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 807348839b..e7e156ee38 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -306,6 +306,10 @@
       <fix>
         WAR URLConnection should propagate use of caching. (remm)
       </fix>
+      <fix>
+        Ensure resources are evicted from the static resource cache in the
+        correct order. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


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

Reply via email to