Example usage for com.google.common.util.concurrent MoreExecutors sameThreadExecutor

List of usage examples for com.google.common.util.concurrent MoreExecutors sameThreadExecutor

Introduction

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

Prototype

@Deprecated
@GwtIncompatible("TODO")
public static ListeningExecutorService sameThreadExecutor() 

Source Link

Document

Creates an executor service that runs each task in the thread that invokes execute/submit , as in CallerRunsPolicy .

Usage

From source file:com.woollysammoth.nubitj.protocols.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Nubit network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 *///ww  w  .ja v  a 2  s  . co m
@Override
public ListenableFuture<BigInteger> incrementPayment(BigInteger size)
        throws ValueOutOfRangeException, IllegalStateException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToNubit()))
                .setClientChangeValue(state.getValueRefunded().longValue());

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:com.google.sha1coin.protocols.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Bitcoin network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 *///from w w  w.jav a 2 s .co  m
@Override
public ListenableFuture<Coin> incrementPayment(Coin size)
        throws ValueOutOfRangeException, IllegalStateException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToBitcoin()))
                .setClientChangeValue(state.getValueRefunded().value);

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:io.mappum.altcoinj.protocols.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Bitcoin network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @param info Information about this update, used to extend this protocol.
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 *///  ww w.  j av  a2 s. c o m
@Override
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info)
        throws ValueOutOfRangeException, IllegalStateException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToBitcoin()))
                .setClientChangeValue(state.getValueRefunded().value);
        if (info != null)
            updatePaymentBuilder.setInfo(info);

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:io.xpydev.paycoinj.protocols.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Bitcoin network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @param info Information about this update, used to extend this protocol.
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 */// w w w  .  j  av a2  s  . com
@Override
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info)
        throws ValueOutOfRangeException, IllegalStateException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToPaycoin()))
                .setClientChangeValue(state.getValueRefunded().value);
        if (info != null)
            updatePaymentBuilder.setInfo(info);

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:com.github.kryptohash.kryptohashj.protocols.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Bitcoin network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @param info Information about this update, used to extend this protocol.
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 */// www  .j a v  a  2  s.  co m
@Override
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info)
        throws ValueOutOfRangeException, IllegalStateException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToKryptohash()))
                .setClientChangeValue(state.getValueRefunded().value);
        if (info != null)
            updatePaymentBuilder.setInfo(info);

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:com.matthewmitchell.nubitsj.protocols.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Bitcoin network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @param info Information about this update, used to extend this protocol.
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 *//*from w  ww  . j a  va 2 s .co m*/
@Override
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info)
        throws ValueOutOfRangeException, IllegalStateException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToNubits()))
                .setClientChangeValue(state.getValueRefunded().value);
        if (info != null)
            updatePaymentBuilder.setInfo(info);

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:com.matthewmitchell.peercoinj.protocols.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Bitcoin network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @param info Information about this update, used to extend this protocol.
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 *///from w  w  w  .  j  ava2 s.  c om
@Override
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info)
        throws ValueOutOfRangeException, IllegalStateException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToPeercoin()))
                .setClientChangeValue(state.getValueRefunded().value);
        if (info != null)
            updatePaymentBuilder.setInfo(info);

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:org.neoscoinj.protocols.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Neoscoin network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @param info Information about this update, used to extend this protocol.
 * @param userKey Key derived from a user password, needed for any signing when the wallet is encrypted.
 *                The wallet KeyCrypter is assumed.
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 * @throws ECKey.KeyIsEncryptedException If the keys are encrypted and no AES key has been provided,
 *//*from   ww  w .jav  a 2 s.co m*/
@Override
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info,
        @Nullable KeyParameter userKey)
        throws ValueOutOfRangeException, IllegalStateException, ECKey.KeyIsEncryptedException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");
        if (wallet.isEncrypted() && userKey == null)
            throw new ECKey.KeyIsEncryptedException();

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size, userKey);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToNeoscoin()))
                .setClientChangeValue(state.getValueRefunded().value);
        if (info != null)
            updatePaymentBuilder.setInfo(info);

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:network.bitmesh.channels.PaymentChannelClient.java

