Example usage for com.google.common.util.concurrent SettableFuture isCancelled

List of usage examples for com.google.common.util.concurrent SettableFuture isCancelled

Introduction

In this page you can find the example usage for com.google.common.util.concurrent SettableFuture isCancelled.

Prototype

@Override
    public boolean isCancelled() 

Source Link

Usage

From source file:com.spotify.futures.ConcurrencyLimiter.java

private void pump() {
    while (true) {
        if (!limit.tryAcquire()) {
            return;
        }/*from ww w.j a v a2s.  c  o  m*/

        final Job<T> job = queue.poll();
        if (job == null) {
            limit.release();
            return;
        }
        queueSize.decrementAndGet();

        final SettableFuture<T> response = job.response;

        if (response.isCancelled()) {
            limit.release();
            continue;
        }

        invoke(response, job.callable);
    }
}

From source file:io.flutter.plugins.googlesignin.BackgroundTaskRunner.java

/**
 * Executes the specified task in a background thread and returns a future with which the caller
 * can be notified of task completion.//from   w ww  . ja  v a 2 s . c om
 *
 * <p>Note: the future will be notified on the background thread. To be notified on the UI thread,
 * use {@link #runInBackground(Callable,Callback)}.
 */
public <T> ListenableFuture<T> runInBackground(final Callable<T> task) {
    final SettableFuture<T> future = SettableFuture.create();

    executor.execute(new Runnable() {
        @Override
        public void run() {
            if (!future.isCancelled()) {
                try {
                    future.set(task.call());
                } catch (Throwable t) {
                    future.setException(t);
                }
            }
        }
    });

    return future;
}

From source file:com.yahoo.yqlplus.engine.internal.java.runtime.TimeoutHandler.java

public <T> ListenableFuture<T> withTimeout(final ListenableFuture<T> source, long timeout,
        TimeUnit timeoutUnits) {/*ww  w .j  a  v  a 2 s . co m*/
    if (timeout != 0) {
        final SettableFuture<T> result = SettableFuture.create();
        final Future<?> scheduledFuture = timers
                .schedule(new TimeoutTask<T>(source, result, timeout, timeoutUnits), timeout, timeoutUnits);
        result.addListener(new Runnable() {
            @Override
            public void run() {
                scheduledFuture.cancel(false);
                if (result.isCancelled()) {
                    source.cancel(true);
                }
            }
        }, MoreExecutors.sameThreadExecutor());
        Futures.addCallback(source, new FutureCallback<T>() {
            @Override
            public void onSuccess(T out) {
                scheduledFuture.cancel(false);
                result.set(out);
            }

            @Override
            public void onFailure(Throwable t) {
                scheduledFuture.cancel(false);
                result.setException(t);
            }
        });
        return scoper.scopeCallbacks(result);
    } else {
        return source;
    }
}

From source file:com.yahoo.yqlplus.engine.internal.scope.ScopedTracingExecutor.java

public <T> ListenableFuture<T> withTimeout(final ListenableFuture<T> source, long timeout,
        TimeUnit timeoutUnits) {// w  w  w.  j a va2 s.c o m
    if (timeout != 0) {
        final SettableFuture<T> result = SettableFuture.create();
        final Future<?> scheduledFuture = timers
                .schedule(new TimeoutTask<T>(source, result, timeout, timeoutUnits), timeout, timeoutUnits);
        result.addListener(new Runnable() {
            @Override
            public void run() {
                scheduledFuture.cancel(false);
                if (result.isCancelled()) {
                    source.cancel(true);
                }
            }
        }, MoreExecutors.sameThreadExecutor());
        Futures.addCallback(source, new FutureCallback<T>() {
            @Override
            public void onSuccess(T out) {
                scheduledFuture.cancel(false);
                result.set(out);
            }

            @Override
            public void onFailure(Throwable t) {
                scheduledFuture.cancel(false);
                result.setException(t);
            }
        });
        return new WrappedListenableFuture<>(result);
    } else {
        return new WrappedListenableFuture<>(source);
    }
}

From source file:org.opendaylight.ovsdb.lib.impl.OvsdbClientImpl.java

