Mercurial Hosting > luan
changeset 1264:d41997776788
fix onClose issues
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 25 Sep 2018 17:03:57 -0600 |
parents | 382c444a6c77 |
children | 3f4644246e39 |
files | src/luan/LuanState.java src/luan/host/Backup.java src/luan/host/WebHandler.java src/luan/modules/http/LuanHandler.java |
diffstat | 4 files changed, 169 insertions(+), 90 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/LuanState.java Mon Sep 24 22:06:25 2018 -0600 +++ b/src/luan/LuanState.java Tue Sep 25 17:03:57 2018 -0600 @@ -2,10 +2,6 @@ import java.io.Closeable; import java.io.IOException; -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import org.slf4j.Logger; @@ -20,9 +16,13 @@ public LuanJavaOk javaOk; private Map registry; - private final List<Reference<Closeable>> onClose = new ArrayList<Reference<Closeable>>(); public boolean isLocked = false; + public interface OnClose extends Closeable { + public void onClose(Closeable c); + } + public OnClose onClose; + public LuanState() { javaOk = new LuanJavaOk(); registry = new HashMap(); @@ -47,25 +47,8 @@ } public void onClose(Closeable c) { - onClose.add(new WeakReference<Closeable>(c)); - } - - public void close() { - for( Reference<Closeable> ref : onClose ) { - Closeable c = ref.get(); - if( c != null ) { - try { - c.close(); - } catch(IOException e) { - logger.error(c.toString(),e); - } - } - } - onClose.clear(); - } - - protected void finalize() throws Throwable { - close(); + if( onClose != null ) + onClose.onClose(c); } public final Object eval(String cmd,Object... args) throws LuanException {
--- a/src/luan/host/Backup.java Mon Sep 24 22:06:25 2018 -0600 +++ b/src/luan/host/Backup.java Tue Sep 25 17:03:57 2018 -0600 @@ -1,9 +1,12 @@ package luan.host; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.Map; +import java.util.List; +import java.util.ArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.lucene.index.SnapshotDeletionPolicy; @@ -64,6 +67,24 @@ luceneInstances = (LuanTable)WebHandler.runLuan( from.getName(), getLucenes, "getLucenes" ); } else { luan = new LuanState(); + luan.onClose = new LuanState.OnClose() { + private final List<Closeable> onClose = new ArrayList<Closeable>(); + + public void onClose(Closeable c) { + onClose.add(c); + } + + public void close() { + for( Closeable c : onClose ) { + try { + c.close(); + } catch(IOException e) { + logger.error(c.toString(),e); + } + } + onClose.clear(); + } + }; WebHandler.initLuan( luan, from.toString(), from.getName() ); PackageLuan.load(luan,"site:/init.luan"); luceneInstances = (LuanTable)luan.eval(getLucenes); @@ -92,7 +113,7 @@ } } if( luan != null ) - luan.close(); + luan.onClose.close(); } public static void backup(File sitesDir,File backupDir) throws IOException {
--- a/src/luan/host/WebHandler.java Mon Sep 24 22:06:25 2018 -0600 +++ b/src/luan/host/WebHandler.java Tue Sep 25 17:03:57 2018 -0600 @@ -32,12 +32,10 @@ private static final Logger logger = LoggerFactory.getLogger(WebHandler.class); private static class LuanRef { - private final LuanState luan; private final Handler handler; private final LuanHandler luanHandler; - private LuanRef(LuanState luan,Handler handler,LuanHandler luanHandler) { - this.luan = luan; + private LuanRef(Handler handler,LuanHandler luanHandler) { this.handler = handler; this.luanHandler = luanHandler; } @@ -46,11 +44,11 @@ private static final ReferenceQueue<LuanRef> queue = new ReferenceQueue<LuanRef>(); private static class MyReference extends SoftReference<LuanRef> { - private LuanState luan; + private LuanHandler luanHandler; private MyReference(LuanRef lr) { super(lr,queue); - this.luan = lr.luan; + this.luanHandler = lr.luanHandler; } } @@ -60,8 +58,8 @@ if( ref == null ) return; //logger.info("sweep"); - ref.luan.close(); - ref.luan = null; + ref.luanHandler.close(); + ref.luanHandler = null; } } @@ -175,7 +173,7 @@ String logDir = dir + "/site/private/local/logs/web"; new File(logDir).mkdirs(); - return new LuanRef(luan,handler,luanHandler); + return new LuanRef(handler,luanHandler); } public static void removeHandler(String domain) throws Exception { @@ -183,7 +181,7 @@ Reference<LuanRef> ref = siteMap.remove(domain); LuanRef lr = ref==null ? null : ref.get(); if( lr != null ) { - lr.luan.close(); + lr.luanHandler.close(); } } }
--- a/src/luan/modules/http/LuanHandler.java Mon Sep 24 22:06:25 2018 -0600 +++ b/src/luan/modules/http/LuanHandler.java Tue Sep 25 17:03:57 2018 -0600 @@ -4,8 +4,14 @@ import java.io.Writer; import java.io.PrintWriter; import java.io.IOException; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.net.BindException; +import java.util.List; +import java.util.ArrayList; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import luan.webserver.Request; @@ -24,10 +30,114 @@ import luan.modules.BasicLuan; -public final class LuanHandler implements Handler, Closeable { +public final class LuanHandler implements Handler { + + private class Instance implements LuanState.OnClose { + private final List<Reference<Closeable>> onClose; + private final LuanState luan; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + + Instance() { + onClose = new ArrayList<Reference<Closeable>>(); + LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); + luan = (LuanState)cloner.clone(luanInit); + luan.onClose = this; + try { + PackageLuan.load(luan,"site:/init.luan"); + } catch(LuanException e) { + String err = e.getLuanStackTraceString(); + logger.error(err); + } + } + + Response handle(Request request,String modName) { + Thread thread = Thread.currentThread(); + String oldName = thread.getName(); + thread.setName(request.headers.get("host")+request.path); + lock.readLock().lock(); + try { + return HttpServicer.service(luan,request,modName); + } finally { + lock.readLock().unlock(); + thread.setName(oldName); + } + } + + Object call_rpc(String fnName,Object... args) throws LuanException { + lock.readLock().lock(); + try { + LuanFunction fn; + LuanState luan = this.luan; + synchronized(luan) { + PackageLuan.enableLoad(luan,"luan:Rpc.luan"); + LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan"); + LuanTable fns = (LuanTable)rpc.get(luan,"functions"); + fn = (LuanFunction)fns.get(luan,fnName); + if( fn == null ) + throw new LuanException( "function not found: " + fnName ); + LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); + luan = (LuanState)cloner.clone(luan); + fn = (LuanFunction)cloner.get(fn); + } + return fn.call(luan,args); + } finally { + lock.readLock().unlock(); + } + } + + public Object runLuan(String sourceText,String sourceName) throws LuanException { + lock.readLock().lock(); + try { + LuanFunction fn = Luan.load(sourceText,sourceName); + synchronized(luan) { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); + LuanState luan = (LuanState)cloner.clone(this.luan); + return fn.call(luan); + } + } finally { + lock.readLock().unlock(); + } + } + + 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) { + logger.error(c.toString(),e); + } + } + } + onClose.clear(); + } + } + + Instance cloneInstance() { + synchronized(luan) { + return new Instance(this); + } + } + + private Instance(Instance instance) { + onClose = instance.onClose; + LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); + luan = (LuanState)cloner.clone(instance.luan); + luan.onClose = this; + } + } + private final LuanState luanInit; private final Logger logger; - private volatile LuanState luan; + private volatile Instance instance; private static final Method resetLuanMethod; private static final Method evalInRootMethod; @@ -52,25 +162,13 @@ } catch(LuanException e) { throw new RuntimeException(e); } - setLuan(); - luanInit.onClose(this); + instance = new Instance(); } - +/* public LuanState getLuan() { return luan; } - - private void setLuan() { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - luan = (LuanState)cloner.clone(luanInit); - try { - PackageLuan.load(luan,"site:/init.luan"); - } catch(LuanException e) { - String err = e.getLuanStackTraceString(); - logger.error(err); - } - } - +*/ @Override public Response handle(Request request) { if( request.path.endsWith("/") ) return null; @@ -79,60 +177,39 @@ } Response handle(Request request,String modName) { - Thread thread = Thread.currentThread(); - String oldName = thread.getName(); - thread.setName(request.headers.get("host")+request.path); - try { - return HttpServicer.service(luan,request,modName); - } finally { - thread.setName(oldName); - } + return instance.handle(request,modName); } public void close() { - synchronized(luan) { - luan.close(); - } + instance.close(); } public Object call_rpc(String fnName,Object... args) throws LuanException { - LuanFunction fn; - LuanState luan = this.luan; - synchronized(luan) { - PackageLuan.enableLoad(luan,"luan:Rpc.luan"); - LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan"); - LuanTable fns = (LuanTable)rpc.get(luan,"functions"); - fn = (LuanFunction)fns.get(luan,fnName); - if( fn == null ) - throw new LuanException( "function not found: " + fnName ); - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - luan = (LuanState)cloner.clone(luan); - fn = (LuanFunction)cloner.get(fn); - } - return fn.call(luan,args); + return instance.call_rpc(fnName,args); } public void reset_luan() { - setLuan(); + new Thread() { + public void run() { + instance.lock.writeLock().lock(); + try { + instance.close(); + instance = new Instance(); + } finally { + instance.lock.writeLock().unlock(); + } + } + }.start(); } public Object runLuan(String sourceText,String sourceName) throws LuanException { - LuanFunction fn = Luan.load(sourceText,sourceName); - synchronized(luan) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - LuanState luan = (LuanState)cloner.clone(this.luan); - return fn.call(luan); - } + return instance.runLuan(sourceText,sourceName); } public void eval_in_root(String text) throws LuanException { - LuanState luan; - synchronized(this.luan) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - luan = (LuanState)cloner.clone(this.luan); - } - BasicLuan.load(text,"<eval_in_root>",null).call(luan); - this.luan = luan; + Instance newInstance = this.instance.cloneInstance(); + BasicLuan.load(text,"<eval_in_root>",null).call(newInstance.luan); + this.instance = newInstance; } public static void start(Server server) throws Exception {