com.google.common.util.concurrent.Service Java Examples

The following examples show how to use com.google.common.util.concurrent.Service. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: CompositeService.java    From twill with Apache License 2.0 6 votes vote down vote up
@Override
protected void startUp() throws Exception {
  Throwable failureCause = null;

  for (Service service : services) {
    try {
      service.startAndWait();
    } catch (UncheckedExecutionException e) {
      failureCause = e.getCause();
      break;
    }
  }

  if (failureCause != null) {
    // Stop all running services and then throw the failure exception
    try {
      stopAll();
    } catch (Throwable t) {
      // Ignore the stop error. Just log.
      LOG.warn("Failed when stopping all services on start failure", t);
    }

    Throwables.propagateIfPossible(failureCause, Exception.class);
    throw new RuntimeException(failureCause);
  }
}
 
Example #2
Source File: AbstractThreadPoolServiceTests.java    From pravega with Apache License 2.0 6 votes vote down vote up
/**
 * Tests the behavior of AbstractThreadPoolService when the runFuture completes (normally or not).
 */
@Test
public void testAutoShutdown() {
    // When completed normally.
    @Cleanup
    val s1 = newService();
    s1.runFuture.complete(null);
    s1.awaitTerminated();
    Assert.assertEquals("Unexpected state upon auto-shutdown (normal completion).", Service.State.TERMINATED, s1.state());

    // When completed with failure.
    @Cleanup
    val s2 = newService();
    s2.runFuture.completeExceptionally(new IntentionalException());
    AssertExtensions.assertThrows(
            "Service did not fail when runFuture failed.",
            () -> s2.awaitTerminated(),
            ex -> ex instanceof IllegalStateException);
    Assert.assertEquals("Unexpected state upon auto-shutdown (failure).", Service.State.FAILED, s2.state());
    Assert.assertTrue("Unexpected failure cause.", s2.failureCause() instanceof IntentionalException);
}
 
Example #3
Source File: BatchWorkerTest.java    From attic-aurora with Apache License 2.0 6 votes vote down vote up
@Test
public void testExecuteThrows() throws Exception {
  control.replay();

  // Make sure BatchWorker service fails on unhandled error during batch processing.
  CountDownLatch shutdownLatch = new CountDownLatch(1);
  batchWorker.addListener(
      new Service.Listener() {
        @Override
        public void failed(Service.State from, Throwable failure) {
          shutdownLatch.countDown();
        }
      },
      MoreExecutors.newDirectExecutorService());

  batchWorker.startAsync().awaitRunning();
  batchWorker.execute(store -> {
    throw new IllegalArgumentException();
  });

  assertTrue(shutdownLatch.await(10L, TimeUnit.SECONDS));
}
 
Example #4
Source File: StyxProxyTest.java    From styx with Apache License 2.0 6 votes vote down vote up
@Disabled
@Test
public void startsServerWithBothHttpAndHttpsConnectors() throws IOException {
    Service server = StyxServers.toGuavaService(newBuilder()
            .setProtocolConnector(connector(0))
            .build());

    server.startAsync().awaitRunning();
    assertThat("Server should be running", server.isRunning());

    LOGGER.info("server is running: " + server.isRunning());

    HttpResponse clearResponse = get("http://localhost:8080/search?q=fanta");
    assertThat(clearResponse.bodyAs(UTF_8), containsString("Response from http Connector"));

    HttpResponse secureResponse = get("https://localhost:8443/secure");
    assertThat(secureResponse.bodyAs(UTF_8), containsString("Response from https Connector"));


    server.stopAsync().awaitTerminated();
    assertThat("Server should not be running", !server.isRunning());
}
 
Example #5
Source File: StyxServerTest.java    From styx with Apache License 2.0 6 votes vote down vote up
@Test
public void stopsTheServerWhenPluginFailsToStart() {
    StyxServer styxServer = null;
    try {
        styxServer = styxServerWithPlugins(ImmutableMap.of(
                "foo", new NonStarterPlugin("foo"),
                "mockplugin3", mock(Plugin.class)));

        Service service = styxServer.startAsync();
        eventually(() -> assertThat(service.state(), is(FAILED)));

        assertThat(pssLog.log(), hasItem(
                loggingEvent(ERROR, "Error starting plugin 'foo'", RuntimeException.class, "Plugin start test error: foo")));

        assertThat(styxServer.state(), is(FAILED));
    } finally {
        stopIfRunning(styxServer);
    }
}
 
