Example usage for java.util.concurrent ScheduledFuture cancel

List of usage examples for java.util.concurrent ScheduledFuture cancel

Introduction

In this page you can find the example usage for java.util.concurrent ScheduledFuture cancel.

Prototype

boolean cancel(boolean mayInterruptIfRunning);

Source Link

Document

Attempts to cancel execution of this task.

Usage

From source file:org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler.java

void handleWebsocketCommand(JsonPushCommand pushCommand) {
    String command = pushCommand.command;
    if (command != null) {
        switch (command) {
        case "PUSH_ACTIVITY":
            handlePushActivity(pushCommand.payload);
            return;
        case "PUSH_DOPPLER_CONNECTION_CHANGE":
        case "PUSH_BLUETOOTH_STATE_CHANGE":
            // refresh data 200ms after last command
            @Nullable
            ScheduledFuture<?> refreshDataDelayed = this.refreshAfterCommandJob;
            if (refreshDataDelayed != null) {
                refreshDataDelayed.cancel(false);
            }//from   ww w  . ja  va 2  s  .  com
            this.refreshAfterCommandJob = scheduler.schedule(this::refreshAfterCommand, 700,
                    TimeUnit.MILLISECONDS);
            break;
        case "PUSH_NOTIFICATION_CHANGE":
            JsonCommandPayloadPushNotificationChange pushPayload = gson.fromJson(pushCommand.payload,
                    JsonCommandPayloadPushNotificationChange.class);
            refreshNotifications(pushPayload);
            break;
        default:
            String payload = pushCommand.payload;
            if (payload != null && StringUtils.isNotEmpty(payload) && payload.startsWith("{")
                    && payload.endsWith("}")) {
                JsonCommandPayloadPushDevice devicePayload = gson.fromJson(payload,
                        JsonCommandPayloadPushDevice.class);
                @Nullable
                DopplerId dopplerId = devicePayload.dopplerId;
                if (dopplerId != null) {
                    handlePushDeviceCommand(dopplerId, command, payload);
                }
            }
            break;
        }
    }
}

From source file:org.openhab.binding.amazonechocontrol.handler.EchoHandler.java

private void stopCurrentNotification() {
    ScheduledFuture<?> currentNotifcationUpdateTimer = this.currentNotifcationUpdateTimer;
    if (currentNotifcationUpdateTimer != null) {
        this.currentNotifcationUpdateTimer = null;
        currentNotifcationUpdateTimer.cancel(true);
    }/* w w w .  j a v  a2 s.  c o m*/
    JsonNotificationResponse currentNotification = this.currentNotification;
    if (currentNotification != null) {
        this.currentNotification = null;
        Connection currentConnection = this.connection;
        if (currentConnection != null) {
            try {
                currentConnection.stopNotification(currentNotification);
            } catch (IOException | URISyntaxException e) {
                logger.warn("Stop notification failed: {}", e);
            }
        }
    }
}

From source file:io.fabric8.kubernetes.client.dsl.internal.RollingUpdater.java

/**
 * Lets wait until there are enough Ready pods of the given RC
 *//*from ww  w . j  a va  2  s. c om*/
