Example usage for java.util.concurrent CompletableFuture complete

List of usage examples for java.util.concurrent CompletableFuture complete

Introduction

In this page you can find the example usage for java.util.concurrent CompletableFuture complete.

Prototype

public boolean complete(T value) 

Source Link

Document

If not already completed, sets the value returned by #get() and related methods to the given value.

Usage

From source file:org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.java

/**
 * Checks whether there are ledger that have been fully consumed and deletes them.
 *
 * @throws Exception/*from   ww w  .j  av a  2  s  .  c  o m*/
 */
void internalTrimConsumedLedgers(CompletableFuture<?> promise) {
    // Ensure only one trimming operation is active
    if (!trimmerMutex.tryLock()) {
        scheduleDeferredTrimming(promise);
        return;
    }

    List<LedgerInfo> ledgersToDelete = Lists.newArrayList();
    List<LedgerInfo> offloadedLedgersToDelete = Lists.newArrayList();
    synchronized (this) {
        if (log.isDebugEnabled()) {
            log.debug("[{}] Start TrimConsumedLedgers. ledgers={} totalSize={}", name, ledgers.keySet(),
                    TOTAL_SIZE_UPDATER.get(this));
        }
        if (STATE_UPDATER.get(this) == State.Closed) {
            log.debug("[{}] Ignoring trimming request since the managed ledger was already closed", name);
            trimmerMutex.unlock();
            promise.completeExceptionally(new ManagedLedgerAlreadyClosedException("Can't trim closed ledger"));
            return;
        }

        long slowestReaderLedgerId = -1;
        if (cursors.isEmpty()) {
            // At this point the lastLedger will be pointing to the
            // ledger that has just been closed, therefore the +1 to
            // include lastLedger in the trimming.
            slowestReaderLedgerId = currentLedger.getId() + 1;
        } else {
            PositionImpl slowestReaderPosition = cursors.getSlowestReaderPosition();
            if (slowestReaderPosition != null) {
                slowestReaderLedgerId = slowestReaderPosition.getLedgerId();
            } else {
                promise.completeExceptionally(new ManagedLedgerException("Couldn't find reader position"));
                trimmerMutex.unlock();
                return;
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("[{}] Slowest consumer ledger id: {}", name, slowestReaderLedgerId);
        }

        // skip ledger if retention constraint met
        for (LedgerInfo ls : ledgers.headMap(slowestReaderLedgerId, false).values()) {
            boolean expired = hasLedgerRetentionExpired(ls.getTimestamp());
            boolean overRetentionQuota = isLedgerRetentionOverSizeQuota();

            if (log.isDebugEnabled()) {
                log.debug(
                        "[{}] Checking ledger {} -- time-old: {} sec -- "
                                + "expired: {} -- over-quota: {} -- current-ledger: {}",
                        name, ls.getLedgerId(), (clock.millis() - ls.getTimestamp()) / 1000.0, expired,
                        overRetentionQuota, currentLedger.getId());
            }
            if (ls.getLedgerId() == currentLedger.getId()) {
                log.debug("[{}] ledger id skipped for deletion as it is currently being written to", name,
                        ls.getLedgerId());
                break;
            } else if (expired) {
                log.debug("[{}] Ledger {} has expired, ts {}", name, ls.getLedgerId(), ls.getTimestamp());
                ledgersToDelete.add(ls);
            } else if (overRetentionQuota) {
                log.debug("[{}] Ledger {} is over quota", name, ls.getLedgerId());
                ledgersToDelete.add(ls);
            } else {
                log.debug("[{}] Ledger {} not deleted. Neither expired nor over-quota", name, ls.getLedgerId());
                break;
            }
        }
        for (LedgerInfo ls : ledgers.values()) {
            if (isOffloadedNeedsDelete(ls.getOffloadContext()) && !ledgersToDelete.contains(ls)) {
                log.debug("[{}] Ledger {} has been offloaded, bookkeeper ledger needs to be deleted", name,
                        ls.getLedgerId());
                offloadedLedgersToDelete.add(ls);
            }
        }

        if (ledgersToDelete.isEmpty() && offloadedLedgersToDelete.isEmpty()) {
            trimmerMutex.unlock();
            promise.complete(null);
            return;
        }

        if (STATE_UPDATER.get(this) == State.CreatingLedger // Give up now and schedule a new trimming
                || !ledgersListMutex.tryLock()) { // Avoid deadlocks with other operations updating the ledgers list
            scheduleDeferredTrimming(promise);
            trimmerMutex.unlock();
            return;
        }

        // Update metadata
        for (LedgerInfo ls : ledgersToDelete) {
            ledgerCache.remove(ls.getLedgerId());

            ledgers.remove(ls.getLedgerId());
            NUMBER_OF_ENTRIES_UPDATER.addAndGet(this, -ls.getEntries());
            TOTAL_SIZE_UPDATER.addAndGet(this, -ls.getSize());

            entryCache.invalidateAllEntries(ls.getLedgerId());
        }
        for (LedgerInfo ls : offloadedLedgersToDelete) {
            LedgerInfo.Builder newInfoBuilder = ls.toBuilder();
            newInfoBuilder.getOffloadContextBuilder().setBookkeeperDeleted(true);
            String driverName = OffloadUtils.getOffloadDriverName(ls,
                    config.getLedgerOffloader().getOffloadDriverName());
            Map<String, String> driverMetadata = OffloadUtils.getOffloadDriverMetadata(ls,
                    config.getLedgerOffloader().getOffloadDriverMetadata());
            OffloadUtils.setOffloadDriverMetadata(newInfoBuilder, driverName, driverMetadata);
            ledgers.put(ls.getLedgerId(), newInfoBuilder.build());
        }

        if (log.isDebugEnabled()) {
            log.debug("[{}] Updating of ledgers list after trimming", name);
        }

        store.asyncUpdateLedgerIds(name, getManagedLedgerInfo(), ledgersStat, new MetaStoreCallback<Void>() {
            @Override
            public void operationComplete(Void result, Stat stat) {
                log.info("[{}] End TrimConsumedLedgers. ledgers={} totalSize={}", name, ledgers.size(),
                        TOTAL_SIZE_UPDATER.get(ManagedLedgerImpl.this));
                ledgersStat = stat;
                ledgersListMutex.unlock();
                trimmerMutex.unlock();

                for (LedgerInfo ls : ledgersToDelete) {
                    log.info("[{}] Removing ledger {} - size: {}", name, ls.getLedgerId(), ls.getSize());
                    asyncDeleteLedger(ls.getLedgerId(), ls);
                }
                for (LedgerInfo ls : offloadedLedgersToDelete) {
                    log.info("[{}] Deleting offloaded ledger {} from bookkeeper - size: {}", name,
                            ls.getLedgerId(), ls.getSize());
                    asyncDeleteLedgerFromBookKeeper(ls.getLedgerId());
                }
                promise.complete(null);
            }

            @Override
            public void operationFailed(MetaStoreException e) {
                log.warn("[{}] Failed to update the list of ledgers after trimming", name, e);
                ledgersListMutex.unlock();
                trimmerMutex.unlock();

                promise.completeExceptionally(e);
            }
        });
    }
}

From source file:org.hyperledger.fabric.sdk.Channel.java

/**
 * Send transaction to one of a specified set of orderers with the specified user context.
 * IF there are no event hubs or eventing peers this future returns immediately completed
 * indicating that orderer has accepted the transaction only.
 *
 * @param proposalResponses/*from   www  .  j  a  va  2s .  co  m*/
 * @param transactionOptions
 * @return Future allowing access to the result of the transaction invocation.
 */

public CompletableFuture<TransactionEvent> sendTransaction(Collection<ProposalResponse> proposalResponses,
        TransactionOptions transactionOptions) {
    try {

        if (null == transactionOptions) {
            throw new InvalidArgumentException("Parameter transactionOptions can't be null");
        }
        checkChannelState();
        User userContext = transactionOptions.userContext != null ? transactionOptions.userContext
                : client.getUserContext();
        userContextCheck(userContext);
        if (null == proposalResponses) {
            throw new InvalidArgumentException("sendTransaction proposalResponses was null");
        }

        List<Orderer> orderers = transactionOptions.orderers != null ? transactionOptions.orderers
                : new ArrayList<>(getOrderers());

        // make certain we have our own copy
        final List<Orderer> shuffeledOrderers = new ArrayList<>(orderers);

        if (transactionOptions.shuffleOrders) {
            Collections.shuffle(shuffeledOrderers);
        }

        if (config.getProposalConsistencyValidation()) {
            HashSet<ProposalResponse> invalid = new HashSet<>();
            int consistencyGroups = SDKUtils.getProposalConsistencySets(proposalResponses, invalid).size();

            if (consistencyGroups != 1 || !invalid.isEmpty()) {
                throw new IllegalArgumentException(format(
                        "The proposal responses have %d inconsistent groups with %d that are invalid."
                                + " Expected all to be consistent and none to be invalid.",
                        consistencyGroups, invalid.size()));

            }

        }

        List<FabricProposalResponse.Endorsement> ed = new LinkedList<>();
        FabricProposal.Proposal proposal = null;
        ByteString proposalResponsePayload = null;
        String proposalTransactionID = null;
        TransactionContext transactionContext = null;

        for (ProposalResponse sdkProposalResponse : proposalResponses) {
            ed.add(sdkProposalResponse.getProposalResponse().getEndorsement());
            if (proposal == null) {
                proposal = sdkProposalResponse.getProposal();
                proposalTransactionID = sdkProposalResponse.getTransactionID();
                if (proposalTransactionID == null) {
                    throw new InvalidArgumentException("Proposals with missing transaction ID");
                }
                proposalResponsePayload = sdkProposalResponse.getProposalResponse().getPayload();
                if (proposalResponsePayload == null) {
                    throw new InvalidArgumentException("Proposals with missing payload.");
                }
                transactionContext = sdkProposalResponse.getTransactionContext();
                if (transactionContext == null) {
                    throw new InvalidArgumentException("Proposals with missing transaction context.");
                }
            } else {
                final String transactionID = sdkProposalResponse.getTransactionID();
                if (transactionID == null) {
                    throw new InvalidArgumentException("Proposals with missing transaction id.");
                }
                if (!proposalTransactionID.equals(transactionID)) {
                    throw new InvalidArgumentException(
                            format("Proposals with different transaction IDs %s,  and %s",
                                    proposalTransactionID, transactionID));
                }
            }
        }

        TransactionBuilder transactionBuilder = TransactionBuilder.newBuilder();

        Payload transactionPayload = transactionBuilder.chaincodeProposal(proposal).endorsements(ed)
                .proposalResponsePayload(proposalResponsePayload).build();

        Envelope transactionEnvelope = createTransactionEnvelope(transactionPayload, transactionContext);

        NOfEvents nOfEvents = transactionOptions.nOfEvents;

        if (nOfEvents == null) {
            nOfEvents = NOfEvents.createNofEvents();
            Collection<Peer> eventingPeers = getEventingPeers();
            boolean anyAdded = false;
            if (!eventingPeers.isEmpty()) {
                anyAdded = true;
                nOfEvents.addPeers(eventingPeers);
            }
            Collection<EventHub> eventHubs = getEventHubs();
            if (!eventHubs.isEmpty()) {
                anyAdded = true;
                nOfEvents.addEventHubs(getEventHubs());
            }

            if (!anyAdded) {
                nOfEvents = NOfEvents.createNoEvents();
            }

        } else if (nOfEvents != NOfEvents.nofNoEvents) {
            StringBuilder issues = new StringBuilder(100);
            Collection<Peer> eventingPeers = getEventingPeers();
            nOfEvents.unSeenPeers().forEach(peer -> {
                if (peer.getChannel() != this) {
                    issues.append(format("Peer %s added to NOFEvents does not belong this channel. ",
                            peer.getName()));

                } else if (!eventingPeers.contains(peer)) {
                    issues.append(format("Peer %s added to NOFEvents is not a eventing Peer in this channel. ",
                            peer.getName()));
                }

            });
            nOfEvents.unSeenEventHubs().forEach(eventHub -> {
                if (!eventHubs.contains(eventHub)) {
                    issues.append(format("Eventhub %s added to NOFEvents does not belong this channel. ",
                            eventHub.getName()));
                }

            });

            if (nOfEvents.unSeenEventHubs().isEmpty() && nOfEvents.unSeenPeers().isEmpty()) {
                issues.append("NofEvents had no Eventhubs added or Peer eventing services.");
            }
            String foundIssues = issues.toString();
            if (!foundIssues.isEmpty()) {
                throw new InvalidArgumentException(foundIssues);
            }
        }

        final boolean replyonly = nOfEvents == NOfEvents.nofNoEvents
                || (getEventHubs().isEmpty() && getEventingPeers().isEmpty());

        CompletableFuture<TransactionEvent> sret;
        if (replyonly) { //If there are no eventhubs to complete the future, complete it
            // immediately but give no transaction event
            logger.debug(format(
                    "Completing transaction id %s immediately no event hubs or peer eventing services found in channel %s.",
                    proposalTransactionID, name));
            sret = new CompletableFuture<>();
        } else {
            sret = registerTxListener(proposalTransactionID, nOfEvents, transactionOptions.failFast);
        }

        logger.debug(format("Channel %s sending transaction to orderer(s) with TxID %s ", name,
                proposalTransactionID));
        boolean success = false;
        Exception lException = null; // Save last exception to report to user .. others are just logged.

        BroadcastResponse resp = null;
        Orderer failed = null;
        for (Orderer orderer : shuffeledOrderers) {
            if (failed != null) {
                logger.warn(format("Channel %s  %s failed. Now trying %s.", name, failed, orderer));
            }
            failed = orderer;
            try {

                if (null != diagnosticFileDumper) {
                    logger.trace(format("Sending to channel %s, orderer: %s, transaction: %s", name,
                            orderer.getName(), diagnosticFileDumper
                                    .createDiagnosticProtobufFile(transactionEnvelope.toByteArray())));
                }

                resp = orderer.sendTransaction(transactionEnvelope);
                lException = null; // no longer last exception .. maybe just failed.
                if (resp.getStatus() == Status.SUCCESS) {
                    success = true;
                    break;
                } else {
                    logger.warn(format("Channel %s %s failed. Status returned %s", name, orderer,
                            getRespData(resp)));
                }
            } catch (Exception e) {
                String emsg = format("Channel %s unsuccessful sendTransaction to orderer %s (%s)", name,
                        orderer.getName(), orderer.getUrl());
                if (resp != null) {

                    emsg = format("Channel %s unsuccessful sendTransaction to orderer %s (%s).  %s", name,
                            orderer.getName(), orderer.getUrl(), getRespData(resp));
                }

                logger.error(emsg);
                lException = new Exception(emsg, e);

            }

        }

        if (success) {
            logger.debug(format("Channel %s successful sent to Orderer transaction id: %s", name,
                    proposalTransactionID));
            if (replyonly) {
                sret.complete(null); // just say we're done.
            }
            return sret;
        } else {

            String emsg = format(
                    "Channel %s failed to place transaction %s on Orderer. Cause: UNSUCCESSFUL. %s", name,
                    proposalTransactionID, getRespData(resp));

            unregisterTxListener(proposalTransactionID);

            CompletableFuture<TransactionEvent> ret = new CompletableFuture<>();
            ret.completeExceptionally(
                    lException != null ? new Exception(emsg, lException) : new Exception(emsg));
            return ret;
        }
    } catch (Exception e) {

        CompletableFuture<TransactionEvent> future = new CompletableFuture<>();
        future.completeExceptionally(e);
        return future;

    }

}