Example #6
Source File: ClientService.java    From 07kit with GNU General Public License v3.0 6 votes vote down vote up
@Override
protected void startUp() throws Exception {
    IO.Options options = new IO.Options();
    options.reconnection = true;
    options.timeout = 20000;
    socket = IO.socket(SERVER_URI, options);
    registerListeners();

    socket.connect();

    emitterServices.startAsync();
    emitterServices.addListener(new ServiceManager.Listener() {
        @Override
        public void failure(Service service) {
            final String serviceName = service.getClass().getSimpleName();
            logger.error(String.format("Sub-service failed [%s]", serviceName), service.failureCause());
        }
    });
}
 
Example #7
Source File: OstrichOwnerGroup.java    From emodb with Apache License 2.0 6 votes vote down vote up
/** Returns true if the Guava service entered the RUNNING state within the specified time period. */
private boolean awaitRunning(Service service, long timeoutAt) {
    if (service.isRunning()) {
        return true;
    }
    long waitMillis = timeoutAt - System.currentTimeMillis();
    if (waitMillis <= 0) {
        return false;
    }
    try {
        service.start().get(waitMillis, TimeUnit.MILLISECONDS);
    } catch (Exception e) {
        // Fall through
    }
    return service.isRunning();
}
 
Example #8
Source File: OstrichOwnerGroup.java    From emodb with Apache License 2.0 6 votes vote down vote up
private Optional<LeaderService> startService(final String name) {
    if (!isOwner(name)) {
        return Optional.absent();
    }

    _log.info("Starting owned service {}: {}", _group, name);

    String zkLeaderPath = String.format("/leader/%s/%s", _group.toLowerCase(), name);
    String threadName = String.format("Leader-%s-%s", _group, name);
    String taskName = String.format("%s-%s", _group.toLowerCase(), name);

    LeaderService leaderService = new LeaderService(_curator, zkLeaderPath, _selfId,
            threadName, 1, TimeUnit.MINUTES, new Supplier<Service>() {
        @Override
        public Service get() {
            return _factory.create(name);
        }
    });
    ServiceFailureListener.listenTo(leaderService, _metricRegistry);
    _dropwizardTask.register(taskName, leaderService);
    leaderService.start();
    return Optional.of(leaderService);
}
 
Example #9
Source File: ControllerTest.java    From twill with Apache License 2.0 6 votes vote down vote up
private Service createService(ZKClient zkClient, RunId runId) {
  return new AbstractTwillService(zkClient, runId) {

    private final CountDownLatch stopLatch = new CountDownLatch(1);

    @Override
    protected void doStart() throws Exception {
      LOG.info("Start");
    }

    @Override
    protected void doRun() throws Exception {
      stopLatch.await();
    }

    @Override
    protected void doStop() throws Exception {
      LOG.info("Stop");
    }

    @Override
    protected void triggerShutdown() {
      stopLatch.countDown();
    }
  };
}
 
Example #10
Source File: CronIT.java    From attic-aurora with Apache License 2.0 6 votes vote down vote up
@Test
public void testJobsAreScheduled() throws Exception {
  auroraCronJob.execute(isA(JobExecutionContext.class));

  control.replay();
  final Scheduler scheduler = injector.getInstance(Scheduler.class);

  storage.write((NoResult.Quiet)
      storeProvider -> storeProvider.getCronJobStore().saveAcceptedJob(CRON_JOB));

  final CountDownLatch cronRan = new CountDownLatch(1);
  scheduler.getListenerManager().addTriggerListener(new CountDownWhenComplete(cronRan));
  Service service = boot();

  cronRan.await();

  service.stopAsync().awaitTerminated();
}
 
Example #11
Source File: ListenerExecutor.java    From twill with Apache License 2.0 6 votes vote down vote up
@Override
public void stopping(final Service.State from) {
  if (hasCalled(Service.State.STOPPING)) {
    return;
  }
  executor.execute(new Runnable() {
    @Override
    public void run() {
      try {
        delegate.stopping(from);
      } catch (Throwable t) {
        LOG.warn("Exception thrown from listener", t);
      }
    }
  });
}
 
