Java Code Examples for org.agrona.CloseHelper#quietClose()

The following examples show how to use org.agrona.CloseHelper#quietClose() . 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: AeronArchive.java    From aeron with Apache License 2.0 6 votes vote down vote up
/**
 * Add an {@link ExclusivePublication} and set it up to be recorded.
 * <p>
 * This is a sessionId specific recording.
 *
 * @param channel  for the publication.
 * @param streamId for the publication.
 * @return the {@link ExclusivePublication} ready for use.
 */
public ExclusivePublication addRecordedExclusivePublication(final String channel, final int streamId)
{
    ExclusivePublication publication = null;
    lock.lock();
    try
    {
        ensureOpen();
        ensureNotReentrant();

        publication = aeron.addExclusivePublication(channel, streamId);
        startRecording(ChannelUri.addSessionId(channel, publication.sessionId()), streamId, SourceLocation.LOCAL);
    }
    catch (final RuntimeException ex)
    {
        CloseHelper.quietClose(publication);
        throw ex;
    }
    finally
    {
        lock.unlock();
    }

    return publication;
}
 
Example 2
Source File: ParameterServerNode.java    From nd4j with Apache License 2.0 6 votes vote down vote up
/**
 * Stop the server
 * @throws Exception
 */
@Override
public void close() throws Exception {
    if (subscriber != null) {
        for (int i = 0; i < subscriber.length; i++) {
            if (subscriber[i] != null) {
                subscriber[i].close();
            }
        }
    }
    if (server != null)
        server.stop();
    if (mediaDriver != null)
        CloseHelper.quietClose(mediaDriver);
    if (aeron != null)
        CloseHelper.quietClose(aeron);

}
 
Example 3
Source File: BaseTransport.java    From deeplearning4j with Apache License 2.0 5 votes vote down vote up
protected void shutdownSilent() {
    log.info("Shutting down Aeron infrastructure...");
    CloseHelper.quietClose(publicationForClients);
    CloseHelper.quietClose(publicationForShards);
    CloseHelper.quietClose(subscriptionForShards);
    CloseHelper.quietClose(subscriptionForClients);
    CloseHelper.quietClose(aeron);
    CloseHelper.quietClose(context);
    CloseHelper.quietClose(driver);
}
 
Example 4
Source File: BenchServer.java    From rpc-bench with Apache License 2.0 5 votes vote down vote up
public void shutdown() throws InterruptedException {
  CloseHelper.quietClose(subscription);
  CloseHelper.quietClose(publication);
  CloseHelper.quietClose(aeron);
  CloseHelper.quietClose(ctx);
  CloseHelper.quietClose(driver);
}
 
Example 5
Source File: AeronArchive.java    From aeron with Apache License 2.0 5 votes vote down vote up
/**
 * Add a {@link Publication} and set it up to be recorded. If this is not the first,
 * i.e. {@link Publication#isOriginal()} is true, then an {@link ArchiveException}
 * will be thrown and the recording not initiated.
 * <p>
 * This is a sessionId specific recording.
 *
 * @param channel  for the publication.
 * @param streamId for the publication.
 * @return the {@link Publication} ready for use.
 */
public Publication addRecordedPublication(final String channel, final int streamId)
{
    Publication publication = null;
    lock.lock();
    try
    {
        ensureOpen();
        ensureNotReentrant();

        publication = aeron.addPublication(channel, streamId);
        if (!publication.isOriginal())
        {
            throw new ArchiveException(
                "publication already added for channel=" + channel + " streamId=" + streamId);
        }

        startRecording(ChannelUri.addSessionId(channel, publication.sessionId()), streamId, SourceLocation.LOCAL);
    }
    catch (final RuntimeException ex)
    {
        CloseHelper.quietClose(publication);
        throw ex;
    }
    finally
    {
        lock.unlock();
    }

    return publication;
}
 
