Coverage Summary for Class: NodeManager (org.ethereum.net)

Class Method, % Line, %
NodeManager 0% (0/11) 0% (0/37)
NodeManager$NodeHandlerWithReputation 0% (0/2) 0% (0/4)
Total 0% (0/13) 0% (0/41)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 RSK Labs Ltd. 4  * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>) 5  * 6  * This program is free software: you can redistribute it and/or modify 7  * it under the terms of the GNU Lesser General Public License as published by 8  * the Free Software Foundation, either version 3 of the License, or 9  * (at your option) any later version. 10  * 11  * This program is distributed in the hope that it will be useful, 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14  * GNU Lesser General Public License for more details. 15  * 16  * You should have received a copy of the GNU Lesser General Public License 17  * along with this program. If not, see <http://www.gnu.org/licenses/>. 18  */ 19  20 package org.ethereum.net; 21  22 import co.rsk.net.discovery.PeerExplorer; 23 import org.ethereum.config.SystemProperties; 24 import org.ethereum.net.rlpx.Node; 25 import org.slf4j.Logger; 26 import org.slf4j.LoggerFactory; 27  28 import java.util.*; 29 import java.util.concurrent.ConcurrentHashMap; 30 import java.util.stream.Collectors; 31  32 /** 33  * The central class for Peer Discovery machinery. 34  * <p> 35  * The NodeManager manages info on all the Nodes discovered by the peer discovery 36  * protocol, routes protocol messages to the corresponding NodeHandlers and 37  * supplies the info about discovered Nodes and their usage statistics 38  * <p> 39  * Created by Anton Nashatyrev on 16.07.2015. 40  */ 41 public class NodeManager { 42  private static final Logger logger = LoggerFactory.getLogger("discover"); 43  44  private static final long MAX_NODES = 2000; 45  protected static final long NODES_TRIM_THRESHOLD = MAX_NODES + 1000; 46  47  // to avoid checking for null 48  private static final NodeStatistics DUMMY_STAT = new NodeStatistics(); 49  50  private final PeerExplorer peerExplorer; 51  52  private Map<String, NodeHandler> nodeHandlerMap = new ConcurrentHashMap<>(); 53  54  private boolean discoveryEnabled; 55  56  public NodeManager(PeerExplorer peerExplorer, SystemProperties config) { 57  this.peerExplorer = peerExplorer; 58  this.discoveryEnabled = config.isPeerDiscoveryEnabled(); 59  60  for (Node node : config.peerActive()) { 61  NodeHandler handler = new NodeHandler(node); 62  handler.getNodeStatistics().setPredefined(true); 63  createNodeHandler(node); 64  } 65  } 66  67  private synchronized NodeHandler getNodeHandler(Node n) { 68  String key = n.getHexId(); 69  NodeHandler handler = nodeHandlerMap.get(key); 70  return (handler != null) ? handler : createNodeHandler(n); 71  } 72  73  private NodeHandler createNodeHandler(Node n) { 74  NodeHandler handler = new NodeHandler(n); 75  purgeNodeHandlers(); 76  nodeHandlerMap.put(n.getHexId(), handler); 77  return handler; 78  } 79  80  public NodeStatistics getNodeStatistics(Node n) { 81  return discoveryEnabled ? getNodeHandler(n).getNodeStatistics() : DUMMY_STAT; 82  } 83  84  public synchronized List<NodeHandler> getNodes(Set<String> nodesInUse) { 85  List<NodeHandler> handlers = new ArrayList<>(); 86  87  List<Node> foundNodes = this.peerExplorer.getNodes(); 88  if (this.discoveryEnabled && !foundNodes.isEmpty()) { 89  logger.debug("{} Nodes retrieved from the PE.", foundNodes.size()); 90  foundNodes.stream().filter(n -> !nodeHandlerMap.containsKey(n.getHexId())).forEach(this::createNodeHandler); 91  } 92  93  for(NodeHandler handler : this.nodeHandlerMap.values()) { 94  if(!nodesInUse.contains(handler.getNode().getHexId())) { 95  handlers.add(handler); 96  } 97  } 98  return handlers; 99  } 100  101  private void purgeNodeHandlers() { 102  if (nodeHandlerMap.size() > NODES_TRIM_THRESHOLD) { 103  //I create a stream 104  List<NodeHandler> toRemove = nodeHandlerMap.values().stream() 105  //collect all reputations first to avoid concurrency issues 106  .map(NodeHandlerWithReputation::new) 107  //sort by reputation 108  .sorted(Comparator.comparingInt(o -> o.reputation)) 109  //and just keep the ones that exceeds the MAX_NODES 110  .limit(nodeHandlerMap.size() - MAX_NODES) 111  .map(o -> o.nodeHandler) 112  .collect(Collectors.toList()); 113  //Remove them 114  nodeHandlerMap.values().removeAll(toRemove); 115  } 116  } 117  118  private static class NodeHandlerWithReputation { 119  private NodeHandler nodeHandler; 120  private int reputation; 121  122  private NodeHandlerWithReputation(NodeHandler nodeHandler) { 123  this.nodeHandler = nodeHandler; 124  this.reputation = nodeHandler.getNodeStatistics().getReputation(); 125  } 126  } 127 }