Example usage for java.util.concurrent Executors newSingleThreadExecutor

List of usage examples for java.util.concurrent Executors newSingleThreadExecutor

Introduction

In this page you can find the example usage for java.util.concurrent Executors newSingleThreadExecutor.

Prototype

public static ExecutorService newSingleThreadExecutor() 

Source Link

Document

Creates an Executor that uses a single worker thread operating off an unbounded queue.

Usage

From source file:hivemall.mix.server.MixServerTest.java

@Test
public void test2ClientsZeroOneDenseModelWithMixCanceling() throws InterruptedException {
    final int port = NetUtils.getAvailablePort();
    CommandLine cl = CommandLineUtils.parseOptions(
            new String[] { "-port", Integer.toString(port), "-sync_threshold", "30" }, MixServer.getOptions());
    MixServer server = new MixServer(cl);
    ExecutorService serverExec = Executors.newSingleThreadExecutor();
    serverExec.submit(server);// www .  jav  a2  s .c  om

    waitForState(server, ServerState.RUNNING);

    final ExecutorService clientsExec = Executors.newCachedThreadPool();
    for (int i = 0; i < 2; i++) {
        clientsExec.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    invokeClient01("test2ClientsZeroOne", port, true, true);
                } catch (InterruptedException e) {
                    Assert.fail(e.getMessage());
                }
            }
        });
    }
    clientsExec.awaitTermination(30, TimeUnit.SECONDS);
    clientsExec.shutdown();
    serverExec.shutdown();
}

From source file:com.amazonaws.services.dynamodbv2.replication.impl.ShardSubscriberImpl.java

/**
 * {@inheritDoc}//from w  w  w.j a  v a 2s .  c o  m
 */
@Override
public void initialize(final String shardId) {
    try {
        shardSubscriberId = "{" + InetAddress.getLocalHost().getCanonicalHostName() + ", " + shardId + ", "
                + UUID.randomUUID() + "}";
    } catch (final UnknownHostException e) {
        shardSubscriberId = "{" + shardId + ", " + UUID.randomUUID() + "}";
    }
    orginalShardId = shardId;
    // Registration will throw a NullPointerException if subscriberId is not set.
    getReplicationWorker().registerShardSubscriber(this);
    LOGGER.debug("registered shardSubscriber: " + shardSubscriberId);

    // Create and start sweeper
    sweeper = new MultiRegionCheckpointSweeper(replicationWorker, tableName, shardId, checkpoints,
            timeBetweenSweeps, checkpointBackoffTime);

    sweeperService = Executors.newSingleThreadExecutor();
    sweeperService.submit(sweeper);
    sweeperService.shutdown();
    LOGGER.debug("Sweepers initialized for shard subscriber: " + shardSubscriberId);
}

From source file:ca.ualberta.cmput301w13t11.FoodBook.model.ServerClient.java

/**
 * Uploads the given recipe to the server.
 * @param recipe The recipe to be uploaded.
 * ReturnCode.ERROR if anything goes wrong, ReturnCode.ALREADY_EXISTS if a recipe
 * by that name already exists on the server (this will eventually be modified to check
 * against URI instead of Recipe title), ReturnCode.SUCCESS if the recipe was successfully
 * uploaded, or ReturnCode.BUSY if the network is not responding or the operation is 
 * taking too long.//from   ww  w  .  ja  va 2  s  .co  m
 */
public ReturnCode uploadRecipe(Recipe recipe) throws IllegalStateException, IOException {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Future<ReturnCode> future = executor.submit(new UploadRecipeTask(recipe));
    ReturnCode ret = ReturnCode.ERROR;
    try {
        ret = future.get(TIMEOUT_PERIOD, TimeUnit.SECONDS);
    } catch (TimeoutException te) {
        logger.log(Level.SEVERE, "Upload Recipe operation timed out.");
        return ReturnCode.BUSY;
    } catch (Exception e) {
        logger.log(Level.SEVERE, "Exception during upload recipe operation.");
        return ReturnCode.ERROR;
    }
    /* Got here so the operation finished. */
    executor.shutdownNow();
    return ret;
}

From source file:ddf.catalog.resource.download.ReliableResourceDownloader.java

