1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package davmail.http;
21
22 import org.apache.http.conn.HttpClientConnectionManager;
23 import org.apache.log4j.Logger;
24
25 import java.util.Set;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.ScheduledExecutorService;
29 import java.util.concurrent.ThreadFactory;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.atomic.AtomicInteger;
32
33
34
35
36
37 public class DavMailIdleConnectionEvictor {
38 protected static final Logger LOGGER = Logger.getLogger(DavMailIdleConnectionEvictor.class);
39
40
41 private static final Set<HttpClientConnectionManager> connectionManagers = ConcurrentHashMap.newKeySet();
42
43 private static final long sleepTimeMs = 1000L * 60;
44 private static final long maxIdleTimeMs = 1000L * 60 * 5;
45
46 private static ScheduledExecutorService scheduler = null;
47
48 private static synchronized void initEvictorThread() {
49 if (scheduler == null) {
50 scheduler = Executors.newScheduledThreadPool(1, new ThreadFactory() {
51 final AtomicInteger count = new AtomicInteger();
52 @Override
53 public Thread newThread(Runnable r) {
54 Thread thread = new Thread(r, "PoolEvictor-" + count.getAndIncrement());
55 thread.setDaemon(true);
56 thread.setUncaughtExceptionHandler((t, e) -> LOGGER.error(e.getMessage(), e));
57 return thread;
58 }
59 });
60
61
62 scheduler.scheduleWithFixedDelay(() -> {
63
64 try {
65 for (HttpClientConnectionManager connectionManager : connectionManagers) {
66 try {
67 connectionManager.closeExpiredConnections();
68 if (maxIdleTimeMs > 0) {
69 connectionManager.closeIdleConnections(maxIdleTimeMs, TimeUnit.MILLISECONDS);
70 }
71 } catch (Exception e) {
72 LOGGER.warn("Error closing idle connections on manager: " + e.getMessage(), e);
73 }
74 }
75 } catch (Throwable t) {
76 LOGGER.error("Unexpected error in connection pool evictor task", t);
77 }
78 }, sleepTimeMs, sleepTimeMs, TimeUnit.MILLISECONDS);
79 }
80 }
81
82
83
84
85
86 public static synchronized void shutdown() throws InterruptedException {
87 if (scheduler != null) {
88 scheduler.shutdown();
89 if (!scheduler.awaitTermination(sleepTimeMs, TimeUnit.MILLISECONDS)) {
90 LOGGER.warn("Timed out waiting for tasks to complete");
91 }
92
93 connectionManagers.clear();
94 scheduler = null;
95 }
96 }
97
98
99
100
101
102 public static void addConnectionManager(HttpClientConnectionManager connectionManager) {
103 if (connectionManager != null) {
104 initEvictorThread();
105 connectionManagers.add(connectionManager);
106 }
107 }
108
109
110
111
112
113 public static void removeConnectionManager(HttpClientConnectionManager connectionManager) {
114 if (connectionManager != null) {
115 connectionManagers.remove(connectionManager);
116 }
117 }
118 }