List of usage examples for java.util.concurrent CompletableFuture complete
public boolean complete(T value)
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; } }