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 }