private void waitUntilPodsAreReady(final T obj, final String namespace, final int requiredPodCount) {
    final CountDownLatch countDownLatch = new CountDownLatch(1);
    final AtomicInteger podCount = new AtomicInteger(0);

    final Runnable readyPodsPoller = new Runnable() {
        public void run() {
            PodList podList = listSelectedPods(obj);
            int count = 0;
            List<Pod> items = podList.getItems();
            for (Pod item : items) {
                for (PodCondition c : item.getStatus().getConditions()) {
                    if (c.getType().equals("Ready") && c.getStatus().equals("True")) {
                        count++;
                    }
                }
            }
            podCount.set(count);
            if (count == requiredPodCount) {
                countDownLatch.countDown();
            }
        }
    };

    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    ScheduledFuture poller = executor.scheduleWithFixedDelay(readyPodsPoller, 0, 1, TimeUnit.SECONDS);
    ScheduledFuture logger = executor.scheduleWithFixedDelay(new Runnable() {
        @Override
        public void run() {
            LOG.debug("Only {}/{} pod(s) ready for {}: {} in namespace: {} seconds so waiting...",
                    podCount.get(), requiredPodCount, obj.getKind(), obj.getMetadata().getName(), namespace);
        }
    }, 0, loggingIntervalMillis, TimeUnit.MILLISECONDS);
    try {
        countDownLatch.await(rollingTimeoutMillis, TimeUnit.MILLISECONDS);
        executor.shutdown();
    } catch (InterruptedException e) {
        poller.cancel(true);
        logger.cancel(true);
        executor.shutdown();
        LOG.warn(
                "Only {}/{} pod(s) ready for {}: {} in namespace: {}  after waiting for {} seconds so giving up",
                podCount.get(), requiredPodCount, obj.getKind(), obj.getMetadata().getName(), namespace,
                TimeUnit.MILLISECONDS.toSeconds(rollingTimeoutMillis));
    }
}

From source file:org.apache.stratos.cloud.controller.context.CloudControllerContext.java

private void stopTask(ScheduledFuture<?> task) {
    if (task != null) {
        task.cancel(true);
        log.info("Scheduled pod activation watcher task canceled");
    }/* w  ww .java2  s.c  o  m*/
}

From source file:org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection.java

/**
 * The connection process is limited by a timeout, realized with a {@link CompletableFuture}. Cancel that future
 * now, if it exists./*  ww  w  .  j av  a2s .c o  m*/
 */
protected void cancelTimeoutFuture() {
    final ScheduledFuture<?> timeoutFuture = this.timeoutFuture.getAndSet(null);
    if (timeoutFuture != null) {
        timeoutFuture.cancel(false);
    }
}

From source file:com.talis.hadoop.rdf.merge.IndexMergeReducer.java

@Override
public void reduce(LongWritable key, Iterable<Text> value, final Context context)
        throws IOException, InterruptedException {
    Runnable reporter = new Runnable() {
        @Override/* w w w  .  j  av  a2s  .  co  m*/
        public void run() {
            context.progress();
        }
    };
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    ScheduledFuture<?> task = scheduler.scheduleAtFixedRate(reporter, 60, 60, TimeUnit.SECONDS);
    LOG.debug("Scheduled progress reporter, combining index shards");

    FileSystem shardsFs = null;
    for (Text remoteShard : value) {
        Path remote = new Path(remoteShard.toString());
        if (null == shardsFs) {
            shardsFs = FileSystem.get(remote.toUri(), context.getConfiguration());
        }
        LOG.debug("Copying shard from {} to {}", remote, localShards);
        shardsFs.copyToLocalFile(remote, localShards);
        LOG.debug("Copy complete");
    }

    Directory[] shards = getDirectories();
    LOG.debug("About to combine {} shards", shards.length);
    writer.addIndexesNoOptimize(shards);
    LOG.debug("Combined index built, terminating reporter");
    task.cancel(true);

}

From source file:io.druid.indexing.overlord.RemoteTaskRunner.java

/**
 * When a new worker appears, listeners are registered for status changes associated with tasks assigned to
 * the worker. Status changes indicate the creation or completion of a task.
 * The RemoteTaskRunner updates state according to these changes.
 *
 * @param worker contains metadata for a worker that has appeared in ZK
 *
 * @return future that will contain a fully initialized worker
 *///from  www .  j a  v a  2 s. c o m
