Coverage Summary for Class: BlocksBloomProcessor (co.rsk.logfilter)
Class |
Class, %
|
Method, %
|
Line, %
|
BlocksBloomProcessor |
0%
(0/1)
|
0%
(0/7)
|
0%
(0/28)
|
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 co.rsk.logfilter;
21
22 import com.google.common.annotations.VisibleForTesting;
23 import org.ethereum.core.Bloom;
24 import org.ethereum.db.BlockStore;
25
26 /**
27 * Process bloom filters from blocks
28 *
29 * It collects bloom filter from flocks with enough confirmations
30 * grouping then in a BlocksBloom instance
31 *
32 * When a new height should be processed, the
33 * BlocksBloom instance is feeded with the block blooms
34 * up to that height
35 *
36 * When the BlocksBloom instance is filled, it is saved into the BlocksBloomStore
37 * and a new instance starts to be processed
38 *
39 * Created by ajlopez on 29/09/2020.
40 */
41 public class BlocksBloomProcessor {
42 private final BlocksBloomStore blocksBloomStore;
43 private final BlockStore blockStore;
44
45 private BlocksBloom blocksBloomInProcess = null;
46
47 public BlocksBloomProcessor(BlocksBloomStore blocksBloomStore, BlockStore blockStore) {
48 this.blocksBloomStore = blocksBloomStore;
49 this.blockStore = blockStore;
50 }
51
52 @VisibleForTesting
53 public BlocksBloom getBlocksBloomInProcess() {
54 return this.blocksBloomInProcess;
55 }
56
57 /**
58 * Receives the new height to process.
59 * Processes the block blooms up to that height minus the number of needed confirmations
60 *
61 * @param newBlockNumber the new height to process
62 */
63 public synchronized void processNewBlockNumber(long newBlockNumber) {
64 if (newBlockNumber < this.blocksBloomStore.getNoConfirmations()) {
65 return;
66 }
67
68 long blockNumber = newBlockNumber - this.blocksBloomStore.getNoConfirmations();
69
70 if (!alreadyAdded(blockNumber)) {
71 for (long aBlockNumber = fromBlock(blockNumber); aBlockNumber <= blockNumber; aBlockNumber++) {
72 this.addBlock(aBlockNumber);
73 }
74 }
75 }
76
77 private boolean alreadyAdded(long blockNumber) {
78 return this.blocksBloomStore.hasBlockNumber(blockNumber) ||
79 (this.blocksBloomInProcess != null && this.blocksBloomInProcess.hasBlockBloom(blockNumber));
80 }
81
82 private long fromBlock(long blockNumber) {
83 long fromBlock;
84 if (this.blocksBloomInProcess == null) {
85 this.blocksBloomInProcess = new BlocksBloom();
86 fromBlock = this.blocksBloomStore.firstNumberInRange(blockNumber);
87 }
88 else {
89 fromBlock = this.blocksBloomInProcess.toBlock() + 1;
90 }
91 return fromBlock;
92 }
93
94 /**
95 * Reads and collect the bloom from the block that corresponds to the provided block number
96 *
97 * If the BlocksBloom instance is fulfilled, it is saved into the store
98 * and a new instance will be created at the process of the next block number
99 *
100 * @param blockNumber block number to process
101 */
102 private void addBlock(long blockNumber) {
103 Bloom bloom = bloomByBlockNumber(blockNumber);
104
105 if (this.blocksBloomInProcess == null) {
106 this.blocksBloomInProcess = new BlocksBloom();
107 }
108
109 this.blocksBloomInProcess.addBlockBloom(blockNumber, bloom);
110
111 if (blockNumber == this.blocksBloomStore.lastNumberInRange(blockNumber)) {
112 this.blocksBloomStore.addBlocksBloom(this.blocksBloomInProcess);
113 this.blocksBloomInProcess = null;
114 }
115 }
116
117 private Bloom bloomByBlockNumber(long blockNumber) {
118 Bloom bloom;
119 if (blockNumber > 0) {
120 bloom = this.blockStore.bloomByBlockNumber(blockNumber);
121 }
122 else {
123 bloom = new Bloom();
124 }
125 return bloom;
126 }
127 }