private void populateSchema(final List<String> dbNames, final Map<String, DatabaseSchema> schema,
        final SettableFuture<Map<String, DatabaseSchema>> sfuture) {

    if (dbNames == null || dbNames.isEmpty()) {
        return;//from  ww w. j  a v a  2 s. c o  m
    }

    Futures.transform(rpc.get_schema(Lists.newArrayList(dbNames.get(0))),
            new com.google.common.base.Function<JsonNode, Void>() {
                @Override
                public Void apply(JsonNode jsonNode) {
                    try {
                        schema.put(dbNames.get(0), DatabaseSchema.fromJson(dbNames.get(0), jsonNode));
                        if (schema.size() > 1 && !sfuture.isCancelled()) {
                            populateSchema(dbNames.subList(1, dbNames.size()), schema, sfuture);
                        } else if (schema.size() == 1) {
                            sfuture.set(schema);
                        }
                    } catch (Exception e) {
                        sfuture.setException(e);
                    }
                    return null;
                }
            });
}

From source file:org.usrz.libs.utils.concurrent.SimpleExecutor.java

public <T> NotifyingFuture<T> call(Callable<T> callable) {
    final SettableFuture<T> settableFuture = SettableFuture.create();

    final Future<T> executingFuture = executor.submit(() -> {
        try {/*  w w  w  .  jav  a  2  s  . co m*/
            final T result = callable.call();
            settableFuture.set(result);
            return result;
        } catch (Throwable throwable) {
            settableFuture.setException(throwable);
            throw new Exception(throwable);
        }
    });

    return new NotifyingFuture<T>() {

        @Override
        public boolean cancel(boolean mayInterruptIfRunning) {
            if (executingFuture.cancel(mayInterruptIfRunning)) {
                settableFuture.cancel(mayInterruptIfRunning);
                return true;
            } else {
                return false;
            }
        }

        @Override
        public boolean isCancelled() {
            return settableFuture.isCancelled();
        }

        @Override
        public boolean isDone() {
            return settableFuture.isCancelled();
        }

        @Override
        public T get() throws InterruptedException, ExecutionException {
            return settableFuture.get();
        }

        @Override
        public T get(long timeout, TimeUnit unit)
                throws InterruptedException, ExecutionException, TimeoutException {
            return settableFuture.get(timeout, unit);
        }

        @Override
        public NotifyingFuture<T> withConsumer(Consumer<Future<T>> consumer) {
            settableFuture.addListener(() -> consumer.accept(settableFuture), notifier);
            return this;
        }

    };
}

From source file:co.cask.cdap.internal.app.deploy.SandboxConfigurator.java

/**
 * Runs the <code>Application.configure()</code> in a sandbox JVM
 * with high level of security.//from  w ww. j ava  2 s  .  co  m
 *
 * @return An instance of {@link ListenableFuture}
 */
@Override
public ListenableFuture<ConfigResponse> config() {
    final SettableFuture<ConfigResponse> result = SettableFuture.create();
    final File outputFile;

    try {
        outputFile = File.createTempFile(PREFIX, EXT);

        // Run the command in seperate JVM.
        process = Runtime.getRuntime().exec(getCommand(outputFile));

        // Add future to handle the case when the future is cancelled.
        // OnSuccess, we don't do anything other than cleaning the output.
        // onFailure, we make sure that process is destroyed.
        Futures.addCallback(result, new FutureCallback<ConfigResponse>() {

            private void deleteOutput() {
                if (outputFile.exists()) {
                    outputFile.delete();
                }
            }

            @Override
            public void onSuccess(final ConfigResponse result) {
                // Delete the output file on delete.
                deleteOutput();
            }

            @Override
            public void onFailure(final Throwable t) {
                // In case the future was cancelled, we have to
                // destroy the process.
                if (result.isCancelled()) {
                    process.destroy();
                }
                deleteOutput();
            }
        });
    } catch (Exception e) {
        // Returns a {@code ListenableFuture} which has an exception set immediately
        // upon construction.
        return Futures.immediateFailedFuture(e);
    }

    // Start a thread that waits for command execution to complete or till it's cancelled.
    new Thread() {
        @Override
        public void run() {
            try {
                // Wait for process to exit and extract the return. If cancelled the process will
                // be shutdown.
                process.waitFor();
                int exit = process.exitValue();
                if (exit == 0) {
                    result.set(
                            new DefaultConfigResponse(0, Files.newReaderSupplier(outputFile, Charsets.UTF_8)));
                } else {
                    result.set(new DefaultConfigResponse(exit, null));
                }
            } catch (Exception e) {
                result.setException(e);
            }
        }
    }.start();

    return result;
}