Example 6
Source File: ParameterServerSubscriber.java    From deeplearning4j with Apache License 2.0 5 votes vote down vote up
@Override
public void close() {
    if (subscriber != null)
        CloseHelper.quietClose(subscriber);
    if (responder != null)
        CloseHelper.quietClose(responder);
    if (scheduledExecutorService != null)
        scheduledExecutorService.shutdown();
}
 
Example 7
Source File: BasicSubscriber.java    From aeron with Apache License 2.0 5 votes vote down vote up
public static void main(final String[] args)
{
    System.out.println("Subscribing to " + CHANNEL + " on stream id " + STREAM_ID);

    final MediaDriver driver = EMBEDDED_MEDIA_DRIVER ? MediaDriver.launchEmbedded() : null;
    final Aeron.Context ctx = new Aeron.Context()
        .availableImageHandler(SamplesUtil::printAvailableImage)
        .unavailableImageHandler(SamplesUtil::printUnavailableImage);

    if (EMBEDDED_MEDIA_DRIVER)
    {
        ctx.aeronDirectoryName(driver.aeronDirectoryName());
    }

    final FragmentHandler fragmentHandler = SamplesUtil.printStringMessage(STREAM_ID);
    final AtomicBoolean running = new AtomicBoolean(true);

    // Register a SIGINT handler for graceful shutdown.
    SigInt.register(() -> running.set(false));

    // Create an Aeron instance using the configured Context and create a
    // Subscription on that instance that subscribes to the configured
    // channel and stream ID.
    // The Aeron and Subscription classes implement "AutoCloseable" and will automatically
    // clean up resources when this try block is finished
    try (Aeron aeron = Aeron.connect(ctx);
        Subscription subscription = aeron.addSubscription(CHANNEL, STREAM_ID))
    {
        SamplesUtil.subscriberLoop(fragmentHandler, FRAGMENT_COUNT_LIMIT, running).accept(subscription);

        System.out.println("Shutting down...");
    }

    CloseHelper.quietClose(driver);
}
 
Example 8
Source File: ParameterServerSubscriber.java    From nd4j with Apache License 2.0 5 votes vote down vote up
@Override
public void close() {
    if (subscriber != null)
        CloseHelper.quietClose(subscriber);
    if (responder != null)
        CloseHelper.quietClose(responder);
    if (scheduledExecutorService != null)
        scheduledExecutorService.shutdown();
}
 
Example 9
Source File: LargeNdArrayIpcTest.java    From nd4j with Apache License 2.0 4 votes vote down vote up
@After
public void after() {
    CloseHelper.quietClose(mediaDriver);
}
 
Example 10
Source File: NdArrayIpcTest.java    From nd4j with Apache License 2.0 4 votes vote down vote up
@After
public void after() {
    CloseHelper.quietClose(mediaDriver);
}
 
Example 11
Source File: NdArrayIpcTest.java    From deeplearning4j with Apache License 2.0 4 votes vote down vote up
@After
public void after() {
    if(isIntegrationTests()) {
        CloseHelper.quietClose(mediaDriver);
    }
}
 
