Example usage for java.util.concurrent ScheduledExecutorService schedule

List of usage examples for java.util.concurrent ScheduledExecutorService schedule

Introduction

In this page you can find the example usage for java.util.concurrent ScheduledExecutorService schedule.

Prototype

public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);

Source Link

Document

Submits a value-returning one-shot task that becomes enabled after the given delay.

Usage

From source file:org.openhab.binding.mqtt.generic.ChannelState.java

/**
 * Subscribes to the state topic on the given connection and informs about updates on the given listener.
 *
 * @param connection A broker connection
 * @param scheduler A scheduler to realize the timeout
 * @param timeout A timeout in milliseconds. Can be 0 to disable the timeout and let the future return earlier.
 * @param channelStateUpdateListener An update listener
 * @return A future that completes with true if the subscribing worked, with false if the stateTopic is not set
 *         and exceptionally otherwise.//from  w  w  w  . j a  v  a 2s .co m
 */
public CompletableFuture<@Nullable Void> start(MqttBrokerConnection connection,
        ScheduledExecutorService scheduler, int timeout) {
    if (hasSubscribed) {
        return CompletableFuture.completedFuture(null);
    }

    this.connection = connection;

    if (StringUtils.isBlank(config.stateTopic)) {
        return CompletableFuture.completedFuture(null);
    }

    this.future = new CompletableFuture<>();
    connection.subscribe(config.stateTopic, this).thenRun(() -> {
        hasSubscribed = true;
        logger.debug("Subscribed channel {} to topic: {}", this.channelUID, config.stateTopic);
        if (timeout > 0 && !future.isDone()) {
            this.scheduledFuture = scheduler.schedule(this::receivedOrTimeout, timeout, TimeUnit.MILLISECONDS);
        } else {
            receivedOrTimeout();
        }
    }).exceptionally(this::subscribeFail);
    return future;
}

From source file:org.elasticsearch.client.sniff.SnifferTests.java

public void testTaskCancelling() throws Exception {
    RestClient restClient = mock(RestClient.class);
    HostsSniffer hostsSniffer = mock(HostsSniffer.class);
    Scheduler noOpScheduler = new Scheduler() {
        @Override//w ww  .  j a v  a  2  s .c  o  m
        public Future<?> schedule(Sniffer.Task task, long delayMillis) {
            return null;
        }

        @Override
        public void shutdown() {
        }
    };
    Sniffer sniffer = new Sniffer(restClient, hostsSniffer, noOpScheduler, 0L, 0L);
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    try {
        int numIters = randomIntBetween(50, 100);
        for (int i = 0; i < numIters; i++) {
            Sniffer.Task task = sniffer.new Task(0L);
            TaskWrapper wrapper = new TaskWrapper(task);
            Future<?> future;
            if (rarely()) {
                future = executor.schedule(wrapper, randomLongBetween(0L, 200L), TimeUnit.MILLISECONDS);
            } else {
                future = executor.submit(wrapper);
            }
            Sniffer.ScheduledTask scheduledTask = new Sniffer.ScheduledTask(task, future);
            boolean skip = scheduledTask.skip();
            try {
                assertNull(future.get());
            } catch (CancellationException ignore) {
                assertTrue(future.isCancelled());
            }

            if (skip) {
                //the task was either cancelled before starting, in which case it will never start (thanks to Future#cancel),
                //or skipped, in which case it will run but do nothing (thanks to Task#skip).
                //Here we want to make sure that whenever skip returns true, the task either won't run or it won't do anything,
                //otherwise we may end up with parallel sniffing tracks given that each task schedules the following one. We need to
                // make sure that onFailure takes scheduling over while at the same time ordinary rounds don't go on.
                assertFalse(task.hasStarted());
                assertTrue(task.isSkipped());
                assertTrue(future.isCancelled());
                assertTrue(future.isDone());
            } else {
                //if a future is cancelled when its execution has already started, future#get throws CancellationException before
                //completion. The execution continues though so we use a latch to try and wait for the task to be completed.
                //Here we want to make sure that whenever skip returns false, the task will be completed, otherwise we may be
                //missing to schedule the following round, which means no sniffing will ever happen again besides on failure sniffing.
                assertTrue(wrapper.await());
                //the future may or may not be cancelled but the task has for sure started and completed
                assertTrue(task.toString(), task.hasStarted());
                assertFalse(task.isSkipped());
                assertTrue(future.isDone());
            }
            //subsequent cancel calls return false for sure
            int cancelCalls = randomIntBetween(1, 10);
            for (int j = 0; j < cancelCalls; j++) {
                assertFalse(scheduledTask.skip());
            }
        }
    } finally {
        executor.shutdown();
        executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
    }
}