@Override
public void run() {
    long bytesRead = 0;
    ReliableResourceStatus reliableResourceStatus = null;
    int retryAttempts = 0;

    try {//w w  w  . j a  v  a 2s  . c o m
        reliableResourceCallable = new ReliableResourceCallable(resourceInputStream, countingFbos, fos,
                downloaderConfig.getChunkSize(), lock);
        downloadFuture = null;
        ResourceRetrievalMonitor resourceRetrievalMonitor = null;
        this.downloadState.setDownloadState(DownloadManagerState.DownloadState.IN_PROGRESS);

        while (retryAttempts < downloaderConfig.getMaxRetryAttempts()) {
            if (reliableResourceCallable == null) {
                // This usually occurs on retry attempts to download and the
                // ReliableResourceCallable cannot be successfully created. In this case, a
                // partial cache file may have been created from the previous caching attempt(s)
                // and needs to be deleted from the product cache directory.
                LOGGER.debug("ReliableResourceCallable is null - cannot download resource");
                retryAttempts++;
                LOGGER.debug("Download attempt {}", retryAttempts);
                eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.RETRYING, metacard,
                        String.format("Attempt %d of %d.", retryAttempts,
                                downloaderConfig.getMaxRetryAttempts()),
                        reliableResourceStatus.getBytesRead(), downloadIdentifier);
                delay();
                reliableResourceCallable = retrieveResource(bytesRead);
                continue;
            }
            retryAttempts++;
            LOGGER.debug("Download attempt {}", retryAttempts);
            try {
                downloadExecutor = Executors.newSingleThreadExecutor();
                downloadFuture = downloadExecutor.submit(reliableResourceCallable);

                // Update callable and its Future in the ReliableResourceInputStream being read
                // by the client so that if client cancels this download the proper Callable and
                // Future are canceled.
                streamReadByClient.setCallableAndItsFuture(reliableResourceCallable, downloadFuture);

                // Monitor to watch that bytes are continually being read from the resource's
                // InputStream. This monitor is used to detect if there are long pauses or
                // network connection loss during the product retrieval. If such a "gap" is
                // detected, the Callable will be canceled and a new download attempt (retry)
                // will be started.
                final Timer downloadTimer = new Timer();
                resourceRetrievalMonitor = new ResourceRetrievalMonitor(downloadFuture,
                        reliableResourceCallable, downloaderConfig.getMonitorPeriodMS(), eventPublisher,
                        resourceResponse, metacard, downloadIdentifier);
                LOGGER.debug("Configuring resourceRetrievalMonitor to run every {} ms",
                        downloaderConfig.getMonitorPeriodMS());
                downloadTimer.scheduleAtFixedRate(resourceRetrievalMonitor,
                        downloaderConfig.getMonitorInitialDelayMS(), downloaderConfig.getMonitorPeriodMS());
                downloadStarted.set(Boolean.TRUE);
                reliableResourceStatus = downloadFuture.get();
            } catch (InterruptedException | CancellationException | ExecutionException e) {
                LOGGER.error("{} - Unable to store product file {}", e.getClass().getSimpleName(), filePath, e);
                reliableResourceStatus = reliableResourceCallable.getReliableResourceStatus();
            }

            LOGGER.debug("reliableResourceStatus = {}", reliableResourceStatus);

            if (DownloadStatus.RESOURCE_DOWNLOAD_COMPLETE.equals(reliableResourceStatus.getDownloadStatus())) {
                LOGGER.debug("Cancelling resourceRetrievalMonitor");
                resourceRetrievalMonitor.cancel();
                if (downloadState.getDownloadState() != DownloadState.CANCELED) {
                    LOGGER.debug("Sending Product Retrieval Complete event");
                    eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.COMPLETE,
                            metacard, null, reliableResourceStatus.getBytesRead(), downloadIdentifier);
                } else {
                    LOGGER.debug(
                            "Client had canceled download and caching completed - do NOT send ProductRetrievalCompleted notification");
                    eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.COMPLETE,
                            metacard, null, reliableResourceStatus.getBytesRead(), downloadIdentifier, false,
                            true);
                }
                if (doCaching) {
                    LOGGER.debug("Setting reliableResource size");
                    reliableResource.setSize(reliableResourceStatus.getBytesRead());
                    LOGGER.debug("Adding caching key = {} to cache map", reliableResource.getKey());
                    resourceCache.put(reliableResource);
                }
                break;
            } else {
                bytesRead = reliableResourceStatus.getBytesRead();
                LOGGER.debug("Download not complete, only read {} bytes", bytesRead);
                if (fos != null) {
                    fos.flush();
                }

                // Synchronized so that the Callable is not shutdown while in the middle of
                // writing to the
                // FileBackedOutputStream and cache file (need to keep both of these in sync
                // with number of bytes
                // written to each of them).
                synchronized (lock) {

                    // Simply doing Future.cancel(true) or a plain shutdown() is not enough.
                    // The downloadExecutor (or its underlying Future/thread) is holding on
                    // to a resource or is blocking on a read - undetermined at this point,
                    // but shutdownNow() along with re-instantiating the executor at top of
                    // while loop fixes this.
                    downloadExecutor.shutdownNow();
                }

                if (DownloadStatus.PRODUCT_INPUT_STREAM_EXCEPTION
                        .equals(reliableResourceStatus.getDownloadStatus())) {

                    // Detected exception when reading from product's InputStream - re-retrieve
                    // product from the Source and retry caching it
                    LOGGER.info("Handling product InputStream exception");
                    eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.RETRYING,
                            metacard,
                            String.format("Attempt %d of %d.", retryAttempts,
                                    downloaderConfig.getMaxRetryAttempts()),
                            reliableResourceStatus.getBytesRead(), downloadIdentifier);
                    IOUtils.closeQuietly(resourceInputStream);
                    resourceInputStream = null;
                    delay();
                    reliableResourceCallable = retrieveResource(bytesRead);
                } else if (DownloadStatus.CACHED_FILE_OUTPUT_STREAM_EXCEPTION
                        .equals(reliableResourceStatus.getDownloadStatus())) {

                    // Detected exception when writing the product data to the product cache
                    // directory - assume this OutputStream cannot be fixed (e.g., disk full)
                    // and just continue streaming product to the client, i.e., writing to the
                    // FileBackedOutputStream
                    LOGGER.info("Handling FileOutputStream exception");
                    eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.RETRYING,
                            metacard,
                            String.format("Attempt %d of %d.", retryAttempts,
                                    downloaderConfig.getMaxRetryAttempts()),
                            reliableResourceStatus.getBytesRead(), downloadIdentifier);
                    if (doCaching) {
                        deleteCacheFile(fos);
                        resourceCache.removePendingCacheEntry(reliableResource.getKey());
                        // Disable caching since the cache file being written to had issues
                        downloaderConfig.setCacheEnabled(false);
                        doCaching = false;
                        downloadState.setCacheEnabled(downloaderConfig.isCacheEnabled());
                        downloadState.setContinueCaching(doCaching);
                    }
                    reliableResourceCallable = new ReliableResourceCallable(resourceInputStream, countingFbos,
                            downloaderConfig.getChunkSize(), lock);
                    reliableResourceCallable.setBytesRead(bytesRead);

                } else if (DownloadStatus.CLIENT_OUTPUT_STREAM_EXCEPTION
                        .equals(reliableResourceStatus.getDownloadStatus())) {

                    // Detected exception when writing product data to the output stream
                    // (FileBackedOutputStream) that
                    // is being read by the client - assume this is unrecoverable, but continue
                    // to cache the file
                    LOGGER.info("Handling FileBackedOutputStream exception");
                    eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.CANCELLED,
                            metacard, "", reliableResourceStatus.getBytesRead(), downloadIdentifier);
                    IOUtils.closeQuietly(fbos);
                    IOUtils.closeQuietly(countingFbos);
                    LOGGER.debug("Cancelling resourceRetrievalMonitor");
                    resourceRetrievalMonitor.cancel();
                    reliableResourceCallable = new ReliableResourceCallable(resourceInputStream, fos,
                            downloaderConfig.getChunkSize(), lock);
                    reliableResourceCallable.setBytesRead(bytesRead);

                } else if (DownloadStatus.RESOURCE_DOWNLOAD_CANCELED
                        .equals(reliableResourceStatus.getDownloadStatus())) {

                    LOGGER.info("Handling client cancellation of product download");
                    downloadState.setDownloadState(DownloadState.CANCELED);
                    LOGGER.debug("Cancelling resourceRetrievalMonitor");
                    resourceRetrievalMonitor.cancel();
                    eventListener.removeDownloadIdentifier(downloadIdentifier);
                    eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.CANCELLED,
                            metacard, "", reliableResourceStatus.getBytesRead(), downloadIdentifier);
                    if (doCaching && downloaderConfig.isCacheWhenCanceled()) {
                        LOGGER.debug("Continuing to cache product");
                        reliableResourceCallable = new ReliableResourceCallable(resourceInputStream, fos,
                                downloaderConfig.getChunkSize(), lock);
                        reliableResourceCallable.setBytesRead(bytesRead);
                    } else {
                        break;
                    }

                } else if (DownloadStatus.RESOURCE_DOWNLOAD_INTERRUPTED
                        .equals(reliableResourceStatus.getDownloadStatus())) {

                    // Caching has been interrupted (possibly resourceRetrievalMonitor detected
                    // too much time being taken to retrieve a chunk of product data from the
                    // InputStream) - re-retrieve product from the Source, skip forward in the
                    // product InputStream the number of bytes already read successfully, and
                    // retry caching it
                    LOGGER.info("Handling interrupt of product caching - closing source InputStream");

                    // Set InputStream used on previous attempt to null so that any attempt to
                    // close it will not fail (CXF's DelegatingInputStream, which is the
                    // underlying InputStream being used, does a consume() which is a read() as
                    // part of its close() operation and this will result in a blocking read)
                    resourceInputStream = null;
                    eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.RETRYING,
                            metacard,
                            String.format("Attempt %d of %d.", retryAttempts,
                                    downloaderConfig.getMaxRetryAttempts()),
                            reliableResourceStatus.getBytesRead(), downloadIdentifier);
                    delay();
                    reliableResourceCallable = retrieveResource(bytesRead);
                }
            }
        }

        if (null != reliableResourceStatus && !DownloadStatus.RESOURCE_DOWNLOAD_COMPLETE
                .equals(reliableResourceStatus.getDownloadStatus())) {
            if (doCaching) {
                deleteCacheFile(fos);
            }
            if (!DownloadStatus.RESOURCE_DOWNLOAD_CANCELED.equals(reliableResourceStatus.getDownloadStatus())) {
                eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.FAILED, metacard,
                        "Unable to retrieve product file.", reliableResourceStatus.getBytesRead(),
                        downloadIdentifier);
            }
        }
    } catch (IOException e) {
        LOGGER.error("Unable to store product file {}", filePath, e);
        downloadState.setDownloadState(DownloadState.FAILED);
        eventPublisher.postRetrievalStatus(resourceResponse, ProductRetrievalStatus.FAILED, metacard,
                "Unable to store product file.", reliableResourceStatus.getBytesRead(), downloadIdentifier);
    } finally {
        cleanupAfterDownload(reliableResourceStatus);
        downloadExecutor.shutdown();
    }
}