Example 12
Source File: StreamingPublisher.java    From aeron with Apache License 2.0 4 votes vote down vote up
public static void main(final String[] args) throws Exception
{
    if (MESSAGE_LENGTH < SIZE_OF_LONG)
    {
        throw new IllegalArgumentException("Message length must be at least " + SIZE_OF_LONG + " bytes");
    }

    final MediaDriver driver = EMBEDDED_MEDIA_DRIVER ? MediaDriver.launchEmbedded() : null;
    final Aeron.Context context = new Aeron.Context();

    if (EMBEDDED_MEDIA_DRIVER)
    {
        context.aeronDirectoryName(driver.aeronDirectoryName());
    }

    final RateReporter reporter = new RateReporter(TimeUnit.SECONDS.toNanos(1), StreamingPublisher::printRate);
    final ExecutorService executor = Executors.newFixedThreadPool(1);

    executor.execute(reporter);

    // Connect to media driver and add publication to send messages on the configured channel and stream ID.
    // The Aeron and Publication classes implement AutoCloseable, and will automatically
    // clean up resources when this try block is finished.
    try (Aeron aeron = Aeron.connect(context);
        Publication publication = aeron.addPublication(CHANNEL, STREAM_ID))
    {
        final ContinueBarrier barrier = new ContinueBarrier("Execute again?");
        final IdleStrategy idleStrategy = SampleConfiguration.newIdleStrategy();

        do
        {
            printingActive = true;

            System.out.format(
                "%nStreaming %,d messages of%s size %d bytes to %s on stream id %d%n",
                NUMBER_OF_MESSAGES,
                RANDOM_MESSAGE_LENGTH ? " random" : "",
                MESSAGE_LENGTH,
                CHANNEL,
                STREAM_ID);

            long backPressureCount = 0;

            for (long i = 0; i < NUMBER_OF_MESSAGES; i++)
            {
                final int length = LENGTH_GENERATOR.getAsInt();

                OFFER_BUFFER.putLong(0, i);
                idleStrategy.reset();
                while (publication.offer(OFFER_BUFFER, 0, length, null) < 0L)
                {
                    // The offer failed, which is usually due to the publication
                    // being temporarily blocked.  Retry the offer after a short
                    // spin/yield/sleep, depending on the chosen IdleStrategy.
                    backPressureCount++;
                    idleStrategy.idle();
                }

                reporter.onMessage(length);
            }

            System.out.println(
                "Done streaming. Back pressure ratio " + ((double)backPressureCount / NUMBER_OF_MESSAGES));

            if (LINGER_TIMEOUT_MS > 0)
            {
                System.out.println("Lingering for " + LINGER_TIMEOUT_MS + " milliseconds...");
                Thread.sleep(LINGER_TIMEOUT_MS);
            }

            printingActive = false;
        }
        while (barrier.await());
    }

    reporter.halt();
    executor.shutdown();
    CloseHelper.quietClose(driver);
}
 
Example 13
Source File: BasicPublisher.java    From aeron with Apache License 2.0 4 votes vote down vote up
public static void main(final String[] args) throws Exception
{
    System.out.println("Publishing to " + CHANNEL + " on stream id " + STREAM_ID);

    // If configured to do so, create an embedded media driver within this application rather
    // than relying on an external one.
    final MediaDriver driver = EMBEDDED_MEDIA_DRIVER ? MediaDriver.launchEmbedded() : null;

    final Aeron.Context ctx = new Aeron.Context();
    if (EMBEDDED_MEDIA_DRIVER)
    {
        ctx.aeronDirectoryName(driver.aeronDirectoryName());
    }

    // Connect a new Aeron instance to the media driver and create a publication on
    // the given channel and stream ID.
    // The Aeron and Publication classes implement "AutoCloseable" and will automatically
    // clean up resources when this try block is finished
    try (Aeron aeron = Aeron.connect(ctx);
        Publication publication = aeron.addPublication(CHANNEL, STREAM_ID))
    {
        for (long i = 0; i < NUMBER_OF_MESSAGES; i++)
        {
            final String message = "Hello World! " + i;
            final byte[] messageBytes = message.getBytes();
            BUFFER.putBytes(0, messageBytes);

            System.out.print("Offering " + i + "/" + NUMBER_OF_MESSAGES + " - ");

            final long result = publication.offer(BUFFER, 0, messageBytes.length);

            if (result < 0L)
            {
                if (result == Publication.BACK_PRESSURED)
                {
                    System.out.println("Offer failed due to back pressure");
                }
                else if (result == Publication.NOT_CONNECTED)
                {
                    System.out.println("Offer failed because publisher is not connected to subscriber");
                }
                else if (result == Publication.ADMIN_ACTION)
                {
                    System.out.println("Offer failed because of an administration action in the system");
                }
                else if (result == Publication.CLOSED)
                {
                    System.out.println("Offer failed publication is closed");
                    break;
                }
                else if (result == Publication.MAX_POSITION_EXCEEDED)
                {
                    System.out.println("Offer failed due to publication reaching max position");
                    break;
                }
                else
                {
                    System.out.println("Offer failed due to unknown reason: " + result);
                }
            }
            else
            {
                System.out.println("yay!");
            }

            if (!publication.isConnected())
            {
                System.out.println("No active subscribers detected");
            }

            Thread.sleep(TimeUnit.SECONDS.toMillis(1));
        }

        System.out.println("Done sending.");

        if (LINGER_TIMEOUT_MS > 0)
        {
            System.out.println("Lingering for " + LINGER_TIMEOUT_MS + " milliseconds...");
            Thread.sleep(LINGER_TIMEOUT_MS);
        }
    }

    CloseHelper.quietClose(driver);
}
 