From source file:org.dc.file.search.ui.DashboardForm.java

private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSearchActionPerformed
    int hopCount = DEFAULT_SEARCH_HOPE_COUNT;
    int timeout = DEFAULT_SEARCH_TIMEOUT_SEC;

    if (advancedSearchEnabled) {
        try {//from  ww w. j av  a2  s  .  c om
            hopCount = Integer.parseInt(txtHopCount.getText());
            timeout = Integer.parseInt(txtTimeoutSec.getText());
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, "Default search options will be used",
                    "Invalid Search Options!", JOptionPane.ERROR_MESSAGE);
        }
    }

    Store store = Store.getInstance();
    String key = txtSearchKey.getText();
    Peer localPeer = store.getLocalPeer();
    SearchRequest searchRequest = new SearchRequest(Calendar.getInstance().getTimeInMillis(), key, hopCount,
            localPeer);
    store.setMySearchRequest(searchRequest);
    store.addSearchRequest(searchRequest);
    store.setSearchResults(new ArrayList<>());
    List<DFile> results = Store.getInstance().findInFiles(searchRequest.getSearchKey());
    if (!results.isEmpty()) {
        SearchResult searchResult = new SearchResult(key, localPeer, 0, results);
        store.addSearchResult(searchResult);
    }
    for (Map.Entry<String, Peer> entry : Store.getInstance().getPeerMap().entrySet()) {
        Peer peer = entry.getValue();
        MessageUtils.sendUDPMessage(peer.getIp(), peer.getPort(),
                MessageType.SER + " " + localPeer.getIp() + " " + localPeer.getPort() + " \"" + key + "\" 2");
    }
    Runnable resultTask = () -> {
        try {
            List<SearchResult> searchResults = Store.getInstance().getSearchResults();
            resultFiles = new HashMap<>();
            if (searchResults != null) {
                DefaultTableModel model = (DefaultTableModel) tblSearchResults.getModel();
                model.setRowCount(0);
                for (int i = 0; i < searchResults.size(); i++) {
                    Object[] data = new Object[MAX_COLS];
                    SearchResult searchResult = searchResults.get(i);
                    Peer peer = searchResult.getPeerWithResults();
                    data[0] = peer.getKey();
                    data[1] = searchResult.getHopCount();
                    for (DFile dFile : searchResult.getResults()) {
                        data[2] = dFile.getFileName();
                        data[3] = new StarRater(5, dFile.getTotalRating(), 0);
                        resultFiles.put(dFile.getFileName(), dFile);
                        model.addRow(data);
                    }
                }
                tblSearchResults.setModel(model);
                model.fireTableDataChanged();
            }
        } catch (Throwable t) {
            System.out.println(t.getMessage());
        } finally {
            btnSearch.setEnabled(true);
        }
    };
    initSearchResultsTable();
    initCommentResultsTable();
    btnSearch.setEnabled(false);
    tblSearchResults.setVisible(true);
    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    scheduler.schedule(resultTask, timeout, TimeUnit.SECONDS);
    resetAndStartProgress(timeout);
}

From source file:org.igov.service.business.dfs.DfsService.java

