comparison src/luan/lib/webserver/handlers/DomainHandler.java @ 1401:ef1620aa99cb

fix gc issues
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 16 Sep 2019 22:51:41 -0400
parents 221eedb0f54e
children
comparison
equal deleted inserted replaced
1400:221eedb0f54e 1401:ef1620aa99cb
1 package luan.lib.webserver.handlers; 1 package luan.lib.webserver.handlers;
2 2
3 import java.io.Closeable; 3 import java.io.Closeable;
4 import java.io.IOException; 4 import java.io.IOException;
5 import java.lang.ref.Reference; 5 import java.lang.ref.Reference;
6 import java.lang.ref.WeakReference; 6 //import java.lang.ref.WeakReference;
7 import java.lang.ref.SoftReference; 7 import java.lang.ref.SoftReference;
8 import java.lang.ref.ReferenceQueue; 8 import java.lang.ref.ReferenceQueue;
9 import java.util.Map; 9 import java.util.Map;
10 import java.util.HashMap; 10 import java.util.HashMap;
11 import luan.lib.logging.Logger; 11 import luan.lib.logging.Logger;
20 20
21 public interface Factory { 21 public interface Factory {
22 public Handler newHandler(String domain); 22 public Handler newHandler(String domain);
23 } 23 }
24 24
25 private static class Ref {
26 private final Handler handler;
27
28 private Ref(Handler handler) {
29 this.handler = handler;
30 }
31 }
32
33 private final ReferenceQueue<Ref> queue = new ReferenceQueue<Ref>();
34
35 private class MyReference extends WeakReference<Ref> {
36 private Handler handler;
37
38 private MyReference(Ref r) {
39 super(r,queue);
40 this.handler = r.handler;
41 }
42 }
43
44 private static void close(Handler handler) { 25 private static void close(Handler handler) {
45 if( handler instanceof Closeable ) { 26 if( handler instanceof Closeable ) {
46 try { 27 try {
47 ((Closeable)handler).close(); 28 ((Closeable)handler).close();
48 } catch(IOException e) { 29 } catch(IOException e) {
49 logger.error(handler.toString(),e); 30 logger.error(handler.toString(),e);
50 } 31 }
51 } 32 }
52 } 33 }
53 34
54 private void sweep() { 35 private final Map<String,Reference<Handler>> map = new HashMap<String,Reference<Handler>>();
55 while(true) {
56 MyReference ref = (MyReference)queue.poll();
57 if( ref == null )
58 return;
59 //logger.info("sweep");
60 close(ref.handler);
61 ref.handler = null;
62 }
63 }
64
65 private final Map<String,MyReference> map = new HashMap<String,MyReference>();
66 36
67 private final Factory factory; 37 private final Factory factory;
68 38
69 public DomainHandler(Factory factory) { 39 public DomainHandler(Factory factory) {
70 this.factory = factory; 40 this.factory = factory;
79 Handler handler = getHandler(domain); 49 Handler handler = getHandler(domain);
80 return handler==null ? null : handler.handle(request); 50 return handler==null ? null : handler.handle(request);
81 } 51 }
82 52
83 public Handler getHandler(String domain) { 53 public Handler getHandler(String domain) {
84 Ref r = getRef(domain); 54 domain = domain.toLowerCase();
85 return r==null ? null : r.handler; 55 synchronized(map) {
56 Reference<Handler> ref = map.get(domain);
57 Handler handler = ref==null ? null : ref.get();
58 if( handler == null ) {
59 //if(ref!=null) logger.info("gc "+domain);
60 handler = factory.newHandler(domain);
61 if( handler == null )
62 return null;
63 map.put(domain,new SoftReference<Handler>(handler));
64 }
65 return handler;
66 }
86 } 67 }
87 68
88 public void removeHandler(String domain) { 69 public void removeHandler(String domain) {
70 logger.info("removeHandler "+domain);
89 domain = domain.toLowerCase(); 71 domain = domain.toLowerCase();
90 synchronized(map) { 72 synchronized(map) {
91 Reference<Ref> ref = map.remove(domain); 73 Reference<Handler> ref = map.remove(domain);
92 Ref r = ref==null ? null : ref.get(); 74 Handler handler = ref==null ? null : ref.get();
93 if( r != null ) { 75 if( handler != null ) {
94 close(r.handler); 76 close(handler);
95 } 77 }
96 } 78 }
97 } 79 }
98 80
99 private Ref getRef(String domain) {
100 domain = domain.toLowerCase();
101 synchronized(map) {
102 Reference<Ref> ref = map.get(domain);
103 Ref r = ref==null ? null : ref.get();
104 if( r == null ) {
105 //if(ref!=null) logger.info("gc "+domain);
106 sweep();
107 Handler handler = factory.newHandler(domain);
108 if( handler == null )
109 return null;
110 r = new Ref(handler);
111 map.put(domain,new MyReference(r));
112 }
113 return r;
114 }
115 }
116
117 } 81 }