Example 14
Source File: RateSubscriber.java    From aeron with Apache License 2.0 4 votes vote down vote up
public static void main(final String[] args) throws Exception
{
    System.out.println("Subscribing to " + CHANNEL + " on stream id " + STREAM_ID);

    final MediaDriver driver = EMBEDDED_MEDIA_DRIVER ? MediaDriver.launchEmbedded() : null;
    final ExecutorService executor = Executors.newFixedThreadPool(1);
    final Aeron.Context ctx = new Aeron.Context()
        .availableImageHandler(SamplesUtil::printAvailableImage)
        .unavailableImageHandler(SamplesUtil::printUnavailableImage);

    if (EMBEDDED_MEDIA_DRIVER)
    {
        ctx.aeronDirectoryName(driver.aeronDirectoryName());
    }

    final RateReporter reporter = new RateReporter(TimeUnit.SECONDS.toNanos(1), SamplesUtil::printRate);
    final AtomicBoolean running = new AtomicBoolean(true);

    SigInt.register(() ->
    {
        reporter.halt();
        running.set(false);
    });

    try (Aeron aeron = Aeron.connect(ctx);
        Subscription subscription = aeron.addSubscription(CHANNEL, STREAM_ID))
    {
        final Future<?> future = executor.submit(() -> SamplesUtil.subscriberLoop(
            rateReporterHandler(reporter), FRAGMENT_COUNT_LIMIT, running).accept(subscription));

        reporter.run();

        System.out.println("Shutting down...");
        future.get();
    }

    executor.shutdown();
    if (!executor.awaitTermination(5, TimeUnit.SECONDS))
    {
        System.out.println("Warning: not all tasks completed promptly");
    }

    CloseHelper.quietClose(driver);
}
 
Example 15
Source File: Ping.java    From aeron with Apache License 2.0 4 votes vote down vote up
public static void main(final String[] args) throws Exception
{
    final MediaDriver driver = EMBEDDED_MEDIA_DRIVER ? MediaDriver.launchEmbedded() : null;
    final Aeron.Context ctx = new Aeron.Context().availableImageHandler(Ping::availablePongImageHandler);
    final FragmentHandler fragmentHandler = new FragmentAssembler(Ping::pongHandler);

    if (EMBEDDED_MEDIA_DRIVER)
    {
        ctx.aeronDirectoryName(driver.aeronDirectoryName());
    }

    System.out.println("Publishing Ping at " + PING_CHANNEL + " on stream id " + PING_STREAM_ID);
    System.out.println("Subscribing Pong at " + PONG_CHANNEL + " on stream id " + PONG_STREAM_ID);
    System.out.println("Message length of " + MESSAGE_LENGTH + " bytes");
    System.out.println("Using exclusive publications " + EXCLUSIVE_PUBLICATIONS);

    try (Aeron aeron = Aeron.connect(ctx);
        Subscription subscription = aeron.addSubscription(PONG_CHANNEL, PONG_STREAM_ID);
        Publication publication = EXCLUSIVE_PUBLICATIONS ?
            aeron.addExclusivePublication(PING_CHANNEL, PING_STREAM_ID) :
            aeron.addPublication(PING_CHANNEL, PING_STREAM_ID))
    {
        System.out.println("Waiting for new image from Pong...");
        LATCH.await();

        System.out.println(
            "Warming up... " + WARMUP_NUMBER_OF_ITERATIONS +
            " iterations of " + WARMUP_NUMBER_OF_MESSAGES + " messages");

        for (int i = 0; i < WARMUP_NUMBER_OF_ITERATIONS; i++)
        {
            roundTripMessages(fragmentHandler, publication, subscription, WARMUP_NUMBER_OF_MESSAGES);
            Thread.yield();
        }

        Thread.sleep(100);
        final ContinueBarrier barrier = new ContinueBarrier("Execute again?");

        do
        {
            HISTOGRAM.reset();
            System.out.println("Pinging " + NUMBER_OF_MESSAGES + " messages");

            roundTripMessages(fragmentHandler, publication, subscription, NUMBER_OF_MESSAGES);
            System.out.println("Histogram of RTT latencies in microseconds.");

            HISTOGRAM.outputPercentileDistribution(System.out, 1000.0);
        }
        while (barrier.await());
    }

    CloseHelper.quietClose(driver);
}
 
