Example usage for java.util.concurrent TimeUnit toMillis

List of usage examples for java.util.concurrent TimeUnit toMillis

Introduction

In this page you can find the example usage for java.util.concurrent TimeUnit toMillis.

Prototype

public long toMillis(long duration) 

Source Link

Document

Equivalent to #convert(long,TimeUnit) MILLISECONDS.convert(duration, this) .

Usage

From source file:org.sfs.nodes.RemoteMasterNode.java

@Override
public Observable<Void> waitForJob(String jobId, long timeout, TimeUnit timeUnit) {
    return Defer.aVoid().flatMap(aVoid -> nodes.connectFirstAvailable(vertx, hostAndPorts, hostAndPort -> {
        ObservableFuture<HttpClientResponse> handler = RxHelper.observableFuture();

        String url = String.format("http://%s/_internal_node_master_wait_for_job/", hostAndPort.toString());

        HttpClientRequest httpClientRequest = httpClient.postAbs(url, httpClientResponse -> {
            httpClientResponse.pause();/* w ww  .  j a v  a  2  s.c o m*/
            handler.complete(httpClientResponse);
        }).exceptionHandler(handler::fail).putHeader(X_SFS_REMOTE_NODE_TOKEN, remoteNodeSecret)
                .putHeader(JOB_ID, jobId)
                .putHeader(HttpHeaders.TIMEOUT, String.valueOf(timeUnit.toMillis(timeout)))
                .setTimeout(responseTimeout);

        httpClientRequest.end();

        return handler.map(
                httpClientResponse -> new HttpClientRequestAndResponse(httpClientRequest, httpClientResponse));
    })).map(HttpClientRequestAndResponse::getResponse).map(new HttpClientResponseHeaderLogger())
            .flatMap(httpClientResponse -> Defer.just(httpClientResponse)
                    .flatMap(new HttpClientKeepAliveResponseBodyBuffer()).map(new HttpBodyLogger())
                    .map(buffer -> {
                        if (HTTP_OK != httpClientResponse.statusCode()) {
                            throw new HttpClientResponseException(httpClientResponse, buffer);
                        }
                        return buffer;
                    }).map(new BufferToJsonObject()).map(jsonObject -> {
                        Integer code = jsonObject.getInteger("code");
                        if (code != null) {
                            if (HTTP_OK == code) {
                                return jsonObject;
                            } else if (HTTP_CONFLICT == code) {
                                return new Jobs.WaitStoppedExpired();
                            } else if (HTTP_NOT_FOUND == code) {
                                throw new Jobs.JobNotFound();
                            }
                        }
                        throw new HttpClientResponseException(httpClientResponse, jsonObject);
                    }))
            .map(new ToVoid<>());
}

From source file:hd3gtv.mydmam.manager.JobNG.java

public JobNG setExpirationTime(long duration, TimeUnit unit) {
    if (duration < 0) {
        return this;
    }//from   ww w.j a  v a 2s . c  om
    expiration_date = System.currentTimeMillis() + unit.toMillis(duration);
    return this;
}

From source file:org.openspaces.grid.gsm.machines.plugins.NonBlockingElasticMachineProvisioningAdapter.java

