18
18
*/
19
19
package com .tc .net .protocol .transport ;
20
20
21
+ import com .tc .lang .TCThreadGroup ;
21
22
import org .slf4j .Logger ;
22
23
import org .slf4j .LoggerFactory ;
23
24
24
25
import com .tc .net .core .TCConnection ;
25
26
import com .tc .net .core .TCConnectionManager ;
26
27
import com .tc .util .Assert ;
27
- import com .tc .util .concurrent .SetOnceFlag ;
28
28
import java .net .InetSocketAddress ;
29
29
30
30
import java .util .Iterator ;
31
- import java .util .Timer ;
32
- import java .util .TimerTask ;
33
31
import java .util .concurrent .ConcurrentHashMap ;
34
32
import java .util .concurrent .ConcurrentMap ;
33
+ import java .util .concurrent .Future ;
34
+ import java .util .concurrent .ScheduledExecutorService ;
35
+ import java .util .concurrent .ScheduledThreadPoolExecutor ;
36
+ import java .util .concurrent .TimeUnit ;
35
37
import java .util .concurrent .atomic .AtomicLong ;
36
38
import java .util .function .Supplier ;
37
39
44
46
public class ConnectionHealthCheckerImpl implements ConnectionHealthChecker {
45
47
46
48
private final Logger logger ;
47
- private final Timer monitorThread ;
49
+ private static final ScheduledExecutorService monitorThread = createHealthCheckExecutor () ;
48
50
private final HealthCheckerMonitorThreadEngine monitorThreadEngine ;
49
51
50
- private final SetOnceFlag shutdown = new SetOnceFlag ();
51
- private final SetOnceFlag started = new SetOnceFlag ();
52
+ private Future <?> task ;
52
53
53
54
public ConnectionHealthCheckerImpl (HealthCheckerConfig healthCheckerConfig , TCConnectionManager connManager , Supplier <Boolean > reachable ) {
54
55
Assert .assertNotNull (healthCheckerConfig );
55
56
Assert .eval (healthCheckerConfig .isHealthCheckerEnabled ());
56
57
logger = LoggerFactory .getLogger (ConnectionHealthCheckerImpl .class .getName () + ": "
57
58
+ healthCheckerConfig .getHealthCheckerName ());
58
- monitorThread = new Timer (healthCheckerConfig .getHealthCheckerName () + " - HealthCheck-Timer" , true );
59
59
monitorThreadEngine = getHealthMonitorThreadEngine (healthCheckerConfig , connManager , reachable , logger );
60
60
}
61
+
62
+ private static ScheduledExecutorService createHealthCheckExecutor () {
63
+ ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor (1 , (r ) -> {
64
+ ThreadGroup grp = Thread .currentThread ().getThreadGroup ();
65
+ String id = "" ;
66
+ while (grp instanceof TCThreadGroup ) {
67
+ id = "-" + grp .getName ();
68
+ grp = grp .getParent ();
69
+ }
70
+ Thread t = new Thread (grp , r , "HealthCheck" + id );
71
+ t .setDaemon (true );
72
+ return t ;
73
+ });
74
+ exec .setKeepAliveTime (5 , TimeUnit .SECONDS );
75
+ exec .allowCoreThreadTimeOut (true );
76
+ return exec ;
77
+ }
61
78
62
79
private HealthCheckerMonitorThreadEngine getHealthMonitorThreadEngine (HealthCheckerConfig config ,
63
80
TCConnectionManager connectionManager ,
@@ -69,17 +86,18 @@ private HealthCheckerMonitorThreadEngine getHealthMonitorThreadEngine(HealthChec
69
86
} else {
70
87
stop ();
71
88
connectionManager .asynchCloseAllConnections ();
89
+ connectionManager .closeAllListeners ();
72
90
connectionManager .shutdown ();
73
91
return false ;
74
92
}
75
93
}, logger );
76
94
}
77
95
78
96
@ Override
79
- public void start () {
80
- if (started . attemptSet () && ! shutdown . isSet () ) {
97
+ public synchronized void start () {
98
+ if (task == null ) {
81
99
try {
82
- monitorThread .scheduleAtFixedRate (monitorThreadEngine , 0L , monitorThreadEngine .pingInterval );
100
+ task = monitorThread .scheduleAtFixedRate (monitorThreadEngine , 0L , monitorThreadEngine .pingInterval , TimeUnit . MILLISECONDS );
83
101
} catch (IllegalStateException state ) {
84
102
logger .warn ("HealthChecker cannot start" );
85
103
return ;
@@ -91,22 +109,15 @@ public void start() {
91
109
}
92
110
93
111
@ Override
94
- public void stop () {
95
- if (shutdown .attemptSet ()) {
96
- monitorThreadEngine .stop ();
97
- monitorThread .cancel ();
98
- // don't bother to join the monitorThread here. shutdown should take care of all the
99
- // threads in the thread group
112
+ public synchronized void stop () {
113
+ if (task != null && !task .isCancelled ()) {
114
+ task .cancel (true );
100
115
logger .debug ("HealthChecker STOP requested" );
101
116
} else {
102
117
logger .warn ("HealthChecker STOP already requested" );
103
118
}
104
119
}
105
120
106
- public boolean isRunning () {
107
- return started .isSet () && !shutdown .isSet ();
108
- }
109
-
110
121
@ Override
111
122
public void notifyTransportClosed (MessageTransport transport ) {
112
123
// HealthChecker Ping Thread can anyway determine this in the next probe interval thru mtb.isConnected and remove it
@@ -129,6 +140,7 @@ public void notifyTransportConnectAttempt(MessageTransport transport) {
129
140
130
141
@ Override
131
142
public void notifyTransportConnected (MessageTransport transport ) {
143
+ start ();
132
144
monitorThreadEngine .addConnection (transport );
133
145
}
134
146
@@ -153,7 +165,7 @@ public void notifyTransportReconnectionRejected(MessageTransport transport) {
153
165
// NOP
154
166
}
155
167
156
- static class HealthCheckerMonitorThreadEngine extends TimerTask {
168
+ static class HealthCheckerMonitorThreadEngine implements Runnable {
157
169
private final ConcurrentMap <ConnectionID , MessageTransportBase > connectionMap =
158
170
new ConcurrentHashMap <>();
159
171
private final long pingIdleTime ;
@@ -204,10 +216,6 @@ protected ConnectionHealthCheckerContext getHealthCheckerContext(MessageTranspor
204
216
return new ConnectionHealthCheckerContextImpl (transport , conf , connManager );
205
217
}
206
218
207
- public void stop () {
208
- this .cancel ();
209
- }
210
-
211
219
@ Override
212
220
public void run () {
213
221
// same interval for all connections
0 commit comments