From source file:no.ntnu.idi.socialhitchhiking.map.GeoHelper.java

/**
 * Gets a {@link JSONObject} from an address string
 * @param adr/* ww  w  .ja v a  2 s  .  c  o  m*/
 * @return
 */
private static JSONObject getLocationInfo(final String adr) {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Callable<StringBuilder> callable = new Callable<StringBuilder>() {
        @Override
        public StringBuilder call() throws ClientProtocolException, IOException {
            StringBuilder stringBuilder = new StringBuilder();
            String address;
            address = adr.replaceAll(" ", "%20");
            address = address.replaceAll("\n", "%20");
            HttpPost httppost = new HttpPost(
                    "http://maps.google.com/maps/api/geocode/json?address=" + address + "&sensor=false");
            HttpClient client = new DefaultHttpClient();
            HttpResponse response;
            stringBuilder = new StringBuilder();

            response = client.execute(httppost);
            HttpEntity entity = response.getEntity();
            InputStream stream = entity.getContent();
            int b;
            while ((b = stream.read()) != -1) {
                stringBuilder.append((char) b);
            }
            return stringBuilder;
        }
    };
    Future<StringBuilder> future = executor.submit(callable);
    StringBuilder stringBuilder;
    try {
        stringBuilder = future.get();
    } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        stringBuilder = new StringBuilder();
    } catch (ExecutionException e1) {
        stringBuilder = new StringBuilder();
    }
    executor.shutdown();

    JSONObject jsonObject = new JSONObject();
    try {
        jsonObject = new JSONObject(stringBuilder.toString());
    } catch (JSONException e) {
        e.printStackTrace();
    }

    return jsonObject;
}