@Override
public FutureStoppedMachine stopMachineAsync(final GridServiceAgent agent, final long duration,
        final TimeUnit unit) {

    final AtomicReference<Throwable> atomicExceptionRef = new AtomicReference<Throwable>();
    final AtomicBoolean atomicDone = new AtomicBoolean(false);

    if (!isStartMachineSupported()) {
        throw new UnsupportedOperationException();
    }/*  www .j ava2s .  c o  m*/

    final long start = System.currentTimeMillis();
    final long end = System.currentTimeMillis() + unit.toMillis(duration);
    final String hostAddress = agent.getMachine().getHostAddress();
    submit(new Runnable() {

        @Override
        public void run() {

            logger.info("Stopping machine " + hostAddress);
            try {
                NonBlockingElasticMachineProvisioningAdapter.this.machineProvisioning
                        .stopMachine(new StartedGridServiceAgent(agent, null), duration, unit);
                logger.info("machine " + hostAddress + " successfully stopped.");
                atomicDone.set(true);
            } catch (ElasticMachineProvisioningException e) {
                atomicExceptionRef.set(e);
            } catch (ElasticGridServiceAgentProvisioningException e) {
                atomicExceptionRef.set(e);
            } catch (InterruptedException e) {
                atomicExceptionRef.set(e);
            } catch (TimeoutException e) {
                atomicExceptionRef.set(e);
            } catch (NoClassDefFoundError e) {
                atomicExceptionRef.set((new NoClassDefFoundElasticMachineProvisioningException(e)));
            } catch (Throwable e) {
                atomicExceptionRef.set(e);
            }
        }

    });

    return new FutureStoppedMachine() {

        @Override
        public boolean isTimedOut() {
            Throwable exception = atomicExceptionRef.get();
            return (exception instanceof TimeoutException) || (!isDone() && System.currentTimeMillis() > end);
        }

        @Override
        public boolean isDone() {
            return atomicDone.get() || (atomicExceptionRef.get() != null);
        }

        @Override
        public Date getTimestamp() {
            return new Date(start);
        }

        @Override
        public ExecutionException getException() {
            ExecutionException executionException = null;
            Throwable throwable = atomicExceptionRef.get();
            if (throwable != null) {
                executionException = new ExecutionException(throwable.getMessage(), throwable);
            }
            return executionException;
        }

        @Override
        public Void get() throws ExecutionException, IllegalStateException, TimeoutException {

            if (!isDone()) {
                // dont allow calling get() before isDone returns true.
                throw new IllegalStateException("Async operation has not completed yet");
            }

            if (isDone() && getException() == null) {
                // all is ok
                return null;
            } else {
                throw getException();
            }
        }

        @Override
        public GridServiceAgent getGridServiceAgent() {
            return agent;
        }
    };

}

From source file:org.openspaces.grid.gsm.machines.plugins.NonBlockingElasticMachineProvisioningAdapter.java

@Override
public FutureCleanupCloudResources cleanupCloudResources(final long duration, final TimeUnit unit) {
    final AtomicReference<Throwable> atomicExceptionRef = new AtomicReference<Throwable>();
    final AtomicBoolean atomicDone = new AtomicBoolean(false);

    if (!isStartMachineSupported()) {
        throw new UnsupportedOperationException();
    }/*from www  .  ja v  a  2  s .  c  o m*/

    final long start = System.currentTimeMillis();
    final long end = System.currentTimeMillis() + unit.toMillis(duration);
    submit(new Runnable() {

        @Override
        public void run() {

            logger.info("Cleaning cloud resources");
            try {
                NonBlockingElasticMachineProvisioningAdapter.this.machineProvisioning
                        .cleanupMachineResources(duration, unit);
                logger.info("Cleaned cloud resources.");
                atomicDone.set(true);
            } catch (ElasticMachineProvisioningException e) {
                atomicExceptionRef.set(e);
            } catch (InterruptedException e) {
                atomicExceptionRef.set(e);
            } catch (TimeoutException e) {
                atomicExceptionRef.set(e);
            } catch (NoClassDefFoundError e) {
                atomicExceptionRef.set((new NoClassDefFoundElasticMachineProvisioningException(e)));
            } catch (Throwable e) {
                atomicExceptionRef.set(e);
            }
        }

    });

    return new FutureCleanupCloudResources() {

        boolean mark;

        @Override
        public boolean isTimedOut() {
            Throwable exception = atomicExceptionRef.get();
            return (exception instanceof TimeoutException) || (!isDone() && System.currentTimeMillis() > end);
        }

        @Override
        public boolean isDone() {
            return atomicDone.get() || (atomicExceptionRef.get() != null);
        }

        @Override
        public Date getTimestamp() {
            return new Date(start);
        }

        @Override
        public ExecutionException getException() {
            ExecutionException executionException = null;
            Throwable throwable = atomicExceptionRef.get();
            if (throwable != null) {
                executionException = new ExecutionException(throwable.getMessage(), throwable);
            }
            return executionException;
        }

        @Override
        public Void get() throws ExecutionException, IllegalStateException, TimeoutException {

            if (!isDone()) {
                // dont allow calling get() before isDone returns true.
                throw new IllegalStateException("Async operation has not completed yet");
            }

            if (isDone() && getException() == null) {
                // all is ok
                return null;
            } else {
                throw getException();
            }
        }

        @Override
        public boolean isMarked() {
            return mark;
        }

        @Override
        public void mark() {
            mark = true;
        }
    };

}

