List of usage examples for java.util TreeSet removeIf
default boolean removeIf(Predicate<? super E> filter)
From source file:com.offbynull.voip.kademlia.FindSubcoroutine.java
@Override public List<Node> run(Continuation cnt) throws Exception { Context ctx = (Context) cnt.getContext(); ctx.addOutgoingMessage(subAddress, logAddress, info("Finding {}", findId)); // Set up subcoroutine router Address routerAddress = subAddress.appendSuffix("finderreq" + idGenerator.generate()); SubcoroutineRouter msgRouter = new SubcoroutineRouter(routerAddress, ctx); Controller msgRouterController = msgRouter.getController(); // Get initial set of nodes to query from routing table List<Node> startNodes = router.find(findId, maxResults, false); // do not include stale nodes, we only want to contact alive nodes ctx.addOutgoingMessage(subAddress, logAddress, info("Route table entries closest to {}: {}", findId, startNodes)); // Create sorted set of nodes to contact IdXorMetricComparator idClosenessComparator = new IdXorMetricComparator(findId); TreeSet<Node> contactSet = new TreeSet<>((x, y) -> idClosenessComparator.compare(x.getId(), y.getId())); contactSet.addAll(startNodes);// w ww.j a v a 2s . c o m // Create a sorted set of nodes to retain closest nodes in TreeSet<Node> closestSet = new TreeSet<>((x, y) -> idClosenessComparator.compare(x.getId(), y.getId())); // Execute requests Map<Subcoroutine<?>, Node> requestSubcoroutineToNodes = new HashMap<>(); // executing requests Set<Id> queriedSet = new HashSet<>(); // ids that have already been queried while (true) { // If there's room left to query more contacts that are closer to findId, do so... while (msgRouterController.size() < maxConcurrentRequests && !contactSet.isEmpty()) { // Get next farthest away node to contact Node contactNode = contactSet.pollLast(); // Add it to set of set of ids that have already been queried.. if it's already there, it means that it's already been // queried by this find, so skip it... boolean added = queriedSet.add(contactNode.getId()); if (!added) { continue; } // Add it to the set of closest nodes (will be removed if node fails to respond) closestSet.add(contactNode); // If we already have maxResult closer nodes to findId, skip this node if (closestSet.size() > maxResults) { Node removedNode = closestSet.pollLast(); if (removedNode == contactNode) { continue; } } // Initialize query Address destinationAddress = addressTransformer.toAddress(contactNode.getLink()) .appendSuffix(ROUTER_EXT_HANDLER_RELATIVE_ADDRESS); RequestSubcoroutine<FindResponse> reqSubcoroutine = new RequestSubcoroutine.Builder<FindResponse>() .sourceAddress(routerAddress, idGenerator).destinationAddress(destinationAddress) .timerAddress(timerAddress) .request(new FindRequest(advertiseSelf ? baseId : null, findId, maxResults)) .addExpectedResponseType(FindResponse.class).attemptInterval(Duration.ofSeconds(2L)) .maxAttempts(5).throwExceptionIfNoResponse(false).build(); ctx.addOutgoingMessage(subAddress, logAddress, info("Querying node {}", contactNode)); // Add query to router msgRouterController.add(reqSubcoroutine, AddBehaviour.ADD_PRIME_NO_FINISH); requestSubcoroutineToNodes.put(reqSubcoroutine, contactNode); } // If there are no more requests running, it means we're finished if (msgRouterController.size() == 0) { ctx.addOutgoingMessage(subAddress, logAddress, info("Find complete: {}", closestSet)); return new ArrayList<>(closestSet); } // Wait for next messange forward to the router cnt.suspend(); ForwardResult fr = msgRouter.forward(); // If a request completed from the forwarded message if (fr.isForwarded() && fr.isCompleted()) { // calling isCompleted by itself may throw an exception, check isForwarded first // Get response FindResponse findResponse = (FindResponse) fr.getResult(); if (findResponse == null) { // If failure, then mark as stale and remove from closest // DONT BOTHER WITH TRYING TO CALCULATE LOCKING/UNLOCKING LOGIC. THE LOGIC WILL BECOME EXTREMELY CONVOLUTED. THE QUERY // DID 5 REQUEST. IF NO ANSWER WAS GIVEN IN THE ALLOTED TIME, THEN MARK AS STALE! Node contactedNode = requestSubcoroutineToNodes.remove(fr.getSubcoroutine()); try { // not allowed to mark self as stale -- we may want to find self, but if we do and it's not responsive dont try to // mark it as stale if (!contactedNode.getId().equals(baseId)) { router.stale(contactedNode); } } catch (NodeNotFoundException nnfe) { // may have been removed (already marked as stale) / may not be in routing tree // Do nothing } closestSet.remove(contactedNode); } else { // If success, then add returned nodes to contacts Node[] nodes = findResponse.getNodes(); contactSet.addAll(Arrays.asList(nodes)); // If we don't want to find our own ID / query ourselves... remove any reference to our own ID in the contactSet // TODO: optimize this by removing before it's added to contactSet if (ignoreSelf) { contactSet.removeIf(x -> x.getId().equals(baseId)); } } } } }