private ListenableFuture<ZkWorker> addWorker(final Worker worker) {
    log.info("Worker[%s] reportin' for duty!", worker.getHost());

    try {
        ScheduledFuture previousCleanup = removedWorkerCleanups.remove(worker.getHost());
        if (previousCleanup != null) {
            log.info("Cancelling Worker[%s] scheduled task cleanup", worker.getHost());
            previousCleanup.cancel(false);
        }

        final String workerStatusPath = JOINER.join(indexerZkConfig.getStatusPath(), worker.getHost());
        final PathChildrenCache statusCache = pathChildrenCacheFactory.make(cf, workerStatusPath);
        final SettableFuture<ZkWorker> retVal = SettableFuture.create();
        final ZkWorker zkWorker = new ZkWorker(worker, statusCache, jsonMapper);

        // Add status listener to the watcher for status changes
        zkWorker.addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                final String taskId;
                final RemoteTaskRunnerWorkItem taskRunnerWorkItem;
                synchronized (statusLock) {
                    try {
                        switch (event.getType()) {
                        case CHILD_ADDED:
                        case CHILD_UPDATED:
                            taskId = ZKPaths.getNodeFromPath(event.getData().getPath());
                            final TaskStatus taskStatus = jsonMapper.readValue(event.getData().getData(),
                                    TaskStatus.class);

                            log.info("Worker[%s] wrote %s status for task: %s", zkWorker.getWorker().getHost(),
                                    taskStatus.getStatusCode(), taskId);

                            // Synchronizing state with ZK
                            statusLock.notifyAll();

                            final RemoteTaskRunnerWorkItem tmp;
                            if ((tmp = runningTasks.get(taskId)) != null) {
                                taskRunnerWorkItem = tmp;
                            } else {
                                final RemoteTaskRunnerWorkItem newTaskRunnerWorkItem = new RemoteTaskRunnerWorkItem(
                                        taskId, zkWorker.getWorker());
                                final RemoteTaskRunnerWorkItem existingItem = runningTasks.putIfAbsent(taskId,
                                        newTaskRunnerWorkItem);
                                if (existingItem == null) {
                                    log.warn(
                                            "Worker[%s] announced a status for a task I didn't know about, adding to runningTasks: %s",
                                            zkWorker.getWorker().getHost(), taskId);
                                    taskRunnerWorkItem = newTaskRunnerWorkItem;
                                } else {
                                    taskRunnerWorkItem = existingItem;
                                }
                            }

                            if (taskStatus.isComplete()) {
                                taskComplete(taskRunnerWorkItem, zkWorker, taskStatus);
                                runPendingTasks();
                            }
                            break;
                        case CHILD_REMOVED:
                            taskId = ZKPaths.getNodeFromPath(event.getData().getPath());
                            taskRunnerWorkItem = runningTasks.remove(taskId);
                            if (taskRunnerWorkItem != null) {
                                log.info("Task[%s] just disappeared!", taskId);
                                taskRunnerWorkItem
                                        .setResult(TaskStatus.failure(taskRunnerWorkItem.getTaskId()));
                            } else {
                                log.info("Task[%s] went bye bye.", taskId);
                            }
                            break;
                        case INITIALIZED:
                            if (zkWorkers.putIfAbsent(worker.getHost(), zkWorker) == null) {
                                retVal.set(zkWorker);
                            } else {
                                final String message = String.format(
                                        "WTF?! Tried to add already-existing worker[%s]", worker.getHost());
                                log.makeAlert(message).addData("workerHost", worker.getHost())
                                        .addData("workerIp", worker.getIp()).emit();
                                retVal.setException(new IllegalStateException(message));
                            }
                            runPendingTasks();
                        }
                    } catch (Exception e) {
                        log.makeAlert(e, "Failed to handle new worker status")
                                .addData("worker", zkWorker.getWorker().getHost())
                                .addData("znode", event.getData().getPath()).emit();
                    }
                }
            }
        });
        zkWorker.start();
        return retVal;
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}

From source file:org.openhab.binding.amazonechocontrol.handler.EchoHandler.java