From source file:org.cloudifysource.esc.driver.provisioning.byon.ByonProvisioningDriver.java

@Override
public MachineDetails[] startManagementMachines(final long duration, final TimeUnit unit)
        throws TimeoutException, CloudProvisioningException {
    if (duration < 0) {
        throw new TimeoutException("Starting a new machine timed out");
    }/*from w  ww  .ja va  2  s .com*/
    final long endTime = System.currentTimeMillis() + unit.toMillis(duration);

    logger.info("DefaultCloudProvisioning: startMachine - management == " + management);

    // first check if management already exists
    final MachineDetails[] mds = findManagementInAdmin();
    if (mds.length != 0) {
        return mds;
    }

    // launch the management machines
    publishEvent(EVENT_ATTEMPT_START_MGMT_VMS);
    final int numberOfManagementMachines = this.cloud.getProvider().getNumberOfManagementMachines();
    final MachineDetails[] createdMachines = doStartManagementMachines(endTime, numberOfManagementMachines);
    publishEvent(EVENT_MGMT_VMS_STARTED);
    return createdMachines;
}

From source file:org.eclipse.gyrex.cloud.internal.queue.ZooKeeperQueue.java

@Override
public IMessage consumeMessage(final long timeout, final TimeUnit unit)
        throws IllegalArgumentException, IllegalStateException, SecurityException, InterruptedException {
    /*/*from w w  w  .j  a va  2 s.  co m*/
     * We want to get the node with the smallest sequence number. But
     * other clients may remove and add nodes concurrently. Thus, we
     * need to further check if the node can be returned. It might be
     * gone by the time we check. If that happens we just continue with
     * the next node.
     */
    if ((timeout > 0) && (unit == null)) {
        throw new IllegalArgumentException("unit must not be null when timeout is specified");
    }
    final long abortTime = timeout > 0 ? unit.toMillis(timeout) + System.currentTimeMillis() : 0;
    TreeMap<Long, String> queueChildren;
    while (true) {
        try {
            queueChildren = readQueueChildren(null);
        } catch (final Exception e) {
            if (e instanceof KeeperException.NoNodeException) {
                throw new IllegalStateException(String.format("queue '%s' does not exist", id));
            }
            throw new QueueOperationFailedException(id, "CONSUME_MESSAGES", e);
        }

        // iterate over all children
        if (queueChildren.size() > 0) {
            for (final String childName : queueChildren.values()) {
                if (childName != null) {
                    // read message
                    final Message message = readQueueMessage(childName);
                    // check if we have a valid message
                    if ((message == null) || message.isHidden()) {
                        continue;
                    }
                    // try to consume the message
                    if (!message.consume(false)) {
                        continue;
                    }
                    return message;
                }
            }
        }

        // at this point no children are available
        if (abortTime <= 0) {
            // abort
            return null;
        }

        // wait for the timeout
        final long diff = abortTime - System.currentTimeMillis();
        if (diff > 0) {
            Thread.sleep(Math.max(diff / 2, 250));
        } else {
            // wait time elapsed
            return null;
        }
    }
}

From source file:org.apache.http2.impl.conn.tsccm.ConnPoolByRoute.java

/**
 * Obtains a pool entry with a connection within the given timeout.
 * If a {@link WaitingThread} is used to block, {@link WaitingThreadAborter#setWaitingThread(WaitingThread)}
 * must be called before blocking, to allow the thread to be interrupted.
 *
 * @param route     the route for which to get the connection
 * @param timeout   the timeout, 0 or negative for no timeout
 * @param tunit     the unit for the <code>timeout</code>,
 *                  may be <code>null</code> only if there is no timeout
 * @param aborter   an object which can abort a {@link WaitingThread}.
 *
 * @return  pool entry holding a connection for the route
 *
 * @throws ConnectionPoolTimeoutException
 *         if the timeout expired//from  ww  w  . j  ava  2  s.co m
 * @throws InterruptedException
 *         if the calling thread was interrupted
 */
