comparison src/luan/modules/http/LuanHandler.java @ 1265:3f4644246e39

LuanHandler cleanup and add Server.serve_for_proxy
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 25 Sep 2018 19:51:34 -0600
parents d41997776788
children 9fa8b8389578
comparison
equal deleted inserted replaced
1264:d41997776788 1265:3f4644246e39
14 import java.util.concurrent.locks.ReentrantReadWriteLock; 14 import java.util.concurrent.locks.ReentrantReadWriteLock;
15 import org.slf4j.Logger; 15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory; 16 import org.slf4j.LoggerFactory;
17 import luan.webserver.Request; 17 import luan.webserver.Request;
18 import luan.webserver.Response; 18 import luan.webserver.Response;
19 import luan.webserver.Status;
19 import luan.webserver.Server; 20 import luan.webserver.Server;
20 import luan.webserver.Handler; 21 import luan.webserver.Handler;
21 import luan.webserver.ResponseOutputStream; 22 import luan.webserver.ResponseOutputStream;
22 import luan.Luan; 23 import luan.Luan;
23 import luan.LuanState; 24 import luan.LuanState;
28 import luan.LuanException; 29 import luan.LuanException;
29 import luan.modules.PackageLuan; 30 import luan.modules.PackageLuan;
30 import luan.modules.BasicLuan; 31 import luan.modules.BasicLuan;
31 32
32 33
33 public final class LuanHandler implements Handler { 34 public final class LuanHandler implements Handler, LuanState.OnClose {
34
35 private class Instance implements LuanState.OnClose {
36 private final List<Reference<Closeable>> onClose;
37 private final LuanState luan;
38 private final ReadWriteLock lock = new ReentrantReadWriteLock();
39
40 Instance() {
41 onClose = new ArrayList<Reference<Closeable>>();
42 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
43 luan = (LuanState)cloner.clone(luanInit);
44 luan.onClose = this;
45 try {
46 PackageLuan.load(luan,"site:/init.luan");
47 } catch(LuanException e) {
48 String err = e.getLuanStackTraceString();
49 logger.error(err);
50 }
51 }
52
53 Response handle(Request request,String modName) {
54 Thread thread = Thread.currentThread();
55 String oldName = thread.getName();
56 thread.setName(request.headers.get("host")+request.path);
57 lock.readLock().lock();
58 try {
59 return HttpServicer.service(luan,request,modName);
60 } finally {
61 lock.readLock().unlock();
62 thread.setName(oldName);
63 }
64 }
65
66 Object call_rpc(String fnName,Object... args) throws LuanException {
67 lock.readLock().lock();
68 try {
69 LuanFunction fn;
70 LuanState luan = this.luan;
71 synchronized(luan) {
72 PackageLuan.enableLoad(luan,"luan:Rpc.luan");
73 LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan");
74 LuanTable fns = (LuanTable)rpc.get(luan,"functions");
75 fn = (LuanFunction)fns.get(luan,fnName);
76 if( fn == null )
77 throw new LuanException( "function not found: " + fnName );
78 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
79 luan = (LuanState)cloner.clone(luan);
80 fn = (LuanFunction)cloner.get(fn);
81 }
82 return fn.call(luan,args);
83 } finally {
84 lock.readLock().unlock();
85 }
86 }
87
88 public Object runLuan(String sourceText,String sourceName) throws LuanException {
89 lock.readLock().lock();
90 try {
91 LuanFunction fn = Luan.load(sourceText,sourceName);
92 synchronized(luan) {
93 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
94 LuanState luan = (LuanState)cloner.clone(this.luan);
95 return fn.call(luan);
96 }
97 } finally {
98 lock.readLock().unlock();
99 }
100 }
101
102 public void onClose(Closeable c) {
103 synchronized(onClose) {
104 onClose.add(new WeakReference<Closeable>(c));
105 }
106 }
107
108 public void close() {
109 synchronized(onClose) {
110 for( Reference<Closeable> ref : onClose ) {
111 Closeable c = ref.get();
112 if( c != null ) {
113 try {
114 c.close();
115 } catch(IOException e) {
116 logger.error(c.toString(),e);
117 }
118 }
119 }
120 onClose.clear();
121 }
122 }
123
124 Instance cloneInstance() {
125 synchronized(luan) {
126 return new Instance(this);
127 }
128 }
129
130 private Instance(Instance instance) {
131 onClose = instance.onClose;
132 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
133 luan = (LuanState)cloner.clone(instance.luan);
134 luan.onClose = this;
135 }
136 }
137
138 private final LuanState luanInit; 35 private final LuanState luanInit;
139 private final Logger logger; 36 private final Logger logger;
140 private volatile Instance instance; 37 private final ReadWriteLock lock = new ReentrantReadWriteLock();
38 private final List<Reference<Closeable>> onClose = new ArrayList<Reference<Closeable>>();
39 private volatile LuanState currentLuan;
141 40
142 private static final Method resetLuanMethod; 41 private static final Method resetLuanMethod;
143 private static final Method evalInRootMethod; 42 private static final Method evalInRootMethod;
144 static { 43 static {
145 try { 44 try {
160 Http.rawPut( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) ); 59 Http.rawPut( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) );
161 Http.rawPut( "eval_in_root", new LuanJavaFunction(evalInRootMethod,this) ); 60 Http.rawPut( "eval_in_root", new LuanJavaFunction(evalInRootMethod,this) );
162 } catch(LuanException e) { 61 } catch(LuanException e) {
163 throw new RuntimeException(e); 62 throw new RuntimeException(e);
164 } 63 }
165 instance = new Instance(); 64 currentLuan = newLuan();
166 } 65 }
66
67 private LuanState newLuan() {
68 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
69 LuanState luan = (LuanState)cloner.clone(luanInit);
70 luan.onClose = this;
71 try {
72 PackageLuan.load(luan,"site:/init.luan");
73 } catch(LuanException e) {
74 String err = e.getLuanStackTraceString();
75 logger.error(err);
76 }
77 return luan;
78 }
79
167 /* 80 /*
168 public LuanState getLuan() { 81 public LuanState getLuan() {
169 return luan; 82 return luan;
170 } 83 }
171 */ 84 */
175 String modName = "site:" + request.path +".luan"; 88 String modName = "site:" + request.path +".luan";
176 return handle(request,modName); 89 return handle(request,modName);
177 } 90 }
178 91
179 Response handle(Request request,String modName) { 92 Response handle(Request request,String modName) {
180 return instance.handle(request,modName); 93 Thread thread = Thread.currentThread();
94 String oldName = thread.getName();
95 thread.setName(request.headers.get("host")+request.path);
96 lock.readLock().lock();
97 try {
98 return HttpServicer.service(currentLuan,request,modName);
99 } catch(LuanException e) {
100 String err = e.getLuanStackTraceString();
101 logger.error(err+"\n"+request.rawHead.trim()+"\n");
102 String msg = "Internel Server Error\n\n" + err;
103 return Response.errorResponse( Status.INTERNAL_SERVER_ERROR, msg );
104 } finally {
105 lock.readLock().unlock();
106 thread.setName(oldName);
107 }
108 }
109
110 public void onClose(Closeable c) {
111 synchronized(onClose) {
112 onClose.add(new WeakReference<Closeable>(c));
113 }
181 } 114 }
182 115
183 public void close() { 116 public void close() {
184 instance.close(); 117 synchronized(onClose) {
118 for( Reference<Closeable> ref : onClose ) {
119 Closeable c = ref.get();
120 if( c != null ) {
121 try {
122 c.close();
123 } catch(IOException e) {
124 logger.error(c.toString(),e);
125 }
126 }
127 }
128 onClose.clear();
129 }
185 } 130 }
186 131
187 public Object call_rpc(String fnName,Object... args) throws LuanException { 132 public Object call_rpc(String fnName,Object... args) throws LuanException {
188 return instance.call_rpc(fnName,args); 133 lock.readLock().lock();
134 try {
135 LuanFunction fn;
136 LuanState luan = currentLuan;
137 synchronized(luan) {
138 PackageLuan.enableLoad(luan,"luan:Rpc.luan");
139 LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan");
140 LuanTable fns = (LuanTable)rpc.get(luan,"functions");
141 fn = (LuanFunction)fns.get(luan,fnName);
142 if( fn == null )
143 throw new LuanException( "function not found: " + fnName );
144 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
145 luan = (LuanState)cloner.clone(luan);
146 fn = (LuanFunction)cloner.get(fn);
147 }
148 return fn.call(luan,args);
149 } finally {
150 lock.readLock().unlock();
151 }
189 } 152 }
190 153
191 public void reset_luan() { 154 public void reset_luan() {
192 new Thread() { 155 new Thread() {
193 public void run() { 156 public void run() {
194 instance.lock.writeLock().lock(); 157 lock.writeLock().lock();
195 try { 158 try {
196 instance.close(); 159 close();
197 instance = new Instance(); 160 currentLuan = newLuan();
198 } finally { 161 } finally {
199 instance.lock.writeLock().unlock(); 162 lock.writeLock().unlock();
200 } 163 }
201 } 164 }
202 }.start(); 165 }.start();
203 } 166 }
204 167
205 public Object runLuan(String sourceText,String sourceName) throws LuanException { 168 public Object runLuan(String sourceText,String sourceName) throws LuanException {
206 return instance.runLuan(sourceText,sourceName); 169 lock.readLock().lock();
170 try {
171 LuanFunction fn = Luan.load(sourceText,sourceName);
172 LuanState luan = currentLuan;
173 synchronized(luan) {
174 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
175 LuanState luan2 = (LuanState)cloner.clone(luan);
176 return fn.call(luan2);
177 }
178 } finally {
179 lock.readLock().unlock();
180 }
207 } 181 }
208 182
209 public void eval_in_root(String text) throws LuanException { 183 public void eval_in_root(String text) throws LuanException {
210 Instance newInstance = this.instance.cloneInstance(); 184 LuanState oldLuan = currentLuan;
211 BasicLuan.load(text,"<eval_in_root>",null).call(newInstance.luan); 185 LuanState luan;
212 this.instance = newInstance; 186 synchronized(oldLuan) {
187 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
188 luan = (LuanState)cloner.clone(oldLuan);
189 }
190 luan.onClose = this;
191 BasicLuan.load(text,"<eval_in_root>",null).call(luan);
192 currentLuan = luan;
213 } 193 }
214 194
215 public static void start(Server server) throws Exception { 195 public static void start(Server server) throws Exception {
216 try { 196 try {
217 server.start(); 197 server.start();