/**
 * Increments the total value which we pay the server. Note that the amount of money sent may not be the same as the
 * amount of money actually requested. It can be larger if the amount left over in the channel would be too small to
 * be accepted by the Bitcoin network. ValueOutOfRangeException will be thrown, however, if there's not enough money
 * left in the channel to make the payment at all. Only one payment can be in-flight at once. You have to ensure
 * you wait for the previous increase payment future to complete before incrementing the payment again.
 *
 * @param size How many satoshis to increment the payment by (note: not the new total).
 * @param info Information about this update, used to extend this protocol.
 * @param userKey Key derived from a user password, needed for any signing when the wallet is encrypted.
 *                The wallet KeyCrypter is assumed.
 * @return a future that completes when the server acknowledges receipt and acceptance of the payment.
 * @throws ValueOutOfRangeException If the size is negative or would pay more than this channel's total value
 *                                  ({@link PaymentChannelClientConnection#state()}.getTotalValue())
 * @throws IllegalStateException If the channel has been closed or is not yet open
 *                               (see {@link PaymentChannelClientConnection#getChannelOpenFuture()} for the second)
 * @throws ECKey.KeyIsEncryptedException If the keys are encrypted and no AES key has been provided,
 *//*  w  w  w .  j  ava  2s.com*/
@Override
public ListenableFuture<PaymentIncrementAck> incrementPayment(Coin size, @Nullable ByteString info,
        @Nullable KeyParameter userKey)
        throws ValueOutOfRangeException, IllegalStateException, ECKey.KeyIsEncryptedException {
    lock.lock();
    try {
        if (state() == null || !connectionOpen || step != InitStep.CHANNEL_OPEN)
            throw new IllegalStateException("Channel is not fully initialized/has already been closed");
        if (increasePaymentFuture != null)
            throw new IllegalStateException(
                    "Already incrementing paying, wait for previous payment to complete.");
        if (wallet.isEncrypted() && userKey == null)
            throw new ECKey.KeyIsEncryptedException();

        PaymentChannelClientState.IncrementedPayment payment = state().incrementPaymentBy(size, userKey);
        Protos.UpdatePayment.Builder updatePaymentBuilder = Protos.UpdatePayment.newBuilder()
                .setSignature(ByteString.copyFrom(payment.signature.encodeToBitcoin()))
                .setClientChangeValue(state.getValueRefunded().value);
        if (info != null)
            updatePaymentBuilder.setInfo(info);

        increasePaymentFuture = SettableFuture.create();
        increasePaymentFuture.addListener(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                increasePaymentFuture = null;
                lock.unlock();
            }
        }, MoreExecutors.sameThreadExecutor());

        conn.sendToServer(Protos.TwoWayChannelMessage.newBuilder().setUpdatePayment(updatePaymentBuilder)
                .setType(Protos.TwoWayChannelMessage.MessageType.UPDATE_PAYMENT).build());
        lastPaymentActualAmount = payment.amount;
        return increasePaymentFuture;
    } finally {
        lock.unlock();
    }
}

From source file:com.google.casinocoin.core.Peer.java