protected BasicPoolEntry getEntryBlocking(HttpRoute route, Object state, long timeout, TimeUnit tunit,
        WaitingThreadAborter aborter) throws ConnectionPoolTimeoutException, InterruptedException {

    Date deadline = null;
    if (timeout > 0) {
        deadline = new Date(System.currentTimeMillis() + tunit.toMillis(timeout));
    }

    BasicPoolEntry entry = null;
    poolLock.lock();
    try {

        RouteSpecificPool rospl = getRoutePool(route, true);
        WaitingThread waitingThread = null;

        while (entry == null) {

            if (shutdown) {
                throw new IllegalStateException("Connection pool shut down");
            }

            if (log.isDebugEnabled()) {
                log.debug("[" + route + "] total kept alive: " + freeConnections.size() + ", total issued: "
                        + leasedConnections.size() + ", total allocated: " + numConnections + " out of "
                        + maxTotalConnections);
            }

            // the cases to check for:
            // - have a free connection for that route
            // - allowed to create a free connection for that route
            // - can delete and replace a free connection for another route
            // - need to wait for one of the things above to come true

            entry = getFreeEntry(rospl, state);
            if (entry != null) {
                break;
            }

            boolean hasCapacity = rospl.getCapacity() > 0;

            if (log.isDebugEnabled()) {
                log.debug("Available capacity: " + rospl.getCapacity() + " out of " + rospl.getMaxEntries()
                        + " [" + route + "][" + state + "]");
            }

            if (hasCapacity && numConnections < maxTotalConnections) {

                entry = createEntry(rospl, operator);

            } else if (hasCapacity && !freeConnections.isEmpty()) {

                deleteLeastUsedEntry();
                // if least used entry's route was the same as rospl,
                // rospl is now out of date : we preemptively refresh
                rospl = getRoutePool(route, true);
                entry = createEntry(rospl, operator);

            } else {

                if (log.isDebugEnabled()) {
                    log.debug("Need to wait for connection" + " [" + route + "][" + state + "]");
                }

                if (waitingThread == null) {
                    waitingThread = newWaitingThread(poolLock.newCondition(), rospl);
                    aborter.setWaitingThread(waitingThread);
                }

                boolean success = false;
                try {
                    rospl.queueThread(waitingThread);
                    waitingThreads.add(waitingThread);
                    success = waitingThread.await(deadline);

                } finally {
                    // In case of 'success', we were woken up by the
                    // connection pool and should now have a connection
                    // waiting for us, or else we're shutting down.
                    // Just continue in the loop, both cases are checked.
                    rospl.removeThread(waitingThread);
                    waitingThreads.remove(waitingThread);
                }

                // check for spurious wakeup vs. timeout
                if (!success && (deadline != null) && (deadline.getTime() <= System.currentTimeMillis())) {
                    throw new ConnectionPoolTimeoutException("Timeout waiting for connection from pool");
                }
            }
        } // while no entry

    } finally {
        poolLock.unlock();
    }
    return entry;
}

From source file:org.apache.ogt.http.impl.conn.tsccm.ConnPoolByRoute.java

/**
 * Obtains a pool entry with a connection within the given timeout.
 * If a {@link WaitingThread} is used to block, {@link WaitingThreadAborter#setWaitingThread(WaitingThread)}
 * must be called before blocking, to allow the thread to be interrupted.
 *
 * @param route     the route for which to get the connection
 * @param timeout   the timeout, 0 or negative for no timeout
 * @param tunit     the unit for the <code>timeout</code>,
 *                  may be <code>null</code> only if there is no timeout
 * @param aborter   an object which can abort a {@link WaitingThread}.
 *
 * @return  pool entry holding a connection for the route
 *
 * @throws ConnectionPoolTimeoutException
 *         if the timeout expired//from w  ww.  java 2s .com
 * @throws InterruptedException
 *         if the calling thread was interrupted
 */