From source file:fr.inria.lille.repair.nopol.NoPol.java

/**
 * Method used as proxy for runNopolProcessor to handle timeout
 *//*w  w w. j  a  v a2  s. c o m*/
private List<Patch> executeNopolProcessor(final List<TestResult> tests, final SourceLocation sourceLocation,
        final SpoonedClass spoonCl, final NopolProcessor nopolProcessor) {
    final ExecutorService executor = Executors.newSingleThreadExecutor();
    final Future nopolExecution = executor.submit(new Callable() {
        @Override
        public Object call() throws Exception {
            return runNopolProcessor(tests, sourceLocation, spoonCl, nopolProcessor);
        }
    });
    try {
        executor.shutdown();
        return (List) nopolExecution.get(nopolContext.getMaxTimeEachTypeOfFixInMinutes(), TimeUnit.MINUTES);
    } catch (ExecutionException exception) {
        LoggerFactory.getLogger(this.getClass()).error("Error ExecutionException " + exception.toString());
        return Collections.emptyList();
    } catch (InterruptedException execption) {
        LoggerFactory.getLogger(this.getClass()).error("Repair interrupted");
        return Collections.emptyList();
    } catch (TimeoutException exception) {
        LoggerFactory.getLogger(this.getClass()).error("Timeout: execution time > "
                + nopolContext.getMaxTimeEachTypeOfFixInMinutes() + " " + TimeUnit.MINUTES, exception);
        return Collections.emptyList();
    }
}