From source file:org.caffinitas.ohc.linked.OHCacheImpl.java

public Future<V> getWithLoaderAsync(final K key, final CacheLoader<K, V> loader) {
    if (key == null)
        throw new NullPointerException();
    if (executorService == null || executorService.isShutdown() || closed)
        throw new IllegalStateException(
                "OHCache has no executor service - configure one via OHCacheBuilder.executorService()");

    final KeyBuffer keySource = keySource(key);

    final OffHeapMap segment = segment(keySource.hash());
    long hashEntryAdr = segment.getEntry(keySource, true);

    if (hashEntryAdr == 0L) {
        // this call is _likely_ the initial requestor for that key since there's no entry for the key

        final long keyLen = keySerializer.serializedSize(key);

        long bytes = Util.allocLen(keyLen, 0L);

        if ((maxEntrySize > 0L && bytes > maxEntrySize)
                || (hashEntryAdr = Uns.allocate(bytes, throwOOME)) == 0L) {
            // entry too large to be inserted or OS is not able to provide enough memory
            putFailCount++;//from   w  w  w. j av  a2 s .c o m

            remove(key);

            return Futures
                    .immediateFailedFuture(new RuntimeException("max entry size exceeded or malloc() failed"));
        }

        try {
            keySerializer.serialize(key, Uns.keyBuffer(hashEntryAdr, keyLen));
        } catch (Throwable e) {
            freeAndThrow(e, hashEntryAdr);
        }

        final long hash = hasher.hash(hashEntryAdr, Util.ENTRY_OFF_DATA, (int) keyLen);

        // initialize hash entry
        HashEntries.init(hash, keyLen, 0L, hashEntryAdr, Util.SENTINEL_LOADING);

        if (segment.putEntry(hashEntryAdr, hash, keyLen, bytes, true, 0L, 0L, 0L)) {
            // this request IS the initial requestor for the key

            final long sentinelHashEntryAdr = hashEntryAdr;
            return executorService.submit(new Callable<V>() {
                public V call() throws Exception {
                    Exception failure = null;
                    V value = null;
                    boolean replaced = false;

                    try {
                        value = loader.load(key);

                        long valueLen = valueSerializer.serializedSize(value);

                        long bytes = Util.allocLen(keyLen, valueLen);

                        long hashEntryAdr;
                        if ((maxEntrySize > 0L && bytes > maxEntrySize)
                                || (hashEntryAdr = Uns.allocate(bytes, throwOOME)) == 0L)
                            throw new RuntimeException("max entry size exceeded or malloc() failed");

                        long hash = serializeForPut(key, value, keyLen, valueLen, hashEntryAdr);

                        // initialize hash entry
                        HashEntries.init(hash, keyLen, valueLen, hashEntryAdr, Util.SENTINEL_NOT_PRESENT);

                        if (!segment.replaceEntry(hash, sentinelHashEntryAdr, hashEntryAdr, bytes))
                            throw new RuntimeException("not enough free capacity");
                        replaced = true;

                        HashEntries.setSentinel(sentinelHashEntryAdr, Util.SENTINEL_SUCCESS);
                        HashEntries.dereference(sentinelHashEntryAdr);
                    } catch (PermanentLoadException e) {
                        HashEntries.setSentinel(sentinelHashEntryAdr, Util.SENTINEL_PERMANENT_FAILURE);
                        throw e;
                    } catch (Throwable e) {
                        failure = e instanceof Exception ? (Exception) e : new RuntimeException(e);
                        HashEntries.setSentinel(sentinelHashEntryAdr, Util.SENTINEL_TEMPORARY_FAILURE);
                        if (replaced)
                            HashEntries.dereference(sentinelHashEntryAdr);
                        else
                            segment.removeEntry(sentinelHashEntryAdr);
                    }

                    if (failure != null)
                        throw failure;

                    return value;
                }
            });
        } else {
            // this request IS NOT the initial requestor for the key, so it must
            // free the unneeded but allocated sentinel

            Uns.free(hashEntryAdr);
        }

        // fall through
    }

    // this request IS NOT the initial requestor for the key
    // this request IS an adjacent requestor for the key

    // check if the value is already there (no sentinel) or has permanent failure status
    int sentinelStatus = HashEntries.getSentinel(hashEntryAdr);
    switch (sentinelStatus) {
    case Util.SENTINEL_NOT_PRESENT:
        try {
            return Futures.immediateFuture(valueSerializer.deserialize(Uns.valueBufferR(hashEntryAdr)));
        } finally {
            HashEntries.dereference(hashEntryAdr);
        }
    case Util.SENTINEL_PERMANENT_FAILURE:
        HashEntries.dereference(hashEntryAdr);
        return Futures.immediateFailedFuture(new PermanentLoadException());
    }

    // handle sentinel

    final SettableFuture<V> future = SettableFuture.create();

    final long sentinelHashEntryAdr = hashEntryAdr;

    // TODO / DOCUMENT: executorService shutdown with ongoing requests with referenced sentinel-entries --> off-heap memory leak
    // Reason:
    // The jobs started for adjacent getWithLoader*() calls are not running (and waiting) continuously.
    // Instead these are scheduled regularly and poll the referenced sentinel hash-entry.
    // The sentinel hash-entry is dereferenced within the following job for adjacent getWithLoader*() calls.
    // So - if the following job is no longer called, the sentinel hash-entry will never be dereferenced and
    // therefore never be deallocated.
    // Workaround is to close the OHCache instance, then wait some time and shutdown the scheduled executor service
    // when there are no more scheduled jobs.

    // The following job basically "spins" on the sentinel field of the sentinel hash-entry without
    // any lock on the segment.
    // It has two "exit" criterias:

    executorService.schedule(new Runnable() {
        public void run() {
            if (future.isCancelled() || closed) {
                HashEntries.dereference(sentinelHashEntryAdr);
                return;
            }

            int sentinelStatus = HashEntries.getSentinel(sentinelHashEntryAdr);
            switch (sentinelStatus) {
            // SENTINEL_NOT_PRESENT is an impossible status on the sentinel hash-entry
            case Util.SENTINEL_SUCCESS:
                break;
            case Util.SENTINEL_LOADING:
                reschedule(0L);
                return;
            case Util.SENTINEL_PERMANENT_FAILURE:
                failure(0L, new PermanentLoadException());
                return;
            case Util.SENTINEL_TEMPORARY_FAILURE:
                failure(0L, new TemporaryLoadException());
                return;
            default:
                failure(0L, new AssertionError("illegal sentinel value " + sentinelStatus));
                return;
            }

            long hashEntryAdr = segment.getEntry(keySource, true);

            if (hashEntryAdr == 0L) {
                // two possibilities that the entry does not exist:
                // - entry has been evicted (very very unlikely, so ignore this option)
                // - loader indicated temporary failure (very very likely)
                future.setException(new TemporaryLoadException());
            }

            if (hashEntryAdr == sentinelHashEntryAdr) {
                // oops, still the sentinel entry
                reschedule(0L);
                return;
            }

            sentinelStatus = HashEntries.getSentinel(hashEntryAdr);
            switch (sentinelStatus) {
            case Util.SENTINEL_NOT_PRESENT:
                try {
                    future.set(valueSerializer.deserialize(Uns.valueBufferR(hashEntryAdr)));
                    HashEntries.dereference(hashEntryAdr);
                    HashEntries.dereference(sentinelHashEntryAdr);
                } catch (Throwable e) {
                    failure(hashEntryAdr, e);
                }
                break;
            case Util.SENTINEL_SUCCESS:
            case Util.SENTINEL_LOADING:
                HashEntries.dereference(hashEntryAdr);
                reschedule(hashEntryAdr);
                break;
            case Util.SENTINEL_PERMANENT_FAILURE:
                failure(hashEntryAdr, new PermanentLoadException());
                break;
            case Util.SENTINEL_TEMPORARY_FAILURE:
                failure(hashEntryAdr, new TemporaryLoadException());
                break;
            default:
                failure(hashEntryAdr, new AssertionError("illegal sentinel value " + sentinelStatus));
                break;
            }
        }

        private void failure(long hashEntryAdr, Throwable e) {
            if (hashEntryAdr != 0L)
                HashEntries.dereference(hashEntryAdr);
            HashEntries.dereference(sentinelHashEntryAdr);
            future.setException(e);
        }

        private void reschedule(long hashEntryAdr) {
            try {
                executorService.schedule(this, 10, TimeUnit.MILLISECONDS);
            } catch (Throwable t) {
                failure(hashEntryAdr, t);
            }
        }
    }, 10, TimeUnit.MILLISECONDS);

    return future;
}

