Coverage Summary for Class: BlockNodeInformation (co.rsk.net)

Class Method, % Line, %
BlockNodeInformation 33.3% (2/6) 33.3% (6/18)
BlockNodeInformation$1 50% (1/2) 50% (1/2)
Total 37.5% (3/8) 35% (7/20)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 RSK Labs Ltd. 4  * 5  * This program is free software: you can redistribute it and/or modify 6  * it under the terms of the GNU Lesser General Public License as published by 7  * the Free Software Foundation, either version 3 of the License, or 8  * (at your option) any later version. 9  * 10  * This program is distributed in the hope that it will be useful, 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13  * GNU Lesser General Public License for more details. 14  * 15  * You should have received a copy of the GNU Lesser General Public License 16  * along with this program. If not, see <http://www.gnu.org/licenses/>. 17  */ 18  19 package co.rsk.net; 20  21 import co.rsk.crypto.Keccak256; 22  23 import javax.annotation.Nonnull; 24 import java.util.*; 25  26 /** 27  * BlockNodeInformation has information about which blocks are known by which peer, 28  * and provides convenient functions to retrieve all the blocks known by a node, and 29  * which nodes know a certain block. 30  * <p> 31  * BlockNodeInformation will only hold a limited amount of blocks and peers. Blocks 32  * that aren't accessed frequently will be deleted, as well as peers. 33  * Peers will only remember the last maxBlocks blocks that were inserted. 34  */ 35 public class BlockNodeInformation { 36  private final LinkedHashMap<Keccak256, Set<NodeID>> nodesByBlock; 37  private final int maxBlocks; 38  39  public BlockNodeInformation(final int maxBlocks) { 40  this.maxBlocks = maxBlocks; 41  // Blocks are evicted in Least-recently-accessed order. 42  nodesByBlock = new LinkedHashMap<Keccak256, Set<NodeID>>(BlockNodeInformation.this.maxBlocks, 0.75f, true) { 43  @Override 44  protected boolean removeEldestEntry(Map.Entry<Keccak256, Set<NodeID>> eldest) { 45  return size() > BlockNodeInformation.this.maxBlocks; 46  } 47  }; 48  } 49  50  public BlockNodeInformation() { 51  this(1000); 52  } 53  54  /** 55  * addBlockToNode specifies that a given node knows about a given block. 56  * 57  * @param blockHash the block hash. 58  * @param nodeID the node to add the block to. 59  */ 60  public synchronized void addBlockToNode(@Nonnull final Keccak256 blockHash, @Nonnull final NodeID nodeID) { 61  Set<NodeID> blockNodes = nodesByBlock.get(blockHash); 62  if (blockNodes == null) { 63  // Create a new set for the nodes that know about a block. 64  // There is no peer eviction, because there are few peers compared to blocks. 65  blockNodes = new HashSet<>(); 66  nodesByBlock.put(blockHash, blockNodes); 67  } 68  69  blockNodes.add(nodeID); 70  } 71  72  /** 73  * getNodesByBlock retrieves all the nodes that contain a given block. 74  * 75  * @param blockHash the block's hash. 76  * @return A set containing all the nodes that have that block. 77  */ 78  @Nonnull 79  public synchronized Set<NodeID> getNodesByBlock(@Nonnull final Keccak256 blockHash) { 80  Set<NodeID> result = nodesByBlock.get(blockHash); 81  if (result == null) { 82  result = new HashSet<>(); 83  } 84  return new HashSet<>(result); 85  } 86  87  /** 88  * getNodesByBlock is a convenient function to avoid creating a Keccak256. 89  * 90  * @param blockHash the block hash. 91  * @return all the nodeIDs that contain the given block. 92  */ 93  @Nonnull 94  public Set<NodeID> getNodesByBlock(@Nonnull final byte[] blockHash) { 95  return getNodesByBlock(new Keccak256(blockHash)); 96  } 97  98 }