@Override
public void handleCommand(ChannelUID channelUID, Command command) {
    try {//from   w ww  .ja v a2 s . c o  m
        int waitForUpdate = 1000;
        boolean needBluetoothRefresh = false;
        String lastKnownBluetoothMAC = this.lastKnownBluetoothMAC;

        ScheduledFuture<?> updateStateJob = this.updateStateJob;
        this.updateStateJob = null;
        if (updateStateJob != null) {
            updateStateJob.cancel(false);
        }

        Connection connection = this.connection;
        if (connection == null) {
            return;
        }
        Device device = this.device;
        if (device == null) {
            return;
        }

        // Player commands
        String channelId = channelUID.getId();
        if (channelId.equals(CHANNEL_PLAYER)) {
            if (command == PlayPauseType.PAUSE || command == OnOffType.OFF) {
                connection.command(device, "{\"type\":\"PauseCommand\"}");
            } else if (command == PlayPauseType.PLAY || command == OnOffType.ON) {
                if (isPaused) {
                    connection.command(device, "{\"type\":\"PlayCommand\"}");
                } else {
                    connection.playMusicVoiceCommand(device, this.musicProviderId, "!");
                    waitForUpdate = 3000;
                }
            } else if (command == NextPreviousType.NEXT) {
                connection.command(device, "{\"type\":\"NextCommand\"}");
            } else if (command == NextPreviousType.PREVIOUS) {
                connection.command(device, "{\"type\":\"PreviousCommand\"}");
            } else if (command == RewindFastforwardType.FASTFORWARD) {
                connection.command(device, "{\"type\":\"ForwardCommand\"}");
            } else if (command == RewindFastforwardType.REWIND) {
                connection.command(device, "{\"type\":\"RewindCommand\"}");
            }
        }
        // Volume commands
        if (channelId.equals(CHANNEL_VOLUME)) {
            if (command instanceof PercentType) {
                PercentType value = (PercentType) command;
                int volume = value.intValue();
                connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + volume
                        + ",\"contentFocusClientId\":\"Default\"}");
            } else if (command == OnOffType.OFF) {
                connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + 0
                        + ",\"contentFocusClientId\":\"Default\"}");
            } else if (command == OnOffType.ON) {
                connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + lastKnownVolume
                        + ",\"contentFocusClientId\":\"Default\"}");
            } else if (command == IncreaseDecreaseType.INCREASE) {
                if (lastKnownVolume < 100) {
                    lastKnownVolume++;
                    updateState(CHANNEL_VOLUME, new PercentType(lastKnownVolume));
                    connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":"
                            + lastKnownVolume + ",\"contentFocusClientId\":\"Default\"}");
                }
            } else if (command == IncreaseDecreaseType.DECREASE) {
                if (lastKnownVolume > 0) {
                    lastKnownVolume--;
                    updateState(CHANNEL_VOLUME, new PercentType(lastKnownVolume));
                    connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":"
                            + lastKnownVolume + ",\"contentFocusClientId\":\"Default\"}");
                }
            }
        }
        // shuffle command
        if (channelId.equals(CHANNEL_SHUFFLE)) {
            if (command instanceof OnOffType) {
                OnOffType value = (OnOffType) command;

                connection.command(device, "{\"type\":\"ShuffleCommand\",\"shuffle\":\""
                        + (value == OnOffType.ON ? "true" : "false") + "\"}");
            }
        }

        // play music command
        if (channelId.equals(CHANNEL_MUSIC_PROVIDER_ID)) {
            if (command instanceof StringType) {
                waitForUpdate = 0;
                String musicProviderId = ((StringType) command).toFullString();
                if (!StringUtils.equals(musicProviderId, this.musicProviderId)) {
                    this.musicProviderId = musicProviderId;
                    if (this.isPlaying) {
                        connection.playMusicVoiceCommand(device, this.musicProviderId, "!");
                        waitForUpdate = 3000;
                    }
                }

            }
        }
        if (channelId.equals(CHANNEL_PLAY_MUSIC_VOICE_COMMAND)) {
            if (command instanceof StringType) {
                String voiceCommand = ((StringType) command).toFullString();
                if (!this.musicProviderId.isEmpty()) {
                    connection.playMusicVoiceCommand(device, this.musicProviderId, voiceCommand);
                    waitForUpdate = 3000;
                    updatePlayMusicVoiceCommand = true;
                }
            }
        }

        // bluetooth commands
        if (channelId.equals(CHANNEL_BLUETOOTH_MAC)) {
            needBluetoothRefresh = true;
            if (command instanceof StringType) {
                String address = ((StringType) command).toFullString();
                if (!address.isEmpty()) {
                    waitForUpdate = 4000;
                }
                connection.bluetooth(device, address);
            }
        }
        if (channelId.equals(CHANNEL_BLUETOOTH)) {
            needBluetoothRefresh = true;
            if (command == OnOffType.ON) {
                waitForUpdate = 4000;
                String bluetoothId = lastKnownBluetoothMAC;
                BluetoothState state = bluetoothState;
                if (state != null && (StringUtils.isEmpty(bluetoothId))) {
                    PairedDevice[] pairedDeviceList = state.pairedDeviceList;
                    if (pairedDeviceList != null) {
                        for (PairedDevice paired : pairedDeviceList) {
                            if (paired == null) {
                                continue;
                            }
                            if (StringUtils.isNotEmpty(paired.address)) {
                                lastKnownBluetoothMAC = paired.address;
                                break;
                            }
                        }
                    }
                }
                if (StringUtils.isNotEmpty(lastKnownBluetoothMAC)) {
                    connection.bluetooth(device, lastKnownBluetoothMAC);
                }
            } else if (command == OnOffType.OFF) {
                connection.bluetooth(device, null);
            }
        }
        if (channelId.equals(CHANNEL_BLUETOOTH_DEVICE_NAME)) {
            needBluetoothRefresh = true;
        }
        // amazon music commands
        if (channelId.equals(CHANNEL_AMAZON_MUSIC_TRACK_ID)) {
            if (command instanceof StringType) {

                String trackId = ((StringType) command).toFullString();
                if (StringUtils.isNotEmpty(trackId)) {
                    waitForUpdate = 3000;
                }
                connection.playAmazonMusicTrack(device, trackId);

            }
        }
        if (channelId.equals(CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID)) {
            if (command instanceof StringType) {

                String playListId = ((StringType) command).toFullString();
                if (StringUtils.isNotEmpty(playListId)) {
                    waitForUpdate = 3000;
                }
                connection.playAmazonMusicPlayList(device, playListId);

            }
        }
        if (channelId.equals(CHANNEL_AMAZON_MUSIC)) {

            if (command == OnOffType.ON) {
                String lastKnownAmazonMusicId = this.lastKnownAmazonMusicId;
                if (StringUtils.isNotEmpty(lastKnownAmazonMusicId)) {
                    waitForUpdate = 3000;
                }
                connection.playAmazonMusicTrack(device, lastKnownAmazonMusicId);
            } else if (command == OnOffType.OFF) {
                connection.playAmazonMusicTrack(device, "");
            }
        }

        // radio commands
        if (channelId.equals(CHANNEL_RADIO_STATION_ID)) {
            if (command instanceof StringType) {
                String stationId = ((StringType) command).toFullString();
                if (StringUtils.isNotEmpty(stationId)) {
                    waitForUpdate = 3000;
                }
                connection.playRadio(device, stationId);
            }
        }
        if (channelId.equals(CHANNEL_RADIO)) {
            if (command == OnOffType.ON) {
                String lastKnownRadioStationId = this.lastKnownRadioStationId;
                if (StringUtils.isNotEmpty(lastKnownRadioStationId)) {
                    waitForUpdate = 3000;
                }
                connection.playRadio(device, lastKnownRadioStationId);
            } else if (command == OnOffType.OFF) {
                connection.playRadio(device, "");
            }
        }

        // notification
        if (channelId.equals(CHANNEL_REMIND)) {
            if (command instanceof StringType) {
                stopCurrentNotification();
                String reminder = ((StringType) command).toFullString();
                if (StringUtils.isNotEmpty(reminder)) {
                    waitForUpdate = 3000;
                    updateRemind = true;
                    currentNotification = connection.notification(device, "Reminder", reminder, null);
                    currentNotifcationUpdateTimer = scheduler.scheduleWithFixedDelay(() -> {
                        updateNotificationTimerState();
                    }, 1, 1, TimeUnit.SECONDS);
                }
            }
        }
        if (channelId.equals(CHANNEL_PLAY_ALARM_SOUND)) {
            if (command instanceof StringType) {
                stopCurrentNotification();
                String alarmSound = ((StringType) command).toFullString();
                if (StringUtils.isNotEmpty(alarmSound)) {
                    waitForUpdate = 3000;
                    updateAlarm = true;
                    String[] parts = alarmSound.split(":", 2);
                    JsonNotificationSound sound = new JsonNotificationSound();
                    if (parts.length == 2) {
                        sound.providerId = parts[0];
                        sound.id = parts[1];
                    } else {
                        sound.providerId = "ECHO";
                        sound.id = alarmSound;
                    }
                    currentNotification = connection.notification(device, "Alarm", null, sound);
                    currentNotifcationUpdateTimer = scheduler.scheduleWithFixedDelay(() -> {
                        updateNotificationTimerState();
                    }, 1, 1, TimeUnit.SECONDS);

                }
            }
        }

        // routine commands
        if (channelId.equals(CHANNEL_TEXT_TO_SPEECH)) {
            if (command instanceof StringType) {
                String text = ((StringType) command).toFullString();
                if (StringUtils.isNotEmpty(text)) {
                    waitForUpdate = 1000;
                    updateTextToSpeech = true;
                    connection.textToSpeech(device, text);
                }
            }
        }
        if (channelId.equals(CHANNEL_START_COMMAND)) {
            if (command instanceof StringType) {
                String commandText = ((StringType) command).toFullString();
                if (StringUtils.isNotEmpty(commandText)) {
                    updateStartCommand = true;
                    if (commandText.startsWith(FLASH_BRIEFING_COMMAND_PREFIX)) {
                        // Handle custom flashbriefings commands
                        String flashbriefing = commandText.substring(FLASH_BRIEFING_COMMAND_PREFIX.length());

                        AccountHandler account = this.account;
                        if (account != null) {
                            for (FlashBriefingProfileHandler flashBriefing : account
                                    .getFlashBriefingProfileHandlers()) {
                                ThingUID flashBriefingId = flashBriefing.getThing().getUID();
                                if (StringUtils.equals(flashBriefing.getThing().getUID().getId(),
                                        flashbriefing)) {
                                    flashBriefing.handleCommand(
                                            new ChannelUID(flashBriefingId, CHANNEL_PLAY_ON_DEVICE),
                                            new StringType(device.serialNumber));
                                    break;
                                }
                            }
                        }
                    } else {
                        // Handle standard commands
                        if (!commandText.startsWith("Alexa.")) {
                            commandText = "Alexa." + commandText + ".Play";
                        }
                        waitForUpdate = 1000;
                        connection.executeSequenceCommand(device, commandText, null);
                    }
                }
            }
        }
        if (channelId.equals(CHANNEL_START_ROUTINE)) {
            if (command instanceof StringType) {
                String utterance = ((StringType) command).toFullString();
                if (StringUtils.isNotEmpty(utterance)) {
                    waitForUpdate = 1000;
                    updateRoutine = true;
                    connection.startRoutine(device, utterance);
                }
            }
        }

        // force update of the state
        this.disableUpdate = true;
        final boolean bluetoothRefresh = needBluetoothRefresh;
        Runnable doRefresh = () -> {
            BluetoothState state = null;
            if (bluetoothRefresh) {
                JsonBluetoothStates states;
                states = connection.getBluetoothConnectionStates();
                state = states.findStateByDevice(device);

            }
            this.disableUpdate = false;
            updateState(device, state);
        };
        if (command instanceof RefreshType) {
            waitForUpdate = 0;
        }
        if (waitForUpdate == 0) {
            doRefresh.run();
        } else {
            this.updateStateJob = scheduler.schedule(doRefresh, waitForUpdate, TimeUnit.MILLISECONDS);
        }
    } catch (IOException | URISyntaxException e) {
        logger.info("handleCommand fails: {}", e);
    }
}