From source file:com.networking.OkHttpResponseTestActivity.java

public void checkForHeaderPost(View view) {

    ANRequest.PostRequestBuilder postRequestBuilder = AndroidNetworking
            .post(ApiEndPoint.BASE_URL + ApiEndPoint.CHECK_FOR_HEADER);

    postRequestBuilder.addHeaders("token", "1234");

    ANRequest anRequest = postRequestBuilder.setTag(this).setPriority(Priority.LOW)
            .setExecutor(Executors.newSingleThreadExecutor()).build();

    anRequest.setAnalyticsListener(new AnalyticsListener() {
        @Override/*from  www .  j  av a2  s  .c om*/
        public void onReceived(long timeTakenInMillis, long bytesSent, long bytesReceived,
                boolean isFromCache) {
            Log.d(TAG, " timeTakenInMillis : " + timeTakenInMillis);
            Log.d(TAG, " bytesSent : " + bytesSent);
            Log.d(TAG, " bytesReceived : " + bytesReceived);
            Log.d(TAG, " isFromCache : " + isFromCache);
        }
    });

    anRequest.getAsOkHttpResponseAndJSONObject(new OkHttpResponseAndJSONObjectRequestListener() {
        @Override
        public void onResponse(Response okHttpResponse, JSONObject response) {
            Log.d(TAG, "onResponse object : " + response.toString());
            Log.d(TAG,
                    "onResponse isMainThread : " + String.valueOf(Looper.myLooper() == Looper.getMainLooper()));
            if (okHttpResponse.isSuccessful()) {
                Log.d(TAG, "onResponse success headers : " + okHttpResponse.headers().toString());
            } else {
                Log.d(TAG, "onResponse not success headers : " + okHttpResponse.headers().toString());
            }
        }

        @Override
        public void onError(ANError anError) {
            Utils.logError(TAG, anError);
        }
    });
}

From source file:com.tenforwardconsulting.cordova.BackgroundGeolocationPlugin.java

@Override
protected void pluginInitialize() {
    super.pluginInitialize();

    log = LoggerManager.getLogger(BackgroundGeolocationPlugin.class);
    LoggerManager.enableRollingFileLogging();
    log.info("initializing plugin");

    final ResourceResolver res = ResourceResolver.newInstance(getApplication());
    final String authority = res.getStringResource(Config.CONTENT_AUTHORITY_RESOURCE);

    executorService = Executors.newSingleThreadExecutor();
}

From source file:com.echopf.ECHODataObject.java

/**
 * Does Delete an object from the remote server in a background thread.
 * /*  w w w.  j a  v a2 s  .co  m*/
 * @param sync if set TRUE, then the main (UI) thread is waited for complete the deleting in a background thread. 
 *              (a synchronous communication)
 * @param callback invoked after the deleting is completed
 * @throws ECHOException 
 */
