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 }