+ protected void run() throws Exception {
+ while (isRunning()) {
+
+ Set<Channel> missingChannels = new HashSet<>();
+ for (Channel channel : channels) {
+ if (joinedChannels.contains(channel) || channelsBeingJoined.contains(channel)) {
+ continue;
+ }
+ if (channelBanManager.isBanned(channel)) {
+ continue;
+ }
+ if (networkConnections.containsKey(channel.network())) {
+ if (networkConnections.get(channel.network()).established()) {
+ missingChannels.add(channel);
+ }
+ }
+ }
+ Set<Network> missingNetworks = missingChannels.stream()
+ .map(Channel::network)
+ .distinct()
+ .filter((network) -> !networkConnections.containsKey(network))
+ .collect(Collectors.toSet());
+
+ if (!missingChannels.isEmpty()) {
+ for (Channel missingChannel : missingChannels) {
+ Network network = missingChannel.network();
+ eventBus.post(new GenericMessage(String.format("Trying to join %s on %s...", missingChannel.name(), network)));
+ try {
+ channelsBeingJoined.add(missingChannel);
+ networkConnections.get(network).joinChannel(missingChannel.name());
+ } catch (IOException ioe1) {
+ logger.warn(String.format("Could not join %s on %s!", missingChannel.name(), network.name()), ioe1);
+ }
+ }
+ } else if (missingNetworks.isEmpty()) {
+ synchronized (syncObject) {
+ try {
+ syncObject.wait(TimeUnit.MINUTES.toMillis(1));
+ } catch (InterruptedException ie1) {
+ /* ignore. */
+ }
+ }
+ continue;
+ }
+
+ Map<Long, Network> timesForNextConnects = new TreeMap<>(missingNetworks.stream()
+ .collect(Collectors.toMap(connectionBackoff::getBackoff, Function.identity(), (network, ignore) -> network)));
+
+ Entry<Long, Network> firstNetwork = timesForNextConnects.entrySet().stream().findFirst().get();
+ if (firstNetwork.getKey() > 0) {
+ eventBus.post(new GenericMessage(String.format("Waiting %d seconds to connect to %s...", TimeUnit.MILLISECONDS.toMinutes(firstNetwork.getKey()), firstNetwork.getValue().name())));
+ synchronized (syncObject) {
+ try {
+ syncObject.wait(firstNetwork.getKey());
+ } catch (InterruptedException ie1) {
+ /* ignore. */
+ }
+ }
+ if (!isRunning()) {
+ break;
+ }
+ }
+
+ connectNetwork(firstNetwork.getValue());
+ }
+ }
+
+ @Override
+ protected void triggerShutdown() {
+ synchronized (syncObject) {
+ syncObject.notifyAll();
+ }