blob: 74fbbd4c329e2bb2bac14595a2f76adb33a3662a [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07002 * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
J. Duke319a3b92007-12-01 00:00:00 +00003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07007 * published by the Free Software Foundation. Oracle designates this
J. Duke319a3b92007-12-01 00:00:00 +00008 * particular file as subject to the "Classpath" exception as provided
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07009 * by Oracle in the LICENSE file that accompanied this code.
J. Duke319a3b92007-12-01 00:00:00 +000010 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
Kelly O'Hairfe008ae2010-05-25 15:58:33 -070021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
J. Duke319a3b92007-12-01 00:00:00 +000024 */
25
26package com.sun.jmx.remote.internal;
27
J. Duke319a3b92007-12-01 00:00:00 +000028
29import com.sun.jmx.remote.util.ClassLogger;
30
31public abstract class ServerCommunicatorAdmin {
32 public ServerCommunicatorAdmin(long timeout) {
33 if (logger.traceOn()) {
34 logger.trace("Constructor",
35 "Creates a new ServerCommunicatorAdmin object "+
36 "with the timeout "+timeout);
37 }
38
39 this.timeout = timeout;
40
41 timestamp = 0;
42 if (timeout < Long.MAX_VALUE) {
43 Runnable timeoutTask = new Timeout();
Chris Hegarty22da92972016-04-18 20:58:19 +010044 final Thread t = new Thread(null,
45 timeoutTask,
46 "JMX-Server-Admin-Timeout",
47 0,
48 false);
J. Duke319a3b92007-12-01 00:00:00 +000049 t.setName("JMX server connection timeout " + t.getId());
50 // If you change this name you will need to change a unit test
51 // (NoServerTimeoutTest)
52 t.setDaemon(true);
53 t.start();
54 }
55 }
56
57 /**
58 * Tells that a new request message is received.
59 * A caller of this method should always call the method
60 * <code>rspOutgoing</code> to inform that a response is sent out
61 * for the received request.
62 * @return the value of the termination flag:
Alexander Stepanov30cda922015-05-19 16:04:14 +040063 * true if the connection is already being terminated,
64 * false otherwise.
J. Duke319a3b92007-12-01 00:00:00 +000065 */
66 public boolean reqIncoming() {
67 if (logger.traceOn()) {
68 logger.trace("reqIncoming", "Receive a new request.");
69 }
70
71 synchronized(lock) {
72 if (terminated) {
73 logger.warning("reqIncoming",
74 "The server has decided to close " +
75 "this client connection.");
76 }
77 ++currentJobs;
78
79 return terminated;
80 }
81 }
82
83 /**
84 * Tells that a response is sent out for a received request.
85 * @return the value of the termination flag:
Alexander Stepanov30cda922015-05-19 16:04:14 +040086 * true if the connection is already being terminated,
87 * false otherwise.
J. Duke319a3b92007-12-01 00:00:00 +000088 */
89 public boolean rspOutgoing() {
90 if (logger.traceOn()) {
91 logger.trace("reqIncoming", "Finish a request.");
92 }
93
94 synchronized(lock) {
95 if (--currentJobs == 0) {
96 timestamp = System.currentTimeMillis();
97 logtime("Admin: Timestamp=",timestamp);
98 // tells the adminor to restart waiting with timeout
99 lock.notify();
100 }
101 return terminated;
102 }
103 }
104
105 /**
106 * Called by this class to tell an implementation to do stop.
107 */
108 protected abstract void doStop();
109
110 /**
111 * Terminates this object.
112 * Called only by outside, so do not need to call doStop
113 */
114 public void terminate() {
115 if (logger.traceOn()) {
116 logger.trace("terminate",
117 "terminate the ServerCommunicatorAdmin object.");
118 }
119
120 synchronized(lock) {
121 if (terminated) {
122 return;
123 }
124
125 terminated = true;
126
127 // tell Timeout to terminate
128 lock.notify();
129 }
130 }
131
132// --------------------------------------------------------------
133// private classes
134// --------------------------------------------------------------
135 private class Timeout implements Runnable {
136 public void run() {
137 boolean stopping = false;
138
139 synchronized(lock) {
140 if (timestamp == 0) timestamp = System.currentTimeMillis();
141 logtime("Admin: timeout=",timeout);
142 logtime("Admin: Timestamp=",timestamp);
143
144 while(!terminated) {
145 try {
146 // wait until there is no more job
147 while(!terminated && currentJobs != 0) {
148 if (logger.traceOn()) {
149 logger.trace("Timeout-run",
150 "Waiting without timeout.");
151 }
152
153 lock.wait();
154 }
155
156 if (terminated) return;
157
158 final long remaining =
159 timeout - (System.currentTimeMillis() - timestamp);
160
161 logtime("Admin: remaining timeout=",remaining);
162
163 if (remaining > 0) {
164
165 if (logger.traceOn()) {
166 logger.trace("Timeout-run",
167 "Waiting with timeout: "+
168 remaining + " ms remaining");
169 }
170
171 lock.wait(remaining);
172 }
173
174 if (currentJobs > 0) continue;
175
176 final long elapsed =
177 System.currentTimeMillis() - timestamp;
178 logtime("Admin: elapsed=",elapsed);
179
180 if (!terminated && elapsed > timeout) {
181 if (logger.traceOn()) {
182 logger.trace("Timeout-run",
183 "timeout elapsed");
184 }
185 logtime("Admin: timeout elapsed! "+
186 elapsed+">",timeout);
187 // stopping
188 terminated = true;
189
190 stopping = true;
191 break;
192 }
193 } catch (InterruptedException ire) {
194 logger.warning("Timeout-run","Unexpected Exception: "+
195 ire);
196 logger.debug("Timeout-run",ire);
197 return;
198 }
199 }
200 }
201
202 if (stopping) {
203 if (logger.traceOn()) {
204 logger.trace("Timeout-run", "Call the doStop.");
205 }
206
207 doStop();
208 }
209 }
210 }
211
212 private void logtime(String desc,long time) {
213 timelogger.trace("synchro",desc+time);
214 }
215
216// --------------------------------------------------------------
217// private variables
218// --------------------------------------------------------------
219 private long timestamp;
220
221 private final int[] lock = new int[0];
222 private int currentJobs = 0;
223
224 private long timeout;
225
226 // state issue
227 private boolean terminated = false;
228
229 private static final ClassLogger logger =
230 new ClassLogger("javax.management.remote.misc",
231 "ServerCommunicatorAdmin");
232 private static final ClassLogger timelogger =
233 new ClassLogger("javax.management.remote.timeout",
234 "ServerCommunicatorAdmin");
235}