private final void onAllResyncItemsFinished() { processingState = ItemProcessingState.CHECKING; try { checkSubItems(); } catch (Exception e) { e.printStackTrace(); report(getLabel(), ()->"error: ItemProcessor.onAllResyncItemsFinished() exception: " + e, DatagramAdapter.VerboseLevel.BASE); } commitCheckedAndStartPolling(); }
public void report(int level, Object... messages) { report(getLabel(), () -> concatReportMessage(messages), level); }
public void pulseResync() { report(getLabel(), ()->"ResyncProcessor.pulseResync(itemId="+itemId+ "), time="+Duration.between(resyncExpiresAt.minus(config.getMaxResyncTime()), Instant.now()).toMillis()+"ms", DatagramAdapter.VerboseLevel.BASE); if (resyncExpiresAt.isBefore(Instant.now())) { report(getLabel(), ()->"ResyncProcessor.pulseResync(itemId="+itemId+") expired, cancel", DatagramAdapter.VerboseLevel.BASE); resyncer.cancel(true); } else { try { ResyncNotification notification = new ResyncNotification(myInfo, itemId, true); network.eachNode(node -> { if (!obtainedAnswersFromNodes.contains(node)) network.deliver(node, notification); }); } catch (IOException e) { report(getLabel(), ()->"error: unable to send ResyncNotification, exception: " + e, DatagramAdapter.VerboseLevel.BASE); } } }
private void pulseProcessing() { report(getLabel(), () -> concatReportMessage("parcel processor for: ", parcelId, " :: pulseProcessing, state ", processingState), DatagramAdapter.VerboseLevel.BASE); if(processingState.canContinue()) { synchronized (mutex) { if (processSchedule == null || processSchedule.isDone()) { processSchedule = (ScheduledFuture<?>) executorService.submit(() -> process(), Node.this.toString() + " pp > parcel " + parcelId + " :: pulseProcessing -> process"); } } } }
/** * Check the parcel's processing state. If parcel is not under processing (not start or already finished) * return ParcelProcessingState.NOT_EXIST * * @param parcelId parcel to check * * @return processing state */ public @NonNull ParcelProcessingState checkParcelProcessingState(HashId parcelId) { report(getLabel(), () -> concatReportMessage("check parcel processor state for parcel: ", parcelId), DatagramAdapter.VerboseLevel.BASE); Object x = checkParcelInternal(parcelId); if (x instanceof ParcelProcessor) { report(getLabel(), () -> concatReportMessage("parcel processor for parcel: ", parcelId, " state is ", ((ParcelProcessor) x).processingState), DatagramAdapter.VerboseLevel.BASE); return ((ParcelProcessor) x).processingState; } report(getLabel(), () -> concatReportMessage("parcel processor for parcel: ", parcelId, " was not found"), DatagramAdapter.VerboseLevel.BASE); return ParcelProcessingState.NOT_EXIST; }
public void obtainAnswer(ResyncNotification answer) { if (obtainedAnswersFromNodes.putIfAbsent(answer.getFrom(), 0) == null) { report(getLabel(), () -> "ResyncProcessor.obtainAnswer(itemId=" + itemId + "), state: " + answer.getItemState(), DatagramAdapter.VerboseLevel.BASE); resyncingItem.resyncVote(answer.getFrom(), answer.getItemState()); if (answer.getHasEnvironment()) envSources.put(answer.getFrom(), 0); if (resyncingItem.isResyncPollingFinished() && resyncingItem.isCommitFinished()) { report(getLabel(), () -> "ResyncProcessor.obtainAnswer... resync done", DatagramAdapter.VerboseLevel.BASE); resyncer.cancel(true); } } }
public void startResync() { report(getLabel(), ()->"ResyncProcessor.startResync(itemId="+itemId+")", DatagramAdapter.VerboseLevel.BASE); resyncExpiresAt = Instant.now().plus(config.getMaxResyncTime()); executorService.schedule(()->resyncEnded(), config.getMaxResyncTime().getSeconds(), TimeUnit.SECONDS); resyncingItem = new ResyncingItem(itemId, ledger.getRecord(itemId)); resyncingItem.finishEvent.addConsumer((ri)->onFinishResync(ri)); List<Integer> periodsMillis = config.getResyncTime(); obtainedAnswersFromNodes.clear(); voteItself(); resyncer = new RunnableWithDynamicPeriod(() -> pulseResync(), periodsMillis, executorService); resyncer.run(); }
/** * Remove parcel processor from the Node and stop all processes. */ private final void removeSelf() { report(getLabel(), () -> concatReportMessage("parcel processor for: ", parcelId, " :: removeSelf, state ", processingState), DatagramAdapter.VerboseLevel.BASE); if(processingState.canRemoveSelf()) { parcelProcessors.remove(parcelId); stopDownloader(); stopProcesser(); doneEvent.fire(); } }
private final void removeSelf() { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: removeSelf, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); if(processingState.canRemoveSelf()) { forceRemoveSelf(); } }
/** * Start checking if item was downloaded and wait for isCheckingForce flag. * If item hasn't downloaded just set isCheckingForce for true. * @param isCheckingForce */ private void forceChecking(boolean isCheckingForce) { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: forceChecking, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); this.isCheckingForce = isCheckingForce; if(processingState.canContinue()) { if (processingState == ItemProcessingState.DOWNLOADED) { executorService.submit(() -> { checkItem(); }, Node.this.toString() + toString() + " :: forceChecking -> checkItem"); } } }
private final void approveAndCommit() { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: approveAndCommit, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); if(processingState.canContinue()) { // todo: fix logic to surely copy approving item dependency. e.g. download original or at least dependencies // first we need to flag our state as approved setState(ItemState.APPROVED); executorService.submit(() -> downloadAndCommit(), Node.this.toString() + toString() + " :: approveAndCommit -> downloadAndCommit"); } }
private void onFinishResync(ResyncingItem ri) { report(getLabel(), ()->"ResyncProcessor.onFinishResync(itemId="+itemId+")", DatagramAdapter.VerboseLevel.BASE); //DELETE ENVIRONMENTS FOR REVOKED ITEMS if(resyncingItem.getResyncingState() == ResyncingItemProcessingState.COMMIT_SUCCESSFUL) { if(resyncingItem.getItemState() == ItemState.REVOKED) { removeEnvironment(itemId); } } //SAVE ENVIRONMENTS FOR APPROVED ITEMS if (saveResyncedEnvironents()) { resyncEnded(); } else { resyncer.cancel(true); } }
/** * Check the state of the item. This method does not start elections and can be safely called from a client. * * @param itemId item to check * * @return last known state */ public @NonNull ItemResult checkItem(HashId itemId) { report(getLabel(), () -> concatReportMessage("check item processor state for item: ", itemId), DatagramAdapter.VerboseLevel.BASE); Object x = checkItemInternal(itemId); //ItemResult ir = (x instanceof ItemResult) ? (ItemResult) x : ((ItemProcessor) x).getResult(); ItemResult ir = ItemResult.UNDEFINED; if (x instanceof ItemResult) ir = (ItemResult)x; else if (x instanceof ItemProcessor) ir = ((ItemProcessor)x).getResult(); else if (x instanceof ResyncProcessor) ir = ((ResyncProcessor)x).getResult(); final ItemResult irFinal = ir; report(getLabel(), () -> concatReportMessage("item state for: ", itemId, "is ", irFinal.state), DatagramAdapter.VerboseLevel.BASE); ItemInformer.Record record = informer.takeFor(itemId); if (record != null) ir.errors = record.errorRecords; ir.isTestnet = ledger.isTestnet(itemId); return ir; }
private final void pulseSendNewConsensus() { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: pulseSendNewConsensus, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); if(processingState.canContinue()) { processingState = ItemProcessingState.SENDING_CONSENSUS; synchronized (mutex) { if(consensusReceivedChecker == null) { List<Integer> periodsMillis = config.getConsensusReceivedCheckTime(); consensusReceivedChecker = new RunnableWithDynamicPeriod(() -> sendNewConsensusNotification(), periodsMillis, executorService ); consensusReceivedChecker.run(); } } } }
private final void broadcastMyState() { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: broadcastMyState, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); if(processingState.canContinue()) { Notification notification; ParcelNotification.ParcelNotificationType notificationType; if(item.shouldBeU()) { notificationType = ParcelNotification.ParcelNotificationType.PAYMENT; } else { notificationType = ParcelNotification.ParcelNotificationType.PAYLOAD; } notification = new ParcelNotification(myInfo, itemId, parcelId, getResult(), true, notificationType); network.broadcast(myInfo, notification); } }
private final void itemDownloaded() { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: itemDownloaded, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); if(processingState.canContinue()) { synchronized (cache) { cache.put(item, getResult()); } synchronized (mutex) { //save item in disk cache ledger.putItem(record, item, Instant.now().plus(config.getMaxDiskCacheAge())); } if(item instanceof Contract) { if(((Contract)item).isLimitedForTestnet()) { markContractTest((Contract) item); } } if(!processingState.isProcessedToConsensus()) { processingState = ItemProcessingState.DOWNLOADED; } if(isCheckingForce) { checkItem(); } downloadedEvent.fire(); } }
/** * Emergency break all processes and remove self. */ private void emergencyBreak() { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: emergencyBreak, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); boolean doRollback = !processingState.isDone(); processingState = ItemProcessingState.EMERGENCY_BREAK; stopDownloader(); stopPoller(); stopConsensusReceivedChecker(); for(ResyncingItem ri : resyncingItems.values()) { if(!ri.isCommitFinished()) { ri.closeByTimeout(); } } if(doRollback) rollbackChanges(stateWas); else close(); processingState = ItemProcessingState.FINISHED; }
private final void pulseStartPolling() { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: pulseStartPolling, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) { // at this point the item is with us, so we can start synchronized (mutex) { if (!processingState.isProcessedToConsensus()) { if (poller == null) { List<Integer> pollTimes = config.getPollTime(); poller = new RunnableWithDynamicPeriod(() -> sendStartPollingNotification(), pollTimes, executorService ); poller.run(); } } } } } }
private void close() { report(getLabel(), () -> concatReportMessage("item processor for item: ", itemId, " from parcel: ", parcelId, " :: close, state ", processingState, " itemState: ", getState()), DatagramAdapter.VerboseLevel.BASE); if(processingState.canContinue()) processingState = ItemProcessingState.DONE; stopPoller(); // fire all event to release possible listeners downloadedEvent.fire(); pollingReadyEvent.fire(); doneEvent.fire(); if(processingState.canContinue()) { checkIfAllReceivedConsensus(); if (processingState == ItemProcessingState.DONE) { pulseSendNewConsensus(); } else { removeSelf(); } } else { removeSelf(); } }