Mercurial Hosting > luan
diff src/luan/modules/http/LuanHandler.java @ 1401:ef1620aa99cb
fix gc issues
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 16 Sep 2019 22:51:41 -0400 |
parents | 221eedb0f54e |
children | 27efb1fcbcb5 |
line wrap: on
line diff
--- a/src/luan/modules/http/LuanHandler.java Fri Sep 13 05:05:51 2019 -0600 +++ b/src/luan/modules/http/LuanHandler.java Mon Sep 16 22:51:41 2019 -0400 @@ -10,6 +10,9 @@ import java.net.BindException; import java.util.List; import java.util.ArrayList; +import java.util.Set; +import java.util.Collections; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import luan.lib.logging.Logger; @@ -31,25 +34,28 @@ import luan.modules.logging.LuanLogger; -public final class LuanHandler implements Handler, Luan.OnClose { +public final class LuanHandler implements Handler, Closeable { private static final Logger sysLogger = LoggerFactory.getLogger(LuanHandler.class); + private static final Set<LuanHandler> dontGc = Collections.newSetFromMap(new ConcurrentHashMap<LuanHandler,Boolean>()); + private final Luan luanInit; private final String domain; private final Logger luanLogger; private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); - private final List<Reference<Closeable>> onClose = new ArrayList<Reference<Closeable>>(); private volatile Luan currentLuan; private volatile boolean isDisabled = false; private static final Method resetLuanMethod; private static final Method evalInRootMethod; private static final Method disableLuanMethod; + private static final Method dontGcMethod; static { try { - resetLuanMethod = LuanHandler.class.getMethod( "reset_luan" ); - evalInRootMethod = LuanHandler.class.getMethod( "eval_in_root", String.class ); - disableLuanMethod = LuanHandler.class.getMethod( "disable_luan" ); + resetLuanMethod = LuanHandler.Fns.class.getMethod( "reset_luan" ); + evalInRootMethod = LuanHandler.Fns.class.getMethod( "eval_in_root", String.class ); + disableLuanMethod = LuanHandler.Fns.class.getMethod( "disable_luan" ); + dontGcMethod = LuanHandler.Fns.class.getMethod( "dont_gc" ); } catch(NoSuchMethodException e) { throw new RuntimeException(e); } @@ -60,20 +66,22 @@ this.domain = domain; this.luanLogger = luanInit.getLogger(LuanHandler.class); try { + Fns fns = new Fns(this); LuanTable Http = (LuanTable)luanInit.require("luan:http/Http.luan"); if( Http.get("reset_luan") == null ) - Http.put( "reset_luan", new LuanJavaFunction(luanInit,resetLuanMethod,this) ); - Http.put( "eval_in_root", new LuanJavaFunction(luanInit,evalInRootMethod,this) ); - Http.put( "disable_luan", new LuanJavaFunction(luanInit,disableLuanMethod,this) ); + Http.put( "reset_luan", new LuanJavaFunction(luanInit,resetLuanMethod,fns) ); + Http.put( "eval_in_root", new LuanJavaFunction(luanInit,evalInRootMethod,fns) ); + Http.put( "disable_luan", new LuanJavaFunction(luanInit,disableLuanMethod,fns) ); + Http.put( "dont_gc", new LuanJavaFunction(luanInit,dontGcMethod,fns) ); } catch(LuanException e) { throw new RuntimeException(e); } + sysLogger.info("new "+domain); currentLuan = newLuan(); - sysLogger.info("new "+domain); } protected void finalize() throws Throwable { - sysLogger.info("gc "+domain); + sysLogger.info("gc "+domain); } private Luan newLuan() { @@ -82,7 +90,6 @@ LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); luan = (Luan)cloner.clone(luanInit); } - luan.onClose = this; try { PackageLuan.load(luan,"site:/init.luan"); } catch(LuanException e) { @@ -126,26 +133,9 @@ } } - public void onClose(Closeable c) { - synchronized(onClose) { - onClose.add(new WeakReference<Closeable>(c)); - } - } - public void close() { - synchronized(onClose) { - for( Reference<Closeable> ref : onClose ) { - Closeable c = ref.get(); - if( c != null ) { - try { - c.close(); - } catch(IOException e) { - luanLogger.error(c.toString(),e); - } - } - } - onClose.clear(); - } + Object obj = dontGc.remove(this); + //sysLogger.info("close "+domain+" "+(obj!=null)); } public Object call_rpc(String fnName,Object... args) throws LuanException { @@ -168,7 +158,15 @@ } } - public void reset_luan() { + public static void start(Server server) throws Exception { + try { + server.start(); + } catch(BindException e) { + throw new LuanException(e.toString()); + } + } + + private void reset_luan() { new Thread() {public void run(){ rwLock.writeLock().lock(); try { @@ -180,32 +178,57 @@ }}.start(); } - public void disable_luan() { + private void disable_luan() { isDisabled = true; } - public void eval_in_root(String text) throws LuanException { + private void eval_in_root(String text) throws LuanException { Luan luan; synchronized(luanInit) { LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); luan = (Luan)cloner.clone(currentLuan); } luan.load(text,"<eval_in_root>",null).call(); - currentLuan.onClose = null; - luan.onClose = this; currentLuan = luan; } - public static void start(Server server) throws Exception { - try { - server.start(); - } catch(BindException e) { - throw new LuanException(e.toString()); + private void dont_gc() { + dontGc.add(this); + //sysLogger.info("dont_gc "+domain); + } + + public static final class Fns { + private final Reference<LuanHandler> ref; + + private Fns(LuanHandler lh) { + this.ref = new WeakReference<LuanHandler>(lh); + } + + private LuanHandler lh() throws LuanException { + LuanHandler lh = ref.get(); + if( lh == null ) + throw new LuanException("HTTP handler has been garbage collected"); + return lh; + } + + public void reset_luan() throws LuanException { + lh().reset_luan(); + } + + public void disable_luan() throws LuanException { + lh().disable_luan(); + } + + public void eval_in_root(String text) throws LuanException { + lh().eval_in_root(text); + } + + public void dont_gc() throws LuanException { + lh().dont_gc(); } } - // from HttpServicer private Response service(Request request,boolean notFound) @@ -289,9 +312,7 @@ for( String mod : mods ) { if( loaded.rawGet(mod) == null ) { LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - currentLuan.onClose = null; currentLuan = (Luan)cloner.clone(currentLuan); - currentLuan.onClose = this; break; } }