protected BasicPoolEntry getEntryBlocking(HttpRoute route, Object state, long timeout, TimeUnit tunit,
        WaitingThreadAborter aborter) throws ConnectionPoolTimeoutException, InterruptedException {

    Date deadline = null;
    if (timeout > 0) {
        deadline = new Date(System.currentTimeMillis() + tunit.toMillis(timeout));
    }

    BasicPoolEntry entry = null;
    poolLock.lock();
    try {

        RouteSpecificPool rospl = getRoutePool(route, true);
        WaitingThread waitingThread = null;

        while (entry == null) {

            if (shutdown) {
                throw new IllegalStateException("Connection pool shut down");
            }

            if (log.isDebugEnabled()) {
                log.debug("[" + route + "] total kept alive: " + freeConnections.size() + ", total issued: "
                        + leasedConnections.size() + ", total allocated: " + numConnections + " out of "
                        + maxTotalConnections);
            }

            // the cases to check for:
            // - have a free connection for that route
            // - allowed to create a free connection for that route
            // - can delete and replace a free connection for another route
            // - need to wait for one of the things above to come true

            entry = getFreeEntry(rospl, state);
            if (entry != null) {
                break;
            }

            boolean hasCapacity = rospl.getCapacity() > 0;

            if (log.isDebugEnabled()) {
                log.debug("Available capacity: " + rospl.getCapacity() + " out of " + rospl.getMaxEntries()
                        + " [" + route + "][" + state + "]");
            }

            if (hasCapacity && numConnections < maxTotalConnections) {

                entry = createEntry(rospl, operator);

            } else if (hasCapacity && !freeConnections.isEmpty()) {

                deleteLeastUsedEntry();
                // if least used entry's route was the same as rospl,
                // rospl is now out of date : we preemptively refresh
                rospl = getRoutePool(route, true);
                entry = createEntry(rospl, operator);

            } else {

                if (log.isDebugEnabled()) {
                    log.debug("Need to wait for connection" + " [" + route + "][" + state + "]");
                }

                if (waitingThread == null) {
                    waitingThread = newWaitingThread(poolLock.newCondition(), rospl);
                    aborter.setWaitingThread(waitingThread);
                }

                boolean success = false;
                try {
                    rospl.queueThread(waitingThread);
                    waitingThreads.add(waitingThread);
                    success = waitingThread.await(deadline);

                } finally {
                    // In case of 'success', we were woken up by the
                    // connection pool and should now have a connection
                    // waiting for us, or else we're shutting down.
                    // Just continue in the loop, both cases are checked.
                    rospl.removeThread(waitingThread);
                    waitingThreads.remove(waitingThread);
                }

                // check for spurious wakeup vs. timeout
                if (!success && (deadline != null) && (deadline.getTime() <= System.currentTimeMillis())) {
                    throw new ConnectionPoolTimeoutException("Timeout waiting for connection");
                }
            }
        } // while no entry

    } finally {
        poolLock.unlock();
    }
    return entry;
}

From source file:org.apache.http.impl.conn.tsccm.ConnPoolByRoute.java

/**
 * Obtains a pool entry with a connection within the given timeout.
 * If a {@link WaitingThread} is used to block, {@link WaitingThreadAborter#setWaitingThread(WaitingThread)}
 * must be called before blocking, to allow the thread to be interrupted.
 *
 * @param route     the route for which to get the connection
 * @param timeout   the timeout, 0 or negative for no timeout
 * @param tunit     the unit for the <code>timeout</code>,
 *                  may be <code>null</code> only if there is no timeout
 * @param aborter   an object which can abort a {@link WaitingThread}.
 *
 * @return  pool entry holding a connection for the route
 *
 * @throws ConnectionPoolTimeoutException
 *         if the timeout expired/*from  ww  w.jav a 2 s . c  om*/
 * @throws InterruptedException
 *         if the calling thread was interrupted
 */