Example #12
Source File: ScanUploadMonitor.java    From emodb with Apache License 2.0 6 votes vote down vote up
@Inject
public ScanUploadMonitor(@ScannerZooKeeper CuratorFramework curator, @SelfHostAndPort HostAndPort selfHostAndPort,
                         final ScanWorkflow scanWorkflow, final ScanStatusDAO scanStatusDAO,
                         final ScanWriterGenerator scanWriterGenerator,
                         final StashStateListener stashStateListener, final ScanCountListener scanCountListener,
                         final DataTools dataTools, LifeCycleRegistry lifecycle, LeaderServiceTask leaderServiceTask,
                         MetricRegistry metricRegistry, @DelegateCompactionControl CompactionControlSource compactionControlSource, DataCenters dataCenters) {
    super(curator, LEADER_DIR, selfHostAndPort.toString(), SERVICE_NAME, 1, TimeUnit.MINUTES,
            new Supplier<Service>() {
                @Override
                public Service get() {
                    return new LocalScanUploadMonitor(scanWorkflow, scanStatusDAO,
                            scanWriterGenerator, stashStateListener, scanCountListener, dataTools, compactionControlSource, dataCenters);
                }
            });

    ServiceFailureListener.listenTo(this, metricRegistry);
    leaderServiceTask.register(SERVICE_NAME, this);
    lifecycle.manage(new ManagedGuavaService(this));
}
 
Example #13
Source File: ListenerExecutor.java    From twill with Apache License 2.0 6 votes vote down vote up
@Override
public void running() {
  if (hasCalled(Service.State.RUNNING)) {
    return;
  }
  executor.execute(new Runnable() {
    @Override
    public void run() {
      try {
        delegate.running();
      } catch (Throwable t) {
        LOG.warn("Exception thrown from listener", t);
      }
    }
  });
}
 
Example #14
Source File: ListenerExecutor.java    From twill with Apache License 2.0 6 votes vote down vote up
@Override
public void starting() {
  if (hasCalled(Service.State.STARTING)) {
    return;
  }
  executor.execute(new Runnable() {
    @Override
    public void run() {
      try {
        delegate.starting();
      } catch (Throwable t) {
        LOG.warn("Exception thrown from listener", t);
      }
    }
  });
}
 
Example #15
Source File: Services.java    From twill with Apache License 2.0 6 votes vote down vote up
/**
 * Returns a {@link Runnable} that can be used as a {@link ListenableFuture} listener to trigger
 * further service action or completing the result future. Used by
 * {@link #doChain(boolean, com.google.common.util.concurrent.Service, com.google.common.util.concurrent.Service...)}
 */
private static Runnable createChainListener(final ListenableFuture<Service.State> future, final Service[] services,
                                            final AtomicInteger idx,
                                            final List<ListenableFuture<Service.State>> result,
                                            final SettableFuture<List<ListenableFuture<Service.State>>> resultFuture,
                                            final boolean doStart) {
  return new Runnable() {

    @Override
    public void run() {
      result.add(future);
      int nextIdx = idx.getAndIncrement();
      if (nextIdx == services.length) {
        resultFuture.set(result);
        return;
      }
      ListenableFuture<Service.State> actionFuture = doStart ? services[nextIdx].start() : services[nextIdx].stop();
      actionFuture.addListener(createChainListener(actionFuture, services, idx, result, resultFuture, doStart),
                               Threads.SAME_THREAD_EXECUTOR);
    }
  };
}
 
Example #16
Source File: StandardGobblinInstanceDriver.java    From incubator-gobblin with Apache License 2.0 6 votes vote down vote up
protected StandardGobblinInstanceDriver(String instanceName, Configurable sysConfig,
    JobCatalog jobCatalog,
    JobSpecScheduler jobScheduler, JobExecutionLauncher jobLauncher,
    Optional<MetricContext> instanceMetricContext,
    Optional<Logger> log,
    List<GobblinInstancePluginFactory> plugins,
    SharedResourcesBroker<GobblinScopeTypes> instanceBroker) {
  super(instanceName, sysConfig, jobCatalog, jobScheduler, jobLauncher, instanceMetricContext, log, instanceBroker);
  List<Service> componentServices = new ArrayList<>();

  checkComponentService(getJobCatalog(), componentServices);
  checkComponentService(getJobScheduler(), componentServices);
  checkComponentService(getJobLauncher(), componentServices);

  _plugins = createPlugins(plugins, componentServices);

  if (componentServices.size() > 0) {
    _subservices = new ServiceManager(componentServices);
  }
}
 
