Skip to content

Commit

Permalink
LDEV-4721 - add Harakiri controller thread
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeloffner committed Oct 10, 2023
1 parent 0010427 commit cdfdaf2
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 25 deletions.
4 changes: 2 additions & 2 deletions build.number
Original file line number Diff line number Diff line change
@@ -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
82 changes: 82 additions & 0 deletions source/java/src/org/lucee/extension/resource/s3/Harakiri.java
Original file line number Diff line number Diff line change
@@ -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<String, S3Info> 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);
}
}
}
}
}
28 changes: 5 additions & 23 deletions source/java/src/org/lucee/extension/resource/s3/S3.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public class S3 {
private static final ConcurrentHashMap<String, Object> tokens = new ConcurrentHashMap<String, Object>();

private static Map<String, S3> instances = new ConcurrentHashMap<String, S3>();
private static Map<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
private static Map<String, S3Cache> caches = new ConcurrentHashMap<String, S3Cache>();

private final String host;
private final String accessKeyId;
Expand All @@ -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<S3BucketWrapper> buckets;
private Map<String, S3BucketExists> existBuckets;
private final Map<String, ValidUntilMap<S3Info>> objects = new ConcurrentHashMap<String, ValidUntilMap<S3Info>>();
private Map<String, ValidUntilElement<AccessControlList>> accessControlLists = new ConcurrentHashMap<String, ValidUntilElement<AccessControlList>>();
private Map<String, Region> regions = new ConcurrentHashMap<String, Region>();
private final Map<String, Region> bucketRegions = new ConcurrentHashMap<String, Region>();
Map<String, S3Info> exists = new ConcurrentHashMap<String, S3Info>();

public Cache(Log log) {
regions.put("US", RegionFactory.US_EAST_1);
harakiri = new Harakiri(this, log);
}
}

public static S3 getInstance(S3Properties props, long cache) {

Expand All @@ -147,15 +129,15 @@ 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;
Config config = CFMLEngineFactory.getInstance().getThreadConfig();
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));
}
}
}
Expand All @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions source/java/src/org/lucee/extension/resource/s3/S3Cache.java
Original file line number Diff line number Diff line change
@@ -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<S3BucketWrapper> buckets;
Map<String, S3BucketExists> existBuckets;
final Map<String, ValidUntilMap<S3Info>> objects = new ConcurrentHashMap<String, ValidUntilMap<S3Info>>();
final Map<String, ValidUntilElement<AccessControlList>> accessControlLists = new ConcurrentHashMap<String, ValidUntilElement<AccessControlList>>();
final Map<String, Region> regions = new ConcurrentHashMap<String, Region>();
final Map<String, Region> bucketRegions = new ConcurrentHashMap<String, Region>();
final Map<String, S3Info> exists = new ConcurrentHashMap<String, S3Info>();

public S3Cache(Log log) {
regions.put("US", RegionFactory.US_EAST_1);
harakiri = new Harakiri(this, log);
}
}

0 comments on commit cdfdaf2

Please sign in to comment.