From source file:org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection.java

/**
 * This will establish a connection to the MQTT broker and if successful, notify all
 * publishers and subscribers that the connection has become active. This method will
 * do nothing if there is already an active connection.
 *
 * @return Returns a future that completes with true if already connected or connecting,
 *         completes with false if a connection timeout has happened and completes exceptionally otherwise.
 */// ww  w  .  j  av  a2  s  . co m
public CompletableFuture<Boolean> start() {
    // We don't want multiple concurrent threads to start a connection
    synchronized (this) {
        if (connectionState() != MqttConnectionState.DISCONNECTED) {
            return CompletableFuture.completedFuture(true);
        }

        // Perform the connection attempt
        isConnecting = true;
        connectionObservers.forEach(o -> o.connectionStateChanged(MqttConnectionState.CONNECTING, null));
    }

    // Ensure the reconnect strategy is started
    if (reconnectStrategy != null) {
        reconnectStrategy.start();
    }

    // Close client if there is still one existing
    if (client != null) {
        try {
            client.close();
        } catch (org.eclipse.paho.client.mqttv3.MqttException ignore) {
        }
        client = null;
    }

    CompletableFuture<Boolean> future = connectionCallback.createFuture();

    StringBuilder serverURI = new StringBuilder();
    switch (protocol) {
    case TCP:
        serverURI.append(secure ? "ssl://" : "tcp://");
        break;
    case WEBSOCKETS:
        serverURI.append(secure ? "wss://" : "ws://");
        break;
    default:
        future.completeExceptionally(new ConfigurationException("protocol", "Protocol unknown"));
        return future;
    }
    serverURI.append(host);
    serverURI.append(":");
    serverURI.append(port);

    // Storage
    Path persistencePath = this.persistencePath;
    if (persistencePath == null) {
        persistencePath = Paths.get(ConfigConstants.getUserDataFolder()).resolve("mqtt").resolve(host);
    }
    try {
        persistencePath = Files.createDirectories(persistencePath);
    } catch (IOException e) {
        future.completeExceptionally(new MqttException(e));
        return future;
    }
    MqttDefaultFilePersistence _dataStore = new MqttDefaultFilePersistence(persistencePath.toString());

    // Create the client
    MqttAsyncClient _client;
    try {
        _client = createClient(serverURI.toString(), clientId, _dataStore);
    } catch (org.eclipse.paho.client.mqttv3.MqttException e) {
        future.completeExceptionally(new MqttException(e));
        return future;
    }

    // Assign to object
    this.client = _client;
    this.dataStore = _dataStore;

    // Connect
    _client.setCallback(clientCallback);
    try {
        _client.connect(createMqttOptions(), null, connectionCallback);
        logger.info("Starting MQTT broker connection to '{}' with clientid {} and file store '{}'", host,
                getClientId(), persistencePath);
    } catch (org.eclipse.paho.client.mqttv3.MqttException | ConfigurationException e) {
        future.completeExceptionally(new MqttException(e));
        return future;
    }

    // Connect timeout
    ScheduledExecutorService executor = timeoutExecutor;
    if (executor != null) {
        final ScheduledFuture<?> timeoutFuture = this.timeoutFuture
                .getAndSet(executor.schedule(() -> connectionCallback.onFailure(null, new TimeoutException()),
                        timeout, TimeUnit.MILLISECONDS));
        if (timeoutFuture != null) {
            timeoutFuture.cancel(false);
        }
    }
    return future;
}