protected void doDelete(final boolean sync, final DeleteCallback<S> callback) throws ECHOException {
    final Handler handler = new Handler();

    // Get ready a background thread
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Callable<Object> communictor = new Callable<Object>() {

        @Override
        public Object call() throws ECHOException {

            JSONObject data = null;
            ECHOException exception = null;
            try {

                synchronized (lock) {
                    data = ECHOQuery.deleteRequest(getRequestURLPath());

                    refid = null;
                    copyData(data);
                }

            } catch (ECHOException e) {
                exception = e;
            } catch (Exception e) {
                exception = new ECHOException(e);
            }

            if (sync == false) {

                // Execute a callback method in the main (UI) thread.
                if (callback != null) {
                    final ECHOException fException = exception;

                    handler.post(new Runnable() {
                        @Override
                        @SuppressWarnings("unchecked")
                        public void run() {
                            callback.done((S) ECHODataObject.this, fException);
                        }
                    });
                }

            } else {

                if (exception != null)
                    throw exception;

            }

            return null;
        }
    };

    Future<Object> future = executor.submit(communictor);

    if (sync) {
        try {
            future.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // ignore/reset
        } catch (ExecutionException e) {
            Throwable e2 = e.getCause();

            if (e2 instanceof ECHOException) {
                throw (ECHOException) e2;
            }

            throw new RuntimeException(e2);
        }
    }
}

From source file:com.spotify.reaper.unit.service.SegmentRunnerTest.java

@Test
public void failureTest() throws InterruptedException, ReaperException, ExecutionException {
    final IStorage storage = new MemoryStorage();
    RepairUnit cf = storage/* www  .jav a 2  s.c  o m*/
            .addRepairUnit(new RepairUnit.Builder("reaper", "reaper", Sets.newHashSet("reaper")));
    RepairRun run = storage.addRepairRun(
            new RepairRun.Builder("reaper", cf.getId(), DateTime.now(), 0.5, 1, RepairParallelism.PARALLEL));
    storage.addRepairSegments(Collections.singleton(
            new RepairSegment.Builder(run.getId(), new RingRange(BigInteger.ONE, BigInteger.ZERO), cf.getId())),
            run.getId());
    final long segmentId = storage.getNextFreeSegment(run.getId()).get().getId();

    final ExecutorService executor = Executors.newSingleThreadExecutor();
    final MutableObject<Future<?>> future = new MutableObject<>();

    AppContext context = new AppContext();
    context.storage = storage;
    context.jmxConnectionFactory = new JmxConnectionFactory() {
        @Override
        public JmxProxy connect(final Optional<RepairStatusHandler> handler, String host) {
            JmxProxy jmx = mock(JmxProxy.class);
            when(jmx.getClusterName()).thenReturn("reaper");
            when(jmx.isConnectionAlive()).thenReturn(true);
            when(jmx.tokenRangeToEndpoint(anyString(), any(RingRange.class)))
                    .thenReturn(Lists.newArrayList(""));
            when(jmx.triggerRepair(any(BigInteger.class), any(BigInteger.class), anyString(),
                    Matchers.<RepairParallelism>any(), Sets.newHashSet(anyString())))
                            .then(new Answer<Integer>() {
                                @Override
                                public Integer answer(InvocationOnMock invocation) {
                                    assertEquals(RepairSegment.State.NOT_STARTED,
                                            storage.getRepairSegment(segmentId).get().getState());
                                    future.setValue(executor.submit(new Runnable() {
                                        @Override
                                        public void run() {
                                            handler.get().handle(1, ActiveRepairService.Status.STARTED,
                                                    "Repair command 1 has started");
                                            assertEquals(RepairSegment.State.RUNNING,
                                                    storage.getRepairSegment(segmentId).get().getState());
                                            handler.get().handle(1, ActiveRepairService.Status.SESSION_FAILED,
                                                    "Repair command 1 has failed");
                                            assertEquals(RepairSegment.State.NOT_STARTED,
                                                    storage.getRepairSegment(segmentId).get().getState());
                                            handler.get().handle(1, ActiveRepairService.Status.FINISHED,
                                                    "Repair command 1 has finished");
                                            assertEquals(RepairSegment.State.NOT_STARTED,
                                                    storage.getRepairSegment(segmentId).get().getState());
                                        }
                                    }));

                                    return 1;
                                }
                            });

            return jmx;
        }
    };
    RepairRunner rr = mock(RepairRunner.class);
    RepairUnit ru = mock(RepairUnit.class);
    SegmentRunner sr = new SegmentRunner(context, segmentId, Collections.singleton(""), 1000, 0.5,
            RepairParallelism.PARALLEL, "reaper", ru, rr);
    sr.run();

    future.getValue().get();
    executor.shutdown();

    assertEquals(RepairSegment.State.NOT_STARTED, storage.getRepairSegment(segmentId).get().getState());
    assertEquals(1, storage.getRepairSegment(segmentId).get().getFailCount());
}