Coverage Summary for Class: FilterManager (org.ethereum.rpc)
Class |
Method, %
|
Line, %
|
FilterManager |
14.3%
(1/7)
|
12.7%
(7/55)
|
FilterManager$1 |
33.3%
(1/3)
|
20%
(1/5)
|
Total |
20%
(2/10)
|
13.3%
(8/60)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2018 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 org.ethereum.rpc;
20
21 import org.ethereum.core.Block;
22 import org.ethereum.core.Transaction;
23 import org.ethereum.core.TransactionReceipt;
24 import org.ethereum.facade.Ethereum;
25 import org.ethereum.listener.EthereumListenerAdapter;
26
27 import javax.annotation.concurrent.GuardedBy;
28 import java.util.*;
29 import java.util.concurrent.atomic.AtomicInteger;
30
31 /**
32 * Created by ajlopez on 17/01/2018.
33 */
34 public class FilterManager {
35 private static final long filterTimeout = 5 * 60 * 1000L; // 5 minutes in milliseconds
36 private static final long filterCleanupPeriod = 1 * 60 * 1000L; // 1 minute in milliseconds
37
38 private long latestFilterCleanup = System.currentTimeMillis();
39
40 private final Object filterLock = new Object();
41
42 private AtomicInteger filterCounter = new AtomicInteger(1);
43
44 @GuardedBy("filterLock")
45 private Map<Integer, Filter> installedFilters = new HashMap<>();
46
47 public FilterManager(Ethereum eth) {
48 eth.addListener(new EthereumListenerAdapter() {
49 @Override
50 public void onBlock(Block block, List<TransactionReceipt> receipts) {
51 newBlockReceived(block);
52 }
53
54 @Override
55 public void onPendingTransactionsReceived(List<Transaction> transactions) {
56 newPendingTx(transactions);
57 }
58 });
59 }
60
61 public int registerFilter(Filter filter) {
62 synchronized (filterLock) {
63 filtersCleanup();
64
65 int id = filterCounter.getAndIncrement();
66 installedFilters.put(id, filter);
67
68 return id;
69 }
70 }
71
72 public boolean removeFilter(int id) {
73 synchronized (filterLock) {
74 return installedFilters.remove(id) != null;
75 }
76 }
77
78 public Object[] getFilterEvents(int id, boolean newevents) {
79 synchronized (filterLock) {
80 filtersCleanup();
81
82 Filter filter = installedFilters.get(id);
83
84 if (filter == null) {
85 return null;
86 }
87
88 if (newevents) {
89 return filter.getNewEvents();
90 }
91 else {
92 return filter.getEvents();
93 }
94 }
95 }
96
97 public void newBlockReceived(Block block) {
98 synchronized (filterLock) {
99 filtersCleanup();
100
101 for (Filter filter : installedFilters.values()) {
102 filter.newBlockReceived(block);
103 }
104 }
105 }
106
107 public void newPendingTx(List<Transaction> transactions) {
108 synchronized (filterLock) {
109 filtersCleanup();
110
111 for (Filter filter : installedFilters.values()) {
112 for (Transaction tx : transactions) {
113 filter.newPendingTx(tx);
114 }
115 }
116 }
117 }
118
119 private void filtersCleanup() {
120 long now = System.currentTimeMillis();
121
122 if (latestFilterCleanup + filterCleanupPeriod > now) {
123 return;
124 }
125
126 List<Integer> toremove = new ArrayList<>();
127
128 for (Map.Entry<Integer, Filter> entry : installedFilters.entrySet()) {
129 Filter f = entry.getValue();
130
131 if (f.hasExpired(filterTimeout)) {
132 toremove.add(entry.getKey());
133 }
134 }
135
136 for (Integer id : toremove) {
137 installedFilters.remove(id);
138 }
139
140 latestFilterCleanup = now;
141 }
142 }