Example 16
Source File: Pong.java    From aeron with Apache License 2.0 4 votes vote down vote up
public static void main(final String[] args)
{
    final MediaDriver driver = EMBEDDED_MEDIA_DRIVER ? MediaDriver.launchEmbedded() : null;

    final Aeron.Context ctx = new Aeron.Context();
    if (EMBEDDED_MEDIA_DRIVER)
    {
        ctx.aeronDirectoryName(driver.aeronDirectoryName());
    }

    if (INFO_FLAG)
    {
        ctx.availableImageHandler(SamplesUtil::printAvailableImage);
        ctx.unavailableImageHandler(SamplesUtil::printUnavailableImage);
    }

    final IdleStrategy idleStrategy = new BusySpinIdleStrategy();

    System.out.println("Subscribing Ping at " + PING_CHANNEL + " on stream id " + PING_STREAM_ID);
    System.out.println("Publishing Pong at " + PONG_CHANNEL + " on stream id " + PONG_STREAM_ID);
    System.out.println("Using exclusive publications " + EXCLUSIVE_PUBLICATIONS);

    final AtomicBoolean running = new AtomicBoolean(true);
    SigInt.register(() -> running.set(false));

    try (Aeron aeron = Aeron.connect(ctx);
        Subscription subscription = aeron.addSubscription(PING_CHANNEL, PING_STREAM_ID);
        Publication publication = EXCLUSIVE_PUBLICATIONS ?
            aeron.addExclusivePublication(PONG_CHANNEL, PONG_STREAM_ID) :
            aeron.addPublication(PONG_CHANNEL, PONG_STREAM_ID))
    {
        final BufferClaim bufferClaim = new BufferClaim();
        final FragmentHandler fragmentHandler = (buffer, offset, length, header) ->
            pingHandler(bufferClaim, publication, buffer, offset, length, header);

        while (running.get())
        {
            idleStrategy.idle(subscription.poll(fragmentHandler, FRAME_COUNT_LIMIT));
        }

        System.out.println("Shutting down...");
    }

    CloseHelper.quietClose(driver);
}
 