private ListenableFuture<Object> downloadDependenciesInternal(final Transaction tx, final Object marker,
        final List<Transaction> results) {
    final SettableFuture<Object> resultFuture = SettableFuture.create();
    final Sha256Hash rootTxHash = tx.getHash();
    // We want to recursively grab its dependencies. This is so listeners can learn important information like
    // whether a transaction is dependent on a timelocked transaction or has an unexpectedly deep dependency tree
    // or depends on a no-fee transaction.
    ///*from  w  w w.  j  a  v  a2  s .c o  m*/
    // Firstly find any that are already in the memory pool so if they weren't garbage collected yet, they won't
    // be deleted. Use COW sets to make unit tests deterministic and because they are small. It's slower for
    // the case of transactions with tons of inputs.
    Set<Transaction> dependencies = new CopyOnWriteArraySet<Transaction>();
    Set<Sha256Hash> needToRequest = new CopyOnWriteArraySet<Sha256Hash>();
    for (TransactionInput input : tx.getInputs()) {
        // There may be multiple inputs that connect to the same transaction.
        Sha256Hash hash = input.getOutpoint().getHash();
        Transaction dep = memoryPool.get(hash);
        if (dep == null) {
            needToRequest.add(hash);
        } else {
            dependencies.add(dep);
        }
    }
    results.addAll(dependencies);
    lock.lock();
    try {
        // Build the request for the missing dependencies.
        List<ListenableFuture<Transaction>> futures = Lists.newArrayList();
        GetDataMessage getdata = new GetDataMessage(params);
        final long nonce = (long) (Math.random() * Long.MAX_VALUE);
        if (needToRequest.size() > 1)
            log.info("{}: Requesting {} transactions for dep resolution", needToRequest.size());
        for (Sha256Hash hash : needToRequest) {
            getdata.addTransaction(hash);
            GetDataRequest req = new GetDataRequest();
            req.hash = hash;
            req.future = SettableFuture.create();
            if (!isNotFoundMessageSupported()) {
                req.nonce = nonce;
            }
            futures.add(req.future);
            getDataFutures.add(req);
        }
        // The transactions we already grabbed out of the mempool must still be considered by the code below.
        for (Transaction dep : dependencies) {
            futures.add(Futures.immediateFuture(dep));
        }
        ListenableFuture<List<Transaction>> successful = Futures.successfulAsList(futures);
        Futures.addCallback(successful, new FutureCallback<List<Transaction>>() {
            public void onSuccess(List<Transaction> transactions) {
                // Once all transactions either were received, or we know there are no more to come ...
                // Note that transactions will contain "null" for any positions that weren't successful.
                List<ListenableFuture<Object>> childFutures = Lists.newLinkedList();
                for (Transaction tx : transactions) {
                    if (tx == null)
                        continue;
                    log.info("{}: Downloaded dependency of {}: {}",
                            new Object[] { vAddress, rootTxHash, tx.getHashAsString() });
                    results.add(tx);
                    // Now recurse into the dependencies of this transaction too.
                    childFutures.add(downloadDependenciesInternal(tx, marker, results));
                }
                if (childFutures.size() == 0) {
                    // Short-circuit: we're at the bottom of this part of the tree.
                    resultFuture.set(marker);
                } else {
                    // There are some children to download. Wait until it's done (and their children and their
                    // children...) to inform the caller that we're finished.
                    Futures.addCallback(Futures.successfulAsList(childFutures),
                            new FutureCallback<List<Object>>() {
                                public void onSuccess(List<Object> objects) {
                                    resultFuture.set(marker);
                                }

                                public void onFailure(Throwable throwable) {
                                    resultFuture.setException(throwable);
                                }
                            });
                }
            }

            public void onFailure(Throwable throwable) {
                resultFuture.setException(throwable);
            }
        });
        // Start the operation.
        sendMessage(getdata);
        if (!isNotFoundMessageSupported()) {
            // If the peer isn't new enough to support the notfound message, we use a nasty hack instead and
            // assume if we send a ping message after the getdata message, it'll be processed after all answers
            // from getdata are done, so we can watch for the pong message as a substitute.
            log.info("{}: Dep resolution waiting for a pong with nonce {}", this, nonce);
            ping(nonce).addListener(new Runnable() {
                public void run() {
                    // The pong came back so clear out any transactions we requested but didn't get.
                    for (GetDataRequest req : getDataFutures) {
                        if (req.nonce == nonce) {
                            log.info("{}: Bottomed out dep tree at {}", this, req.hash);
                            req.future.cancel(true);
                            getDataFutures.remove(req);
                        }
                    }
                }
            }, MoreExecutors.sameThreadExecutor());
        }
    } catch (Exception e) {
        log.error("{}: Couldn't send getdata in downloadDependencies({})", this, tx.getHash());
        resultFuture.setException(e);
        return resultFuture;
    } finally {
        lock.unlock();
    }
    return resultFuture;
}