Mercurial Hosting > luan
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(); |