protected BasicPoolEntry getEntryBlocking(final HttpRoute route, final Object state, final long timeout,
        final TimeUnit tunit, final WaitingThreadAborter aborter)
        throws ConnectionPoolTimeoutException, InterruptedException {

    Date deadline = null;
    if (timeout > 0) {
        deadline = new Date(System.currentTimeMillis() + tunit.toMillis(timeout));
    }

    BasicPoolEntry entry = null;
    poolLock.lock();
    try {

        RouteSpecificPool rospl = getRoutePool(route, true);
        WaitingThread waitingThread = null;

        while (entry == null) {
            Asserts.check(!shutdown, "Connection pool shut down");

            if (log.isDebugEnabled()) {
                log.debug("[" + route + "] total kept alive: " + freeConnections.size() + ", total issued: "
                        + leasedConnections.size() + ", total allocated: " + numConnections + " out of "
                        + maxTotalConnections);
            }

            // the cases to check for:
            // - have a free connection for that route
            // - allowed to create a free connection for that route
            // - can delete and replace a free connection for another route
            // - need to wait for one of the things above to come true

            entry = getFreeEntry(rospl, state);
            if (entry != null) {
                break;
            }

            final boolean hasCapacity = rospl.getCapacity() > 0;

            if (log.isDebugEnabled()) {
                log.debug("Available capacity: " + rospl.getCapacity() + " out of " + rospl.getMaxEntries()
                        + " [" + route + "][" + state + "]");
            }

            if (hasCapacity && numConnections < maxTotalConnections) {

                entry = createEntry(rospl, operator);

            } else if (hasCapacity && !freeConnections.isEmpty()) {

                deleteLeastUsedEntry();
                // if least used entry's route was the same as rospl,
                // rospl is now out of date : we preemptively refresh
                rospl = getRoutePool(route, true);
                entry = createEntry(rospl, operator);

            } else {

                if (log.isDebugEnabled()) {
                    log.debug("Need to wait for connection" + " [" + route + "][" + state + "]");
                }

                if (waitingThread == null) {
                    waitingThread = newWaitingThread(poolLock.newCondition(), rospl);
                    aborter.setWaitingThread(waitingThread);
                }

                boolean success = false;
                try {
                    rospl.queueThread(waitingThread);
                    waitingThreads.add(waitingThread);
                    success = waitingThread.await(deadline);

                } finally {
                    // In case of 'success', we were woken up by the
                    // connection pool and should now have a connection
                    // waiting for us, or else we're shutting down.
                    // Just continue in the loop, both cases are checked.
                    rospl.removeThread(waitingThread);
                    waitingThreads.remove(waitingThread);
                }

                // check for spurious wakeup vs. timeout
                if (!success && (deadline != null) && (deadline.getTime() <= System.currentTimeMillis())) {
                    throw new ConnectionPoolTimeoutException("Timeout waiting for connection from pool");
                }
            }
        } // while no entry

    } finally {
        poolLock.unlock();
    }
    return entry;
}

From source file:com.google.acre.script.NHttpClient.java

public void wait_on_result(long time, TimeUnit tunit, AcreResponse res) throws NHttpException {

    if (_reactor != null && _reactor.getStatus() != IOReactorStatus.INACTIVE) {
        throw new NHttpException("Can not run wait_on_results while it is already running [current status: "
                + _reactor.getStatus() + "]");
    }/*from   ww w  .ja  va2 s  .c  o m*/

    start();

    long endtime = System.currentTimeMillis() + tunit.toMillis(time);

    int i = 0;
    while (_requests.size() > 0) {
        long pass_start_time = System.currentTimeMillis();

        if (i > _requests.size() - 1)
            i = 0;

        if (time != -1L && endtime <= System.currentTimeMillis()) {
            // If we've run out of time, kill off the reactor to
            // close our open connections, and throw an exception
            // to let the caller know we're out of time
            // 
            // XXX should probably use a real exception here
            try {
                _requests.clear();
                _reactor.shutdown();
                throw new NHttpTimeoutException();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        NHttpClientClosure closure = _requests.get(i);
        if (!closure.done() && closure.sreq() == null && _connection_lock.availablePermits() > 0) {
            closure.sreq(closure.connect(_proxy, _reactor));
        }

        if (closure.done()) {
            if (closure.response() != null) {
                closure.callback().finished(closure.url(), closure.response());
            } else if (closure.exceptions().size() > 0) {
                closure.exceptions().get(0).printStackTrace();
                closure.callback().error(closure.url(), new NHttpException(closure.exceptions().get(0)));
            } else {
                closure.callback().error(closure.url(), new NHttpException("Request failed"));
            }
            _requests.remove(i);
            continue;
        } else if (closure.timeout() != 0
                && (closure.start_time() + closure.timeout()) <= System.currentTimeMillis()) {
            // We pass a null response to the callback to let it know
            // that things broke
            if (closure.sreq() != null) {
                closure.sreq().cancel();
                _connection_lock.release();
            }

            closure.callback().error(closure.url(), new NHttpTimeoutException());
            _requests.remove(i);
            continue;
        }

        // Block for 15ms to not eat all the cpu
        try {
            Thread.sleep(15);
        } catch (InterruptedException e) {
            // pass
        }

        _costCollector.collect("auub", System.currentTimeMillis() - pass_start_time);
        i++;
    }

    // It's somewhat questionable to stop the reactor when we're done
    // but we can restart it if we need it again.
    stop();
}