protected void saveServiceMessage_EncryptedFile(String sHead, String sBody, byte[] aByte, String sID_Order,
        String sMail, String sFileName, String sFileContentType) {

    final Map<String, String> mParam = new HashMap<>();
    mParam.put("sHead", sHead);//" ?"
    mParam.put("sBody", sBody);
    mParam.put("sID_Order", sID_Order);
    mParam.put("sMail", sMail);
    mParam.put("sFileName", sFileName);
    mParam.put("sFileContentType", sFileContentType);
    mParam.put("nID_SubjectMessageType", "" + 12L);
    mParam.put("sID_DataLinkSource", "Region");
    mParam.put("sID_DataLinkAuthor", "SFS");
    String sID_DataLink;/*www .j  a v a  2 s .  c  o  m*/
    sID_DataLink = durableBytesDataStorage.saveData(aByte); //sBody.getBytes(Charset.forName("UTF-8"))
    mParam.put("sID_DataLink", sID_DataLink);

    mParam.put("RequestMethod", RequestMethod.GET.name());

    LOG.info("ToJournal-PROCESS mParam=" + mParam);

    ScheduledExecutorService oScheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    Runnable oRunnable = new Runnable() {

        @Override
        public void run() {
            LOG.info("try to save service message with params with a delay: (params={})", mParam);
            String jsonServiceMessage;
            try {
                jsonServiceMessage = historyEventService.addServiceMessage(mParam);
                LOG.info("(jsonServiceMessage={})", jsonServiceMessage);
            } catch (Exception e) {
                LOG.error("( saveServiceMessage error={})", e.getMessage());
            }
        }
    };
    // run saving message in 10 seconds so history event will be in the
    // database already by that time
    oScheduledExecutorService.schedule(oRunnable, 10, TimeUnit.SECONDS);
    oScheduledExecutorService.shutdown();

    LOG.info("Configured thread to run in 10 seconds with params: (params={})", mParam);
}

From source file:org.openhab.io.transport.modbus.internal.ModbusManagerImpl.java

@Override
public ScheduledFuture<?> submitOneTimePoll(PollTask task) {
    ScheduledExecutorService executor = scheduledThreadPoolExecutor;
    Objects.requireNonNull(executor, "Not activated!");
    long scheduleTime = System.currentTimeMillis();
    logger.debug("Scheduling one-off poll task {}", task);
    ScheduledFuture<?> future = executor.schedule(() -> {
        long millisInThreadPoolWaiting = System.currentTimeMillis() - scheduleTime;
        logger.debug("Will now execute one-off poll task {}, waited in thread pool for {}", task,
                millisInThreadPoolWaiting);
        executeOperation(task, true, pollOperation);
    }, 0L, TimeUnit.MILLISECONDS);
    return future;
}

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  . jav  a  2s .  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;
}

From source file:org.openhab.io.transport.modbus.internal.ModbusManagerImpl.java

@Override
public ScheduledFuture<?> submitOneTimeWrite(WriteTask task) {
    ScheduledExecutorService scheduledThreadPoolExecutor = this.scheduledThreadPoolExecutor;
    Objects.requireNonNull(scheduledThreadPoolExecutor, "Not activated!");
    long scheduleTime = System.currentTimeMillis();
    logger.debug("Scheduling one-off write task {}", task);
    ScheduledFuture<?> future = scheduledThreadPoolExecutor.schedule(() -> {
        long millisInThreadPoolWaiting = System.currentTimeMillis() - scheduleTime;
        logger.debug("Will now execute one-off write task {}, waited in thread pool for {}", task,
                millisInThreadPoolWaiting);
        executeOperation(task, true, writeOperation);
    }, 0L, TimeUnit.MILLISECONDS);
    return future;
}

From source file:org.wso2.andes.kernel.slot.SlotManagerClusterMode.java

/**
 * Recover any messages that are persisted but not notified to the slot coordinator from killed nodes.
 * <p>/*from w  ww . ja va2  s .c  o m*/
 * For instance if a node get killed after persisting messages but before submitting slots,
 * until another message is published to any remaining node a new slot will not be created.
 * Hence these messages will not get delivered until another message is published.
 * <p>
 * Recover mechanism here will schedule tasks for each queue so that if no message get received within the
 * given time period that queue slot manager will create a slot and capture those messages it self.
 *
 * @param deletedNodeId node id of delete node
 */