Example #17
Source File: LeaderServiceTest.java    From curator-extensions with Apache License 2.0 5 votes vote down vote up
/** Verify that leadership is re-acquired after the connection to ZooKeeper is lost. */
@Test
public void testLostZooKeeperConnection() throws Exception {
    int reacquireDelayMillis = 1500;
    ServiceTriggers triggers1 = new ServiceTriggers();
    ServiceTriggers triggers2 = new ServiceTriggers();
    ServiceTimer timer1 = new ServiceTimer();
    ServiceTimer timer2 = new ServiceTimer();
    List<Event> events = Collections.synchronizedList(new ArrayList<>());
    Service leader = newLeaderService(reacquireDelayMillis, TimeUnit.MILLISECONDS, supply(
            triggers1.listenTo(timer1.listenTo(trackEvents("1", events, new NopService()))),
            triggers2.listenTo(timer2.listenTo(trackEvents("2", events, new NopService())))));

    leader.startAsync();
    assertTrue(triggers1.getRunning().firedWithin(1, TimeUnit.MINUTES));

    killSession(_curator);
    assertTrue(triggers1.getTerminated().firedWithin(1, TimeUnit.MINUTES));
    assertTrue(triggers2.getRunning().firedWithin(1, TimeUnit.MINUTES));

    leader.stopAsync();
    assertTrue(triggers2.getTerminated().firedWithin(1, TimeUnit.MINUTES));

    // Verify sequence of events, no overlap between service instances.
    assertEquals(ImmutableList.of(
            new Event("1", Service.State.STARTING),
            new Event("1", Service.State.RUNNING),
            new Event("1", Service.State.STOPPING),
            new Event("1", Service.State.TERMINATED),
            new Event("2", Service.State.STARTING),
            new Event("2", Service.State.RUNNING),
            new Event("2", Service.State.STOPPING),
            new Event("2", Service.State.TERMINATED)
    ), events);

    // Verify that the re-acquire delay was observed
    long actualDelayMillis = timer2.getStartedAt() - timer1.getStoppedAt();
    assertTrue("Re-acquire delay was not observed: " + actualDelayMillis, actualDelayMillis >= reacquireDelayMillis);
}
 
Example #18
Source File: CompositeServiceTest.java    From twill with Apache License 2.0 5 votes vote down vote up
@Test
public void testErrorStart() throws InterruptedException {
  List<Service> services = Lists.newArrayList();

  // Create 5 services. The forth one will got a start failure.
  Semaphore semaphore = new Semaphore(0);
  for (int i = 0; i < 5; i++) {
    services.add(new TestService(semaphore, i, i == 3));
  }

  Service service = new CompositeService(services);
  try {
    service.start().get();
    Assert.fail();
  } catch (ExecutionException e) {
    // Expected
  }

  // Verify all services are not in running state
  Assert.assertTrue(Iterables.all(services, Predicates.not(serviceStatePredicate(Service.State.RUNNING))));

  // There should be one service in error state
  Assert.assertTrue(Iterables.removeIf(services, serviceStatePredicate(Service.State.FAILED)));

  for (Service s : services) {
    Assert.assertNotEquals(3, ((TestService) s).getOrder());
  }
}
 
Example #19
Source File: MRHistoryJobApplicationProvider.java    From eagle with Apache License 2.0 5 votes vote down vote up
@Override
public Optional<List<Service>> getSharedServices(Config envConfig) {
    if (envConfig.hasPath(MRHistoryJobDailyReporter.SERVICE_PATH)) {
        return Optional.of(Collections.singletonList(new MRHistoryJobDailyReporter(envConfig)));
    } else {
        return Optional.empty();
    }
}
 
Example #20
Source File: OstrichOwnerGroup.java    From emodb with Apache License 2.0 5 votes vote down vote up
private void stopService(String name, Optional<? extends Service> ref) {
    if (ref.isPresent()) {
        Service service = ref.get();
        _log.info("Stopping owned service {}: {}", _group, name);
        service.stop();
    }
}
 
