diff --git a/build.number b/build.number index 00f8a15..f350577 100644 --- a/build.number +++ b/build.number @@ -1,3 +1,3 @@ #Build Number for ANT. Do not edit! -#Tue Oct 10 13:30:49 CEST 2023 -build.number=1 +#Tue Oct 10 13:44:11 CEST 2023 +build.number=2 diff --git a/source/java/src/org/lucee/extension/resource/s3/Harakiri.java b/source/java/src/org/lucee/extension/resource/s3/Harakiri.java new file mode 100644 index 0000000..c7613b2 --- /dev/null +++ b/source/java/src/org/lucee/extension/resource/s3/Harakiri.java @@ -0,0 +1,82 @@ +package org.lucee.extension.resource.s3; + +import java.util.Map; + +import org.lucee.extension.resource.s3.info.S3Info; + +import lucee.commons.io.log.Log; + +public class Harakiri { + private S3Cache cache; + private HarakiriThread thread; + private Log log; + + public Harakiri(S3Cache cache, Log log) { + this.cache = cache; + this.log = log; + } + + public void touch() { + if (thread == null || !thread.isAlive()) { + synchronized (this) { + if (thread == null || !thread.isAlive()) { + thread = new HarakiriThread(cache, log); + thread.start(); + } + } + } + } + + private static class HarakiriThread extends Thread { + private static final long IDLE_TIMEOUT = 10000; + private static final long INTERVALL = 1000; + private long lastMod; + private S3Cache cache; + private Log log; + + public HarakiriThread(S3Cache cache, Log log) { + this.cache = cache; + this.log = log; + } + + @Override + public void run() { + while (true) { + if (log != null) + log.debug("S3", "S3 cache observer: checking for elements to flush in the cache, there are " + cache.exists.size() + " elements currently in the cache"); + if (!cache.exists.isEmpty()) { + long now = System.currentTimeMillis(); + try { + for (Map.Entry e: cache.exists.entrySet()) { + if (e.getValue().validUntil() < now) { + if (log != null) log.debug("S3", "S3 cache observer: remove object " + e.getKey() + " from cache"); + cache.exists.remove(e.getKey()); + + } + } + } + catch (Exception e) { + if (log != null) log.error("S3", e); + } + lastMod = now; + } + // nothing to do ATM + else { + long now = System.currentTimeMillis(); + if (lastMod + IDLE_TIMEOUT < now) { + if (log != null) log.debug("S3", "S3 cache observer: nothing to do, idle timeout reached, stoping observer "); + break; + } + else if (log != null) log.debug("S3", "S3 cache observer: nothing to do, remaining idle for another " + ((lastMod + IDLE_TIMEOUT) - now) + "ms"); + } + if (log != null) log.debug("S3", "S3 cache observer: sleep for " + INTERVALL + "ms"); + try { + sleep(INTERVALL); + } + catch (InterruptedException e) { + if (log != null) log.error("S3", e); + } + } + } + } +} diff --git a/source/java/src/org/lucee/extension/resource/s3/S3.java b/source/java/src/org/lucee/extension/resource/s3/S3.java index fce3c54..63217c6 100755 --- a/source/java/src/org/lucee/extension/resource/s3/S3.java +++ b/source/java/src/org/lucee/extension/resource/s3/S3.java @@ -105,7 +105,7 @@ public class S3 { private static final ConcurrentHashMap tokens = new ConcurrentHashMap(); private static Map instances = new ConcurrentHashMap(); - private static Map caches = new ConcurrentHashMap(); + private static Map caches = new ConcurrentHashMap(); private final String host; private final String accessKeyId; @@ -115,27 +115,9 @@ public class S3 { private final long cacheTimeout; private final long liveTimeout; - private final Cache cache; + private final S3Cache cache; private Log log; - /////////////////////// CACHE //////////////// - - static class Cache { - - private final Harakiri harakiri; - private ValidUntilMap buckets; - private Map existBuckets; - private final Map> objects = new ConcurrentHashMap>(); - private Map> accessControlLists = new ConcurrentHashMap>(); - private Map regions = new ConcurrentHashMap(); - private final Map bucketRegions = new ConcurrentHashMap(); - Map exists = new ConcurrentHashMap(); - - public Cache(Log log) { - regions.put("US", RegionFactory.US_EAST_1); - harakiri = new Harakiri(this, log); - } - } public static S3 getInstance(S3Properties props, long cache) { @@ -147,7 +129,7 @@ public static S3 getInstance(S3Properties props, long cache) { if (s3 == null) { String keyCache = props.getAccessKeyId() + ":" + props.getSecretAccessKey() + ":" + props.getHostWithoutRegion() + ":" + cache; - Cache c = caches.get(keyCache); + S3Cache c = caches.get(keyCache); if (c == null) { synchronized (caches) { Log log = null; @@ -155,7 +137,7 @@ public static S3 getInstance(S3Properties props, long cache) { if (config != null) log = config.getLog("application"); c = caches.get(keyCache); if (c == null) { - caches.put(keyCache, c = new Cache(log)); + caches.put(keyCache, c = new S3Cache(log)); } } } @@ -177,7 +159,7 @@ public static S3 getInstance(S3Properties props, long cache) { * @param log * @throws S3Exception */ - private S3(Cache cache, String accessKeyId, String secretAccessKey, String host, String defaultLocation, long cacheTimeout, long liveTimeout, boolean cacheRegions, Log log) { + private S3(S3Cache cache, String accessKeyId, String secretAccessKey, String host, String defaultLocation, long cacheTimeout, long liveTimeout, boolean cacheRegions, Log log) { this.cache = cache; this.accessKeyId = accessKeyId; this.secretAccessKey = secretAccessKey; diff --git a/source/java/src/org/lucee/extension/resource/s3/S3Cache.java b/source/java/src/org/lucee/extension/resource/s3/S3Cache.java new file mode 100644 index 0000000..1661e49 --- /dev/null +++ b/source/java/src/org/lucee/extension/resource/s3/S3Cache.java @@ -0,0 +1,33 @@ +package org.lucee.extension.resource.s3; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.lucee.extension.resource.s3.S3.S3BucketExists; +import org.lucee.extension.resource.s3.S3.ValidUntilElement; +import org.lucee.extension.resource.s3.S3.ValidUntilMap; +import org.lucee.extension.resource.s3.info.S3BucketWrapper; +import org.lucee.extension.resource.s3.info.S3Info; +import org.lucee.extension.resource.s3.region.RegionFactory; +import org.lucee.extension.resource.s3.region.RegionFactory.Region; + +import com.amazonaws.services.s3.model.AccessControlList; + +import lucee.commons.io.log.Log; + +class S3Cache { + + final Harakiri harakiri; + ValidUntilMap buckets; + Map existBuckets; + final Map> objects = new ConcurrentHashMap>(); + final Map> accessControlLists = new ConcurrentHashMap>(); + final Map regions = new ConcurrentHashMap(); + final Map bucketRegions = new ConcurrentHashMap(); + final Map exists = new ConcurrentHashMap(); + + public S3Cache(Log log) { + regions.put("US", RegionFactory.US_EAST_1); + harakiri = new Harakiri(this, log); + } +} \ No newline at end of file