public void deletePublisherNode(final String deletedNodeId) {

    int threadPoolCount = 1; // Single thread is suffice for this task
    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("RecoverSlotsThreadPool")
            .build();
    ScheduledExecutorService recoverSlotScheduler = Executors.newScheduledThreadPool(threadPoolCount,
            namedThreadFactory);

    // this is accessed from another thread therefore using a set that supports concurrency

    Set<String> concurrentSet;

    try {
        concurrentSet = Collections
                .newSetFromMap(new ConcurrentHashMap<String, Boolean>(slotAgent.getAllQueues().size()));
        concurrentSet.addAll(slotAgent.getAllQueues());
        queuesToRecover = concurrentSet;
    } catch (AndesException ex) {
        log.error("Failed to get all queue names", ex);
    }

    recoverSlotScheduler.schedule(new Runnable() {
        @Override
        public void run() {

            try {
                long lastId = SlotMessageCounter.getInstance().getCurrentNodeSafeZoneId();
                //TODO: Delete if the queue has not progressed
                for (String queueName : queuesToRecover) {
                    // Trigger a submit slot for each queue so that new slots are created
                    // for queues that have not published any messages after a node crash
                    try {
                        updateMessageID(queueName, deletedNodeId, lastId - 1, lastId, lastId);
                    } catch (AndesException ex) {
                        log.error("Failed to update message id", ex);
                    }
                }
                slotRecoveryScheduled.set(false);
                try {
                    if (log.isDebugEnabled()) {
                        log.debug("Removing " + deletedNodeId + " from safe zone calculation.");
                    }
                    slotAgent.removePublisherNode(deletedNodeId);
                } catch (AndesException e) {
                    log.error("Failed to remove publisher node ID from safe zone calculation", e);
                }

            } catch (Throwable e) {
                log.error("Error occurred while trying to run recover slot scheduler", e);
            }
        }
    }, SlotMessageCounter.getInstance().SLOT_SUBMIT_TIMEOUT, TimeUnit.MILLISECONDS);

    slotRecoveryScheduled.set(true);

}

From source file:org.apache.hadoop.hive.serde2.objectinspector.TestReflectionObjectInspectors.java

public void testObjectInspectorThreadSafety() throws InterruptedException {
    final int workerCount = 5; // 5 workers to run getReflectionObjectInspector concurrently
    final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(workerCount);
    final MutableObject exception = new MutableObject();
    Thread runner = new Thread(new Runnable() {
        @Override/*from   w ww.  ja va2s  .  com*/
        @SuppressWarnings("unchecked")
        public void run() {
            Future<ObjectInspector>[] results = (Future<ObjectInspector>[]) new Future[workerCount];
            ObjectPair<Type, ObjectInspectorFactory.ObjectInspectorOptions>[] types = (ObjectPair<Type, ObjectInspectorFactory.ObjectInspectorOptions>[]) new ObjectPair[] {
                    new ObjectPair<Type, ObjectInspectorFactory.ObjectInspectorOptions>(Complex.class,
                            ObjectInspectorFactory.ObjectInspectorOptions.THRIFT),
                    new ObjectPair<Type, ObjectInspectorFactory.ObjectInspectorOptions>(MyStruct.class,
                            ObjectInspectorFactory.ObjectInspectorOptions.JAVA), };
            try {
                for (int i = 0; i < 20; i++) { // repeat 20 times
                    for (final ObjectPair<Type, ObjectInspectorFactory.ObjectInspectorOptions> t : types) {
                        ObjectInspectorFactory.objectInspectorCache.clear();
                        for (int k = 0; k < workerCount; k++) {
                            results[k] = executorService.schedule(new Callable<ObjectInspector>() {
                                @Override
                                public ObjectInspector call() throws Exception {
                                    return ObjectInspectorFactory.getReflectionObjectInspector(t.getFirst(),
                                            t.getSecond());
                                }
                            }, 50, TimeUnit.MILLISECONDS);
                        }
                        ObjectInspector oi = results[0].get();
                        for (int k = 1; k < workerCount; k++) {
                            assertEquals(oi, results[k].get());
                        }
                    }
                }
            } catch (Throwable e) {
                exception.setValue(e);
            }
        }
    });
    try {
        runner.start();
        long endTime = System.currentTimeMillis() + 300000; // timeout in 5 minutes
        while (runner.isAlive()) {
            if (System.currentTimeMillis() > endTime) {
                runner.interrupt(); // Interrupt the runner thread
                fail("Timed out waiting for the runner to finish");
            }
            runner.join(10000);
        }
        if (exception.getValue() != null) {
            fail("Got exception: " + exception.getValue());
        }
    } finally {
        executorService.shutdownNow();
    }
}