Example #21
Source File: WalletSettingsController.java    From devcoretalk with GNU General Public License v2.0 5 votes vote down vote up
public void restoreClicked(ActionEvent event) {
    // Don't allow a restore unless this wallet is presently empty. We don't want to end up with two wallets, too
    // much complexity, even though WalletAppKit will keep the current one as a backup file in case of disaster.
    if (Main.bitcoin.wallet().getBalance().value > 0) {
        informationalAlert("Wallet is not empty",
                "You must empty this wallet out before attempting to restore an older one, as mixing wallets " +
                        "together can lead to invalidated backups.");
        return;
    }

    if (aesKey != null) {
        // This is weak. We should encrypt the new seed here.
        informationalAlert("Wallet is encrypted",
                "After restore, the wallet will no longer be encrypted and you must set a new password.");
    }

    log.info("Attempting wallet restore using seed '{}' from date {}", wordsArea.getText(), datePicker.getValue());
    informationalAlert("Wallet restore in progress",
            "Your wallet will now be resynced from the Bitcoin network. This can take a long time for old wallets.");
    overlayUI.done();
    Main.instance.controller.restoreFromSeedAnimation();

    long birthday = datePicker.getValue().atStartOfDay().toEpochSecond(ZoneOffset.UTC);
    DeterministicSeed seed = new DeterministicSeed(Splitter.on(' ').splitToList(wordsArea.getText()), null, "", birthday);
    // Shut down bitcoinj and restart it with the new seed.
    Main.bitcoin.addListener(new Service.Listener() {
        @Override
        public void terminated(Service.State from) {
            Main.instance.setupWalletKit(seed);
            Main.bitcoin.startAsync();
        }
    }, Platform::runLater);
    Main.bitcoin.stopAsync();
}
 
Example #22
Source File: MainController.java    From cate with MIT License 5 votes vote down vote up
/**
 * Handle a network service failing.
 *
 * @param network the service which failed.
 * @param from the status the service was in before it failed.
 * @param thrwbl the exception causing the service to fail.
 */
public void onNetworkFailed(Network network, Service.State from, Throwable thrwbl) {
    networks.remove(network);
    Platform.runLater(() -> {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setTitle(resources.getString("internalError.title"));
        alert.setContentText(thrwbl.getMessage());
        alert.showAndWait();
    });
}
 
Example #23
Source File: ControllerTest.java    From twill with Apache License 2.0 5 votes vote down vote up
@Test
public void testController() throws ExecutionException, InterruptedException, TimeoutException {
  InMemoryZKServer zkServer = InMemoryZKServer.builder().build();
  zkServer.startAndWait();

  LOG.info("ZKServer: " + zkServer.getConnectionStr());

  try {
    RunId runId = RunIds.generate();
    ZKClientService zkClientService = ZKClientService.Builder.of(zkServer.getConnectionStr()).build();
    zkClientService.startAndWait();

    Service service = createService(zkClientService, runId);
    service.startAndWait();

    TwillController controller = getController(zkClientService, "testController", runId);
    controller.sendCommand(Command.Builder.of("test").build()).get(2, TimeUnit.SECONDS);
    controller.terminate().get(2, TimeUnit.SECONDS);

    final CountDownLatch terminateLatch = new CountDownLatch(1);
    service.addListener(new ServiceListenerAdapter() {
      @Override
      public void terminated(Service.State from) {
        terminateLatch.countDown();
      }
    }, Threads.SAME_THREAD_EXECUTOR);

    Assert.assertTrue(service.state() == Service.State.TERMINATED || terminateLatch.await(2, TimeUnit.SECONDS));

    zkClientService.stopAndWait();

  } finally {
    zkServer.stopAndWait();
  }
}
 
Example #24
Source File: SchedulerServicesModule.java    From attic-aurora with Apache License 2.0 5 votes vote down vote up
@Provides
@Singleton
@AppStartup
ServiceManagerIface provideAppStartupServiceManager(
    @AppStartup Set<Service> services,
    LifecycleShutdownListener listener) {

  ServiceManager manager = new ServiceManager(services);
  manager.addListener(listener);
  return GuavaUtils.serviceManager(manager);
}
 
Example #25
Source File: ImportResourceIT.java    From usergrid with Apache License 2.0 5 votes vote down vote up
@BeforeClass
public static void setup() throws Exception {

    bucketPrefix = System.getProperty("bucketName");

    // start the scheduler after we're all set up
    JobSchedulerService jobScheduler = ConcurrentProcessSingleton.getInstance()
        .getSpringResource().getBean( JobSchedulerService.class );

    if (jobScheduler.state() != Service.State.RUNNING) {
        jobScheduler.startAsync();
        jobScheduler.awaitRunning();
    }

}
 
