private final Boolean checkIfAllReceivedConsensus() { if(processingState.canContinue()) { List<NodeInfo> nodes = network.allNodes(); Boolean allReceived = nodes.size() <= positiveNodes.size() + negativeNodes.size(); if (allReceived) { processingState = ItemProcessingState.FINISHED; stopConsensusReceivedChecker(); } return allReceived; } return true; }
private final void onResyncItemFinished(ResyncingItem ri) { if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) { resyncingItemsResults.put(ri.hashId, ri.getItemState()); if (resyncingItemsResults.size() >= resyncingItems.size()) { onAllResyncItemsFinished(); } } } }
public void addItemToResync(HashId hid, StateRecord record) { if(processingState.canContinue()) { resyncingItems.putIfAbsent(hid, new ResyncingItem(hid, record)); } }
private final synchronized void checkNewsOf(Approvable checkingItem) { if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) {
private final synchronized void checkRevokesOf(Approvable checkingItem) { if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) {
private final void sendNewConsensusNotification() { if(processingState.canContinue()) {
public HashMap<HashId, StateRecord> isNeedToResync(boolean baseCheckPassed) { if(processingState.canContinue()) { HashMap<HashId, StateRecord> unknownParts = new HashMap<>(); HashMap<HashId, StateRecord> knownParts = new HashMap<>();
private void download() { if(processingState.canContinue()) { while (!isPollingExpired() && item == null) { if (sources.isEmpty()) { log.e("empty sources for download tasks, stopping"); return; } else { try { // first we have to wait for sources NodeInfo source; // Important: it could be disturbed by notifications synchronized (sources) { source = Do.sample(sources); } item = network.getItem(itemId, source, config.getMaxGetItemTime()); if (item != null) { itemDownloaded(); return; } else { Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } } } }
private final void sendStartPollingNotification() { if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) { synchronized (mutex) { if (isPollingExpired()) { // cancel by timeout expired processingState = ItemProcessingState.GOT_CONSENSUS; stopPoller(); stopDownloader(); rollbackChanges(ItemState.UNDEFINED); return; } } // at this point we should requery the nodes that did not yet answered us 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); List<NodeInfo> nodes = network.allNodes(); for(NodeInfo node : nodes) { if (!positiveNodes.contains(node) && !negativeNodes.contains(node)) network.deliver(node, notification); } } } }
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(); } }
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(); } }
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 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); } }
/** * 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 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 void pulseDownload() { if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) { if(!processingState.isProcessedToConsensus()) { processingState = ItemProcessingState.DOWNLOADING; } synchronized (mutex) { if (item == null && (downloader == null || downloader.isDone())) { downloader = (ScheduledFuture<?>) executorService.submit(() -> download(), Node.this.toString() + toString() + " :: item pulseDownload -> download"); } } } } }
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"); } }
public final void startResync() { if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) { processingState = ItemProcessingState.RESYNCING; resyncingItems.forEach((k, v)-> { resync(k, (re)->onResyncItemFinished(re)); }); } } }
private final synchronized void checkSubItemsOf(Approvable checkingItem) { if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) { // check referenced items //checkReferencesOf(checkingItem); // check revoking items checkRevokesOf(checkingItem); // check new items checkNewsOf(checkingItem); } } }
private final void checkSubItems() { if(processingState.canContinue()) { if (!processingState.isProcessedToConsensus()) { checkSubItemsOf(item); } } }