Example 17
Source File: AeronNDArrayPublisher.java    From nd4j with Apache License 2.0 3 votes vote down vote up
/**
 * Closes this resource, relinquishing any underlying resources.
 * This method is invoked automatically on objects managed by the
 * {@code try}-with-resources statement.
 * <p>
 * <p>While this interface method is declared to throw {@code
 * Exception}, implementers are <em>strongly</em> encouraged to
 * declare concrete implementations of the {@code close} method to
 * throw more specific exceptions, or to throw no exception at all
 * if the close operation cannot fail.
 * <p>
 * <p> Cases where the close operation may fail require careful
 * attention by implementers. It is strongly advised to relinquish
 * the underlying resources and to internally <em>mark</em> the
 * resource as closed, prior to throwing the exception. The {@code
 * close} method is unlikely to be invoked more than once and so
 * this ensures that the resources are released in a timely manner.
 * Furthermore it reduces problems that could arise when the resource
 * wraps, or is wrapped, by another resource.
 * <p>
 * <p><em>Implementers of this interface are also strongly advised
 * to not have the {@code close} method throw {@link
 * InterruptedException}.</em>
 * <p>
 * This exception interacts with a thread's interrupted status,
 * and runtime misbehavior is likely to occur if an {@code
 * InterruptedException} is {@linkplain Throwable#addSuppressed
 * suppressed}.
 * <p>
 * More generally, if it would cause problems for an
 * exception to be suppressed, the {@code AutoCloseable.close}
 * method should not throw it.
 * <p>
 * <p>Note that unlike the {@link Closeable#close close}
 * method of {@link Closeable}, this {@code close} method
 * is <em>not</em> required to be idempotent.  In other words,
 * calling this {@code close} method more than once may have some
 * visible side effect, unlike {@code Closeable.close} which is
 * required to have no effect if called more than once.
 * <p>
 * However, implementers of this interface are strongly encouraged
 * to make their {@code close} methods idempotent.
 *
 * @throws Exception if this resource cannot be closed
 */
@Override
public void close() throws Exception {
    if (publication != null) {
        CloseHelper.quietClose(publication);
    }

}
 
Example 18
Source File: HostPortPublisher.java    From deeplearning4j with Apache License 2.0 2 votes vote down vote up
/**
 * Closes this resource, relinquishing any underlying resources.
 * This method is invoked automatically on objects managed by the
 * {@code try}-with-resources statement.
 * <p>
 * <p>While this interface method is declared to throw {@code
 * Exception}, implementers are <em>strongly</em> encouraged to
 * declare concrete implementations of the {@code close} method to
 * throw more specific exceptions, or to throw no exception at all
 * if the close operation cannot fail.
 * <p>
 * <p> Cases where the close operation may fail require careful
 * attention by implementers. It is strongly advised to relinquish
 * the underlying resources and to internally <em>mark</em> the
 * resource as closed, prior to throwing the exception. The {@code
 * close} method is unlikely to be invoked more than once and so
 * this ensures that the resources are released in a timely manner.
 * Furthermore it reduces problems that could arise when the resource
 * wraps, or is wrapped, by another resource.
 * <p>
 * <p><em>Implementers of this interface are also strongly advised
 * to not have the {@code close} method throw {@link
 * InterruptedException}.</em>
 * <p>
 * This exception interacts with a thread's interrupted status,
 * and runtime misbehavior is likely to occur if an {@code
 * InterruptedException} is {@linkplain Throwable#addSuppressed
 * suppressed}.
 * <p>
 * More generally, if it would cause problems for an
 * exception to be suppressed, the {@code AutoCloseable.close}
 * method should not throw it.
 * <p>
 * <p>Note that unlike the {@link Closeable#close close}
 * method of {@link Closeable}, this {@code close} method
 * is <em>not</em> required to be idempotent.  In other words,
 * calling this {@code close} method more than once may have some
 * visible side effect, unlike {@code Closeable.close} which is
 * required to have no effect if called more than once.
 * <p>
 * However, implementers of this interface are strongly encouraged
 * to make their {@code close} methods idempotent.
 *
 * @throws Exception if this resource cannot be closed
 */
@Override
public void close() throws Exception {
    if (publication != null)
        CloseHelper.quietClose(publication);
}
 