From source file:org.caffinitas.ohc.linked.OHCacheLinkedImpl.java

public Future<V> getWithLoaderAsync(final K key, final CacheLoader<K, V> loader, final long expireAt) {
    if (key == null)
        throw new NullPointerException();
    if (executorService == null || executorService.isShutdown() || closed)
        throw new IllegalStateException(
                "OHCache has no executor service - configure one via OHCacheBuilder.executorService()");

    final KeyBuffer keySource = keySource(key);

    final OffHeapLinkedMap segment = segment(keySource.hash());
    long hashEntryAdr = segment.getEntry(keySource, true, true);

    if (hashEntryAdr == 0L) {
        // this call is _likely_ the initial requestor for that key since there's no entry for the key

        final int keyLen = keySerializer.serializedSize(key);
        if (keyLen <= 0)
            throw new IllegalArgumentException("Illegal key length " + keyLen);

        long bytes = Util.allocLen(keyLen, 0L);

        if ((maxEntrySize > 0L && bytes > maxEntrySize)
                || (hashEntryAdr = Uns.allocate(bytes, throwOOME)) == 0L) {
            // entry too large to be inserted or OS is not able to provide enough memory
            putFailCount++;/*from w w w.  ja v a  2 s  .  c o m*/

            remove(key);

            return Futures
                    .immediateFailedFuture(new RuntimeException("max entry size exceeded or malloc() failed"));
        }

        try {
            keySerializer.serialize(key, Uns.keyBuffer(hashEntryAdr, keyLen));
        } catch (Throwable e) {
            freeAndThrow(e, hashEntryAdr);
        }

        final long hash = hasher.hash(hashEntryAdr, Util.ENTRY_OFF_DATA, keyLen);

        // initialize hash entry
        HashEntries.init(hash, keyLen, 0L, hashEntryAdr, Util.SENTINEL_LOADING, 0L);

        if (segment.putEntry(hashEntryAdr, hash, keyLen, bytes, true, 0L, 0L, 0L, 0L)) {
            // this request IS the initial requestor for the key

            final long sentinelHashEntryAdr = hashEntryAdr;
            return executorService.submit(new Callable<V>() {
                public V call() throws Exception {
                    Exception failure = null;
                    V value = null;
                    boolean derefSentinel = false;

                    try {
                        value = loader.load(key);

                        long entryExpireAt = expireAt;
                        if (value == null
                                || (entryExpireAt > 0L && entryExpireAt <= System.currentTimeMillis())) {
                            // If the value is null, it means the loaded could not
                            // already expired

                            segment.removeEntry(sentinelHashEntryAdr);

                            return null;
                        }

                        // not already expired

                        long valueLen = valueSerializer.serializedSize(value);
                        if (valueLen <= 0)
                            throw new IllegalArgumentException("Illegal value length " + valueLen);

                        long bytes = Util.allocLen(keyLen, valueLen);

                        long hashEntryAdr;
                        if ((maxEntrySize > 0L && bytes > maxEntrySize)
                                || (hashEntryAdr = Uns.allocate(bytes, throwOOME)) == 0L)
                            throw new RuntimeException("max entry size exceeded or malloc() failed");

                        long hash = serializeForPut(key, value, keyLen, valueLen, hashEntryAdr);
                        if (entryExpireAt == USE_DEFAULT_EXPIRE_AT)
                            entryExpireAt = defaultExpireAt();

                        // initialize hash entry
                        HashEntries.init(hash, keyLen, valueLen, hashEntryAdr, Util.SENTINEL_NOT_PRESENT,
                                entryExpireAt);

                        if (!segment.replaceEntry(hash, sentinelHashEntryAdr, hashEntryAdr, bytes,
                                entryExpireAt))
                            throw new RuntimeException("not enough free capacity");
                        derefSentinel = true;

                        HashEntries.setSentinel(sentinelHashEntryAdr, Util.SENTINEL_SUCCESS);
                        HashEntries.dereference(sentinelHashEntryAdr);
                    } catch (PermanentLoadException e) {
                        HashEntries.setSentinel(sentinelHashEntryAdr, Util.SENTINEL_PERMANENT_FAILURE);
                        throw e;
                    } catch (Throwable e) {
                        failure = e instanceof Exception ? (Exception) e : new RuntimeException(e);
                        HashEntries.setSentinel(sentinelHashEntryAdr, Util.SENTINEL_TEMPORARY_FAILURE);
                        if (derefSentinel)
                            HashEntries.dereference(sentinelHashEntryAdr);
                        else
                            segment.removeEntry(sentinelHashEntryAdr);
                    }

                    if (failure != null)
                        throw failure;

                    return value;
                }
            });
        } else {
            // this request IS NOT the initial requestor for the key, so it must
            // free the unneeded but allocated sentinel

            Uns.free(hashEntryAdr);
        }

        // fall through
    }

    // this request IS NOT the initial requestor for the key
    // this request IS an adjacent requestor for the key

    // check if the value is already there (no sentinel) or has permanent failure status
    int sentinelStatus = HashEntries.getSentinel(hashEntryAdr);
    switch (sentinelStatus) {
    case Util.SENTINEL_NOT_PRESENT:
        try {
            return Futures.immediateFuture(valueSerializer.deserialize(Uns.valueBufferR(hashEntryAdr)));
        } finally {
            HashEntries.dereference(hashEntryAdr);
        }
    case Util.SENTINEL_PERMANENT_FAILURE:
        HashEntries.dereference(hashEntryAdr);
        return Futures.immediateFailedFuture(new PermanentLoadException());
    }

    // handle sentinel

    final SettableFuture<V> future = SettableFuture.create();

    final long sentinelHashEntryAdr = hashEntryAdr;

    // TODO / DOCUMENT: executorService shutdown with ongoing requests with referenced sentinel-entries --> off-heap memory leak
    // Reason:
    // The jobs started for adjacent getWithLoader*() calls are not running (and waiting) continuously.
    // Instead these are scheduled regularly and poll the referenced sentinel hash-entry.
    // The sentinel hash-entry is dereferenced within the following job for adjacent getWithLoader*() calls.
    // So - if the following job is no longer called, the sentinel hash-entry will never be dereferenced and
    // therefore never be deallocated.
    // Workaround is to close the OHCache instance, then wait some time and shutdown the scheduled executor service
    // when there are no more scheduled jobs.

    // The following job basically "spins" on the sentinel field of the sentinel hash-entry without
    // any lock on the segment.
    // It has two "exit" criterias:

    executorService.schedule(new Runnable() {
        public void run() {
            if (future.isCancelled() || closed) {
                HashEntries.dereference(sentinelHashEntryAdr);
                return;
            }

            int sentinelStatus = HashEntries.getSentinel(sentinelHashEntryAdr);
            switch (sentinelStatus) {
            // SENTINEL_NOT_PRESENT is an impossible status on the sentinel hash-entry
            case Util.SENTINEL_SUCCESS:
                break;
            case Util.SENTINEL_LOADING:
                reschedule(0L);
                return;
            case Util.SENTINEL_PERMANENT_FAILURE:
                failure(0L, new PermanentLoadException());
                return;
            case Util.SENTINEL_TEMPORARY_FAILURE:
                failure(0L, new TemporaryLoadException());
                return;
            default:
                failure(0L, new AssertionError("illegal sentinel value " + sentinelStatus));
                return;
            }

            long hashEntryAdr = segment.getEntry(keySource, true, true);

            if (hashEntryAdr == 0L) {
                // two possibilities that the entry does not exist:
                // - entry has been evicted (very very unlikely, so ignore this option)
                // - loader indicated temporary failure (very very likely)
                future.setException(new TemporaryLoadException());
            }

            if (hashEntryAdr == sentinelHashEntryAdr) {
                // oops, still the sentinel entry
                reschedule(0L);
                return;
            }

            sentinelStatus = HashEntries.getSentinel(hashEntryAdr);
            switch (sentinelStatus) {
            case Util.SENTINEL_NOT_PRESENT:
                try {
                    future.set(valueSerializer.deserialize(Uns.valueBufferR(hashEntryAdr)));
                    HashEntries.dereference(hashEntryAdr);
                    HashEntries.dereference(sentinelHashEntryAdr);
                } catch (Throwable e) {
                    failure(hashEntryAdr, e);
                }
                break;
            case Util.SENTINEL_SUCCESS:
            case Util.SENTINEL_LOADING:
                HashEntries.dereference(hashEntryAdr);
                reschedule(hashEntryAdr);
                break;
            case Util.SENTINEL_PERMANENT_FAILURE:
                failure(hashEntryAdr, new PermanentLoadException());
                break;
            case Util.SENTINEL_TEMPORARY_FAILURE:
                failure(hashEntryAdr, new TemporaryLoadException());
                break;
            default:
                failure(hashEntryAdr, new AssertionError("illegal sentinel value " + sentinelStatus));
                break;
            }
        }

        private void failure(long hashEntryAdr, Throwable e) {
            if (hashEntryAdr != 0L)
                HashEntries.dereference(hashEntryAdr);
            HashEntries.dereference(sentinelHashEntryAdr);
            future.setException(e);
        }

        private void reschedule(long hashEntryAdr) {
            try {
                executorService.schedule(this, 10, TimeUnit.MILLISECONDS);
            } catch (Throwable t) {
                failure(hashEntryAdr, t);
            }
        }
    }, 10, TimeUnit.MILLISECONDS);

    return future;
}