Example #26
Source File: LeaderServiceTest.java    From curator-extensions with Apache License 2.0 5 votes vote down vote up
/** Test starting multiple instances that compete for leadership. */
@Test
public void testMultipleLeaders() throws Exception {
    final Trigger started = new Trigger();
    final AtomicInteger startCount = new AtomicInteger();
    for (int i = 0; i < 5; i++) {
        newLeaderService(1, TimeUnit.HOURS, new Supplier<Service>() {
            @Override
            public Service get() {
                return new AbstractIdleService() {
                    @Override
                    protected void startUp() throws Exception {
                        started.fire();
                        startCount.incrementAndGet();
                    }

                    @Override
                    protected void shutDown() throws Exception {
                        // Do nothing
                    }
                };
            }
        }).startAsync();
    }
    assertTrue(started.firedWithin(1, TimeUnit.MINUTES));
    // We know one service has started.  Wait a little while and verify no more services are started.
    Thread.sleep(250);
    assertTrue(startCount.get() == 1);
}
 
Example #27
Source File: LeaderServiceTask.java    From emodb with Apache License 2.0 5 votes vote down vote up
private String describeState(Service.State state, boolean hasLeadership) {
    if (state == Service.State.RUNNING && !hasLeadership) {
        return "waiting to win leadership election";
    } else {
        return state.name();
    }
}
 
Example #28
Source File: LoggingPartitionedService.java    From emodb with Apache License 2.0 5 votes vote down vote up
private Service createServiceForPartition(final int partition) {
    return new AbstractService() {
        private ExecutorService _service;
        private CountDownLatch _latch = new CountDownLatch(1);

        @Override
        protected void doStart() {
            _service = Executors.newSingleThreadExecutor(
                    new ThreadFactoryBuilder().setNameFormat(String.format("%s-%d-%%d", _serviceName, partition)).build());
            _service.submit(() -> {
                _log.info("{}-{}: Service started", _serviceName, partition);
                _ownedPartitions.incrementAndGet();
                try {
                    while (!_service.isShutdown()) {
                        try {
                            _latch.await(5, TimeUnit.SECONDS);
                        } catch (InterruptedException e) {
                            if (!_service.isShutdown()) {
                                _log.info("{}-{}: Service thread interrupted prior to shutdown", _serviceName, partition);
                            }
                        }
                    }
                } finally {
                    _log.info("{}-{}: Service terminating", _serviceName, partition);
                    _ownedPartitions.decrementAndGet();
                }
            });
            notifyStarted();
        }

        @Override
        protected void doStop() {
            _latch.countDown();
            _service.shutdown();
            notifyStopped();
        }
    };
}
 
Example #29
Source File: SingleTaskRunner.java    From incubator-gobblin with Apache License 2.0 5 votes vote down vote up
private void initServices() {
  final Properties properties = ConfigUtils.configToProperties(this.clusterConfig);
  this.taskExecutor = new TaskExecutor(properties);
  this.taskStateTracker = new GobblinHelixTaskStateTracker(properties);

  final List<Service> services = Lists.newArrayList(this.taskExecutor, this.taskStateTracker);
  this.serviceManager = new ServiceManager(services);
}
 
Example #30
Source File: CompositeServiceTest.java    From twill with Apache License 2.0 5 votes vote down vote up
@Test
public void testOrder() throws InterruptedException, ExecutionException, TimeoutException {
  List<Service> services = Lists.newArrayList();

  // Start 10 services and check their start sequence is ordered.
  Semaphore semaphore = new Semaphore(0);
  for (int i = 0; i < 10; i++) {
    services.add(new TestService(semaphore, i));
  }

  Service service = new CompositeService(services);
  service.start().get(5, TimeUnit.SECONDS);

  // There should be 10 permits after all 10 services started
  Assert.assertTrue(semaphore.tryAcquire(10, 5, TimeUnit.SECONDS));

  // Check all services are running
  Assert.assertTrue(Iterables.all(services, serviceStatePredicate(Service.State.RUNNING)));

  // Release 10 permits for the stop sequence to start
  semaphore.release(10);
  service.stop().get(5, TimeUnit.SECONDS);

  // There should be no permit left after all 10 services stopped
  Assert.assertFalse(semaphore.tryAcquire(10));

  // Check all services are stopped
  Assert.assertTrue(Iterables.all(services, serviceStatePredicate(Service.State.TERMINATED)));
}