|
@@ -81,9 +81,10 @@ import java.util.List;
|
81
|
81
|
import java.util.Map;
|
82
|
82
|
import java.util.Random;
|
83
|
83
|
import java.util.Set;
|
84
|
|
-import java.util.Timer;
|
85
|
|
-import java.util.TimerTask;
|
86
|
84
|
import java.util.concurrent.ConcurrentSkipListMap;
|
|
85
|
+import java.util.concurrent.ScheduledExecutorService;
|
|
86
|
+import java.util.concurrent.ScheduledFuture;
|
|
87
|
+import java.util.concurrent.TimeUnit;
|
87
|
88
|
import java.util.concurrent.locks.ReadWriteLock;
|
88
|
89
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
89
|
90
|
|
|
@@ -138,10 +139,6 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
138
|
139
|
private final Object myStateLock = new Object();
|
139
|
140
|
/** The current state of this server. */
|
140
|
141
|
private final ServerStatus myState = new ServerStatus(this, myStateLock);
|
141
|
|
- /** The timer we're using to delay reconnects. */
|
142
|
|
- private Timer reconnectTimer;
|
143
|
|
- /** The timer we're using to send WHO requests. */
|
144
|
|
- private final Timer whoTimer;
|
145
|
142
|
/** The tabcompleter used for this server. */
|
146
|
143
|
private final TabCompleter tabCompleter;
|
147
|
144
|
/** Our reason for being away, if any. */
|
|
@@ -180,6 +177,12 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
180
|
177
|
private final ConfigProvider userSettings;
|
181
|
178
|
/** The manager to use to add status bar messages. */
|
182
|
179
|
private final StatusBarManager statusBarManager;
|
|
180
|
+ /** Executor service to use to schedule repeated events. */
|
|
181
|
+ private final ScheduledExecutorService executorService;
|
|
182
|
+ /** The future used when a who timer is scheduled. */
|
|
183
|
+ private ScheduledFuture<?> whoTimerFuture;
|
|
184
|
+ /** The future used when a reconnect timer is scheduled. */
|
|
185
|
+ private ScheduledFuture<?> reconnectTimerFuture;
|
183
|
186
|
|
184
|
187
|
/**
|
185
|
188
|
* Creates a new server which will connect to the specified URL with the specified profile.
|
|
@@ -201,6 +204,7 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
201
|
204
|
* @param urlBuilder The URL builder to use when finding icons.
|
202
|
205
|
* @param eventBus The event bus to despatch events onto.
|
203
|
206
|
* @param userSettings The config provider to write user settings to.
|
|
207
|
+ * @param executorService The service to use to schedule events.
|
204
|
208
|
* @param uri The address of the server to connect to
|
205
|
209
|
* @param profile The profile to use
|
206
|
210
|
*/
|
|
@@ -220,6 +224,7 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
220
|
224
|
final URLBuilder urlBuilder,
|
221
|
225
|
final EventBus eventBus,
|
222
|
226
|
@SuppressWarnings("qualifiers") @UserConfig final ConfigProvider userSettings,
|
|
227
|
+ @Unbound final ScheduledExecutorService executorService,
|
223
|
228
|
@Unbound final URI uri,
|
224
|
229
|
@Unbound final ConfigProvider profile) {
|
225
|
230
|
super("server-disconnected",
|
|
@@ -242,6 +247,7 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
242
|
247
|
this.channelFactory = channelFactory;
|
243
|
248
|
this.queryFactory = queryFactory;
|
244
|
249
|
this.rawFactory = rawFactory;
|
|
250
|
+ this.executorService = executorService;
|
245
|
251
|
this.eventBus = eventBus;
|
246
|
252
|
this.userSettings = userSettings;
|
247
|
253
|
this.statusBarManager = statusBarManager;
|
|
@@ -253,17 +259,6 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
253
|
259
|
|
254
|
260
|
updateIcon();
|
255
|
261
|
|
256
|
|
- // TODO: Don't start timers in the constructor!
|
257
|
|
- whoTimer = new Timer("Server Who Timer");
|
258
|
|
- whoTimer.schedule(new TimerTask() {
|
259
|
|
- @Override
|
260
|
|
- public void run() {
|
261
|
|
- for (Channel channel : channels.values()) {
|
262
|
|
- channel.checkWho();
|
263
|
|
- }
|
264
|
|
- }
|
265
|
|
- }, 0, getConfigManager().getOptionInt(DOMAIN_GENERAL, "whotime"));
|
266
|
|
-
|
267
|
262
|
getConfigManager().addChangeListener("formatter", "serverName", this);
|
268
|
263
|
getConfigManager().addChangeListener("formatter", "serverTitle", this);
|
269
|
264
|
}
|
|
@@ -312,7 +307,9 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
312
|
307
|
switch (myState.getState()) {
|
313
|
308
|
case RECONNECT_WAIT:
|
314
|
309
|
log.debug("Cancelling reconnection timer");
|
315
|
|
- reconnectTimer.cancel();
|
|
310
|
+ if (reconnectTimerFuture != null) {
|
|
311
|
+ reconnectTimerFuture.cancel(false);
|
|
312
|
+ }
|
316
|
313
|
break;
|
317
|
314
|
case CLOSING:
|
318
|
315
|
// Ignore the connection attempt
|
|
@@ -418,7 +415,9 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
418
|
415
|
return;
|
419
|
416
|
case RECONNECT_WAIT:
|
420
|
417
|
log.debug("Cancelling reconnection timer");
|
421
|
|
- reconnectTimer.cancel();
|
|
418
|
+ if (reconnectTimerFuture != null) {
|
|
419
|
+ reconnectTimerFuture.cancel(false);
|
|
420
|
+ }
|
422
|
421
|
break;
|
423
|
422
|
default:
|
424
|
423
|
break;
|
|
@@ -473,12 +472,9 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
473
|
472
|
|
474
|
473
|
handleNotification("connectRetry", getAddress(), delay / 1000);
|
475
|
474
|
|
476
|
|
- reconnectTimer = new Timer("Server Reconnect Timer");
|
477
|
|
- reconnectTimer.schedule(new TimerTask() {
|
|
475
|
+ reconnectTimerFuture = executorService.schedule(new Runnable() {
|
478
|
476
|
@Override
|
479
|
477
|
public void run() {
|
480
|
|
- reconnectTimer.cancel();
|
481
|
|
-
|
482
|
478
|
synchronized (myStateLock) {
|
483
|
479
|
log.debug("Reconnect task executing, state: {}",
|
484
|
480
|
myState.getState());
|
|
@@ -488,7 +484,7 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
488
|
484
|
}
|
489
|
485
|
}
|
490
|
486
|
}
|
491
|
|
- }, delay);
|
|
487
|
+ }, delay, TimeUnit.MILLISECONDS);
|
492
|
488
|
|
493
|
489
|
log.info("Scheduling reconnect task for delay of {}", delay);
|
494
|
490
|
|
|
@@ -1036,7 +1032,7 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
1036
|
1032
|
// Remove any callbacks or listeners
|
1037
|
1033
|
eventHandler.unregisterCallbacks();
|
1038
|
1034
|
getConfigManager().removeListener(this);
|
1039
|
|
- whoTimer.cancel();
|
|
1035
|
+ executorService.shutdown();
|
1040
|
1036
|
|
1041
|
1037
|
// Trigger any actions neccessary
|
1042
|
1038
|
disconnect();
|
|
@@ -1201,8 +1197,7 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
1201
|
1197
|
}
|
1202
|
1198
|
|
1203
|
1199
|
ActionManager.getActionManager().triggerEvent(
|
1204
|
|
- CoreActionType.SERVER_NUMERIC, target, this,
|
1205
|
|
- Integer.valueOf(numeric), tokens);
|
|
1200
|
+ CoreActionType.SERVER_NUMERIC, target, this, numeric, tokens);
|
1206
|
1201
|
|
1207
|
1202
|
handleNotification(target.toString(), (Object[]) tokens);
|
1208
|
1203
|
}
|
|
@@ -1213,16 +1208,19 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
1213
|
1208
|
public void onSocketClosed() {
|
1214
|
1209
|
log.info("Received socket closed event, state: {}", myState.getState());
|
1215
|
1210
|
|
|
1211
|
+ if (whoTimerFuture != null) {
|
|
1212
|
+ whoTimerFuture.cancel(false);
|
|
1213
|
+ }
|
|
1214
|
+
|
1216
|
1215
|
if (Thread.holdsLock(myStateLock)) {
|
1217
|
1216
|
log.info("State lock contended: rerunning on a new thread");
|
1218
|
1217
|
|
1219
|
|
- new Thread(new Runnable() {
|
1220
|
|
-
|
|
1218
|
+ executorService.schedule(new Runnable() {
|
1221
|
1219
|
@Override
|
1222
|
1220
|
public void run() {
|
1223
|
1221
|
onSocketClosed();
|
1224
|
1222
|
}
|
1225
|
|
- }, "Socket closed deferred thread").start();
|
|
1223
|
+ }, 0, TimeUnit.SECONDS);
|
1226
|
1224
|
return;
|
1227
|
1225
|
}
|
1228
|
1226
|
|
|
@@ -1360,7 +1358,7 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
1360
|
1358
|
|
1361
|
1359
|
ActionManager.getActionManager().triggerEvent(
|
1362
|
1360
|
CoreActionType.SERVER_NOPING, null, this,
|
1363
|
|
- Long.valueOf(parser.getPingTime()));
|
|
1361
|
+ parser.getPingTime());
|
1364
|
1362
|
|
1365
|
1363
|
if (parser.getPingTime()
|
1366
|
1364
|
>= getConfigManager().getOptionInt(DOMAIN_SERVER, "pingtimeout")) {
|
|
@@ -1407,6 +1405,16 @@ public class Server extends WritableFrameContainer implements ConfigChangeListen
|
1407
|
1405
|
join(requests.toArray(new ChannelJoinRequest[requests.size()]));
|
1408
|
1406
|
|
1409
|
1407
|
checkModeAliases();
|
|
1408
|
+
|
|
1409
|
+ final int whoTime = getConfigManager().getOptionInt(DOMAIN_GENERAL, "whotime");
|
|
1410
|
+ whoTimerFuture = executorService.scheduleAtFixedRate(new Runnable() {
|
|
1411
|
+ @Override
|
|
1412
|
+ public void run() {
|
|
1413
|
+ for (Channel channel : channels.values()) {
|
|
1414
|
+ channel.checkWho();
|
|
1415
|
+ }
|
|
1416
|
+ }
|
|
1417
|
+ }, whoTime, whoTime, TimeUnit.MILLISECONDS);
|
1410
|
1418
|
}
|
1411
|
1419
|
|
1412
|
1420
|
ActionManager.getActionManager().triggerEvent(
|