Example 19
Source File: AeronNDArraySubscriber.java    From nd4j with Apache License 2.0 2 votes vote down vote up
/**
 * Closes this resource, relinquishing any underlying resources.
 * This method is invoked automatically on objects managed by the
 * {@code try}-with-resources statement.
 * <p>
 * <p>While this interface method is declared to throw {@code
 * Exception}, implementers are <em>strongly</em> encouraged to
 * declare concrete implementations of the {@code close} method to
 * throw more specific exceptions, or to throw no exception at all
 * if the close operation cannot fail.
 * <p>
 * <p> Cases where the close operation may fail require careful
 * attention by implementers. It is strongly advised to relinquish
 * the underlying resources and to internally <em>mark</em> the
 * resource as closed, prior to throwing the exception. The {@code
 * close} method is unlikely to be invoked more than once and so
 * this ensures that the resources are released in a timely manner.
 * Furthermore it reduces problems that could arise when the resource
 * wraps, or is wrapped, by another resource.
 * <p>
 * <p><em>Implementers of this interface are also strongly advised
 * to not have the {@code close} method throw {@link
 * InterruptedException}.</em>
 * <p>
 * This exception interacts with a thread's interrupted status,
 * and runtime misbehavior is likely to occur if an {@code
 * InterruptedException} is {@linkplain Throwable#addSuppressed
 * suppressed}.
 * <p>
 * More generally, if it would cause problems for an
 * exception to be suppressed, the {@code AutoCloseable.close}
 * method should not throw it.
 * <p>
 * <p>Note that unlike the {@link Closeable#close close}
 * method of {@link Closeable}, this {@code close} method
 * is <em>not</em> required to be idempotent.  In other words,
 * calling this {@code close} method more than once may have some
 * visible side effect, unlike {@code Closeable.close} which is
 * required to have no effect if called more than once.
 * <p>
 * However, implementers of this interface are strongly encouraged
 * to make their {@code close} methods idempotent.
 *
 * @throws Exception if this resource cannot be closed
 */
@Override
public void close() throws Exception {
    CloseHelper.quietClose(subscription);
}
 
Example 20
Source File: AeronNDArraySubscriber.java    From deeplearning4j with Apache License 2.0 2 votes vote down vote up
/**
 * Closes this resource, relinquishing any underlying resources.
 * This method is invoked automatically on objects managed by the
 * {@code try}-with-resources statement.
 * <p>
 * <p>While this interface method is declared to throw {@code
 * Exception}, implementers are <em>strongly</em> encouraged to
 * declare concrete implementations of the {@code close} method to
 * throw more specific exceptions, or to throw no exception at all
 * if the close operation cannot fail.
 * <p>
 * <p> Cases where the close operation may fail require careful
 * attention by implementers. It is strongly advised to relinquish
 * the underlying resources and to internally <em>mark</em> the
 * resource as closed, prior to throwing the exception. The {@code
 * close} method is unlikely to be invoked more than once and so
 * this ensures that the resources are released in a timely manner.
 * Furthermore it reduces problems that could arise when the resource
 * wraps, or is wrapped, by another resource.
 * <p>
 * <p><em>Implementers of this interface are also strongly advised
 * to not have the {@code close} method throw {@link
 * InterruptedException}.</em>
 * <p>
 * This exception interacts with a thread's interrupted status,
 * and runtime misbehavior is likely to occur if an {@code
 * InterruptedException} is {@linkplain Throwable#addSuppressed
 * suppressed}.
 * <p>
 * More generally, if it would cause problems for an
 * exception to be suppressed, the {@code AutoCloseable.close}
 * method should not throw it.
 * <p>
 * <p>Note that unlike the {@link Closeable#close close}
 * method of {@link Closeable}, this {@code close} method
 * is <em>not</em> required to be idempotent.  In other words,
 * calling this {@code close} method more than once may have some
 * visible side effect, unlike {@code Closeable.close} which is
 * required to have no effect if called more than once.
 * <p>
 * However, implementers of this interface are strongly encouraged
 * to make their {@code close} methods idempotent.
 *
 * @throws Exception if this resource cannot be closed
 */
@Override
public void close() throws Exception {
    CloseHelper.quietClose(subscription);
}