From source file:org.apache.ambari.server.bootstrap.BSRunner.java

@Override
public void run() {

    if (sshHostInfo.getSshKey() == null || sshHostInfo.getSshKey().equals("")) {
        beforeBootStrap(sshHostInfo);/*  w w  w  .  j  a  v  a 2  s . c o  m*/
    }

    String hostString = createHostString(sshHostInfo.getHosts());
    String user = sshHostInfo.getUser();
    String userRunAs = sshHostInfo.getUserRunAs();
    if (user == null || user.isEmpty()) {
        user = DEFAULT_USER;
    }
    String command[] = new String[12];
    BSStat stat = BSStat.RUNNING;
    String scriptlog = "";
    try {
        createRunDir();
        if (LOG.isDebugEnabled()) {
            // FIXME needs to be removed later
            // security hole
            LOG.debug("Using ssh key=\"" + sshHostInfo.getSshKey() + "\"");
        }

        String password = sshHostInfo.getPassword();
        if (password != null && !password.isEmpty()) {
            this.passwordFile = new File(this.requestIdDir, "host_pass");
            // TODO : line separator should be changed
            // if we are going to support multi platform server-agent solution
            String lineSeparator = System.getProperty("line.separator");
            password = password + lineSeparator;
            writePasswordFile(password);
        }

        writeSshKeyFile(sshHostInfo.getSshKey());
        /* Running command:
         * script hostlist bsdir user sshkeyfile
         */
        command[0] = this.bsScript;
        command[1] = hostString;
        command[2] = this.requestIdDir.toString();
        command[3] = user;
        command[4] = this.sshKeyFile.toString();
        command[5] = this.agentSetupScript.toString();
        command[6] = this.ambariHostname;
        command[7] = this.clusterOsFamily;
        command[8] = this.projectVersion;
        command[9] = this.serverPort + "";
        command[10] = userRunAs;
        command[11] = (this.passwordFile == null) ? "null" : this.passwordFile.toString();
        LOG.info("Host= " + hostString + " bs=" + this.bsScript + " requestDir=" + requestIdDir + " user="
                + user + " keyfile=" + this.sshKeyFile + " passwordFile " + this.passwordFile + " server="
                + this.ambariHostname + " version=" + projectVersion + " serverPort=" + this.serverPort
                + " userRunAs=" + userRunAs);

        String[] env = new String[] { "AMBARI_PASSPHRASE=" + agentSetupPassword };
        if (this.verbose)
            env = new String[] { env[0], " BS_VERBOSE=\"-vvv\" " };

        if (LOG.isDebugEnabled()) {
            LOG.debug(Arrays.toString(command));
        }

        String bootStrapOutputFilePath = requestIdDir + File.separator + "bootstrap.out";
        String bootStrapErrorFilePath = requestIdDir + File.separator + "bootstrap.err";

        Process process = Runtime.getRuntime().exec(command, env);

        PrintWriter stdOutWriter = null;
        PrintWriter stdErrWriter = null;

        try {
            stdOutWriter = new PrintWriter(bootStrapOutputFilePath);
            stdErrWriter = new PrintWriter(bootStrapErrorFilePath);
            IOUtils.copy(process.getInputStream(), stdOutWriter);
            IOUtils.copy(process.getErrorStream(), stdErrWriter);
        } finally {
            if (stdOutWriter != null)
                stdOutWriter.close();

            if (stdErrWriter != null)
                stdErrWriter.close();
        }

        // Startup a scheduled executor service to look through the logs
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        BSStatusCollector statusCollector = new BSStatusCollector();
        ScheduledFuture<?> handle = scheduler.scheduleWithFixedDelay(statusCollector, 0, 10, TimeUnit.SECONDS);
        LOG.info("Kicking off the scheduler for polling on logs in " + this.requestIdDir);
        try {

            LOG.info("Bootstrap output, log=" + bootStrapErrorFilePath + " " + bootStrapOutputFilePath);
            int exitCode = process.waitFor();
            String outMesg = "";
            String errMesg = "";
            try {
                outMesg = FileUtils.readFileToString(new File(bootStrapOutputFilePath));
                errMesg = FileUtils.readFileToString(new File(bootStrapErrorFilePath));
            } catch (IOException io) {
                LOG.info("Error in reading files ", io);
            }
            scriptlog = outMesg + "\n\n" + errMesg;
            LOG.info("Script log Mesg " + scriptlog);
            if (exitCode != 0) {
                stat = BSStat.ERROR;
            } else {
                stat = BSStat.SUCCESS;
            }

            scheduler.schedule(new BSStatusCollector(), 0, TimeUnit.SECONDS);
            long startTime = System.currentTimeMillis();
            while (true) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Waiting for hosts status to be updated");
                }
                boolean pendingHosts = false;
                BootStrapStatus tmpStatus = bsImpl.getStatus(requestId);
                List<BSHostStatus> hostStatusList = tmpStatus.getHostsStatus();
                if (hostStatusList != null) {
                    for (BSHostStatus status : hostStatusList) {
                        if (status.getStatus().equals("RUNNING")) {
                            pendingHosts = true;
                        }
                    }
                } else {
                    //Failed to get host status, waiting for hosts status to be updated
                    pendingHosts = true;
                }
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Whether hosts status yet to be updated, pending=" + pendingHosts);
                }
                if (!pendingHosts) {
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // continue
                }
                long now = System.currentTimeMillis();
                if (now >= (startTime + 15000)) {
                    LOG.warn("Gave up waiting for hosts status to be updated");
                    break;
                }
            }
        } catch (InterruptedException e) {
            throw new IOException(e);
        } finally {
            handle.cancel(true);
            /* schedule a last update */
            scheduler.schedule(new BSStatusCollector(), 0, TimeUnit.SECONDS);
            scheduler.shutdownNow();
            try {
                scheduler.awaitTermination(10, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                LOG.info("Interruped while waiting for scheduler");
            }
            process.destroy();
        }
    } catch (IOException io) {
        LOG.info("Error executing bootstrap " + io.getMessage());
        stat = BSStat.ERROR;
    } finally {
        /* get the bstatus */
        BootStrapStatus tmpStatus = bsImpl.getStatus(requestId);
        List<BSHostStatus> hostStatusList = tmpStatus.getHostsStatus();
        if (hostStatusList != null) {
            for (BSHostStatus hostStatus : hostStatusList) {
                if ("FAILED".equals(hostStatus.getStatus())) {
                    stat = BSStat.ERROR;
                    break;
                }
            }
        } else {
            stat = BSStat.ERROR;
        }
        tmpStatus.setLog(scriptlog);
        tmpStatus.setStatus(stat);
        bsImpl.updateStatus(requestId, tmpStatus);
        bsImpl.reset();
        // Remove private ssh key after bootstrap is complete
        try {
            FileUtils.forceDelete(sshKeyFile);
        } catch (IOException io) {
            LOG.warn(io.getMessage());
        }
        if (passwordFile != null) {
            // Remove password file after bootstrap is complete
            try {
                FileUtils.forceDelete(passwordFile);
            } catch (IOException io) {
                LOG.warn(io.getMessage());
            }
        }
        finished();
    }
}