From source file:com.google.devtools.build.lib.remote.ByteStreamUploader.java

private void startAsyncUploadWithRetry(Chunker chunker, Retrier.Backoff backoffTimes,
        SettableFuture<Void> overallUploadResult) {

    AsyncUpload.Listener listener = new AsyncUpload.Listener() {
        @Override//w  w w  . j  a  va  2  s . com
        public void success() {
            overallUploadResult.set(null);
        }

        @Override
        public void failure(Status status) {
            StatusException cause = status.asException();
            long nextDelayMillis = backoffTimes.nextDelayMillis();
            if (nextDelayMillis < 0 || !retrier.isRetriable(status)) {
                // Out of retries or status not retriable.
                RetryException error = new RetryException(cause, backoffTimes.getRetryAttempts());
                overallUploadResult.setException(error);
            } else {
                retryAsyncUpload(nextDelayMillis, chunker, backoffTimes, overallUploadResult);
            }
        }

        private void retryAsyncUpload(long nextDelayMillis, Chunker chunker, Retrier.Backoff backoffTimes,
                SettableFuture<Void> overallUploadResult) {
            try {
                ListenableScheduledFuture<?> schedulingResult = retryService.schedule(
                        Context.current().wrap(
                                () -> startAsyncUploadWithRetry(chunker, backoffTimes, overallUploadResult)),
                        nextDelayMillis, MILLISECONDS);
                // In case the scheduled execution errors, we need to notify the overallUploadResult.
                schedulingResult.addListener(() -> {
                    try {
                        schedulingResult.get();
                    } catch (Exception e) {
                        overallUploadResult
                                .setException(new RetryException(e, backoffTimes.getRetryAttempts()));
                    }
                }, MoreExecutors.directExecutor());
            } catch (RejectedExecutionException e) {
                // May be thrown by .schedule(...) if i.e. the executor is shutdown.
                overallUploadResult.setException(new RetryException(e, backoffTimes.getRetryAttempts()));
            }
        }
    };

    try {
        chunker.reset();
    } catch (IOException e) {
        overallUploadResult.setException(e);
        return;
    }

    AsyncUpload newUpload = new AsyncUpload(channel, callCredentials, callTimeoutSecs, instanceName, chunker,
            listener);
    overallUploadResult.addListener(() -> {
        if (overallUploadResult.isCancelled()) {
            newUpload.cancel();
        }
    }, MoreExecutors.directExecutor());
    newUpload.start();
}