Coverage Summary for Class: CompositeEthereumListener (org.ethereum.listener)
Class |
Class, %
|
Method, %
|
Line, %
|
CompositeEthereumListener |
100%
(1/1)
|
31.6%
(6/19)
|
27.3%
(12/44)
|
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 org.ethereum.listener;
21
22 import co.rsk.panic.PanicProcessor;
23 import org.ethereum.core.Block;
24 import org.ethereum.core.Transaction;
25 import org.ethereum.core.TransactionPool;
26 import org.ethereum.core.TransactionReceipt;
27 import org.ethereum.net.eth.message.StatusMessage;
28 import org.ethereum.net.message.Message;
29 import org.ethereum.net.p2p.HelloMessage;
30 import org.ethereum.net.rlpx.Node;
31 import org.ethereum.net.server.Channel;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import java.util.List;
36 import java.util.concurrent.CopyOnWriteArrayList;
37 import java.util.function.Consumer;
38
39 /**
40 * @author Roman Mandeleil
41 * @since 12.11.2014
42 */
43 public class CompositeEthereumListener implements EthereumListener {
44 private static final Logger logger = LoggerFactory.getLogger("events");
45 private static final PanicProcessor panicProcessor = new PanicProcessor();
46
47 // Using a concurrent list
48 // (the add and remove methods copy an internal array,
49 // but the iterator directly use the internal array)
50 private final List<EthereumListener> listeners = new CopyOnWriteArrayList<>();
51
52 public void addListener(EthereumListener listener) {
53 listeners.add(listener);
54 }
55 public void removeListener(EthereumListener listener) {
56 listeners.remove(listener);
57 }
58
59 @Override
60 public void trace(String output) {
61 scheduleListenerCallbacks(listener -> listener.trace(output));
62 }
63
64 @Override
65 public void onBlock(Block block, List<TransactionReceipt> receipts) {
66 scheduleListenerCallbacks(listener -> listener.onBlock(block, receipts));
67 }
68
69 @Override
70 public void onBestBlock(Block block, List<TransactionReceipt> receipts) {
71 scheduleListenerCallbacks(listener -> listener.onBestBlock(block, receipts));
72 }
73
74 @Override
75 public void onRecvMessage(Channel channel, Message message) {
76 scheduleListenerCallbacks(listener -> listener.onRecvMessage(channel, message));
77 }
78
79 @Override
80 public void onPeerDisconnect(String host, long port) {
81 scheduleListenerCallbacks(listener -> listener.onPeerDisconnect(host, port));
82 }
83
84 @Override
85 public void onPendingTransactionsReceived(List<Transaction> transactions) {
86 scheduleListenerCallbacks(listener -> listener.onPendingTransactionsReceived(transactions));
87 }
88
89 @Override
90 public void onTransactionPoolChanged(TransactionPool transactionPool) {
91 scheduleListenerCallbacks(listener -> listener.onTransactionPoolChanged(transactionPool));
92 }
93
94 @Override
95 public void onNoConnections() {
96 scheduleListenerCallbacks(EthereumListener::onNoConnections);
97 }
98
99 @Override
100 public void onHandShakePeer(Channel channel, HelloMessage helloMessage) {
101 scheduleListenerCallbacks(listener -> listener.onHandShakePeer(channel, helloMessage));
102 }
103
104 @Override
105 public void onNodeDiscovered(Node node) {
106 scheduleListenerCallbacks(listener -> listener.onNodeDiscovered(node));
107 }
108
109 @Override
110 public void onEthStatusUpdated(Channel channel, StatusMessage status) {
111 scheduleListenerCallbacks(listener -> listener.onEthStatusUpdated(channel, status));
112 }
113
114 @Override
115 public void onPeerAddedToSyncPool(Channel peer) {
116 scheduleListenerCallbacks(listener -> listener.onPeerAddedToSyncPool(peer));
117 }
118
119 @Override
120 public void onLongSyncDone() {
121 scheduleListenerCallbacks(EthereumListener::onLongSyncDone);
122 }
123
124 @Override
125 public void onLongSyncStarted() {
126 scheduleListenerCallbacks(EthereumListener::onLongSyncStarted);
127 }
128
129 private void scheduleListenerCallbacks(Consumer<EthereumListener> callback) {
130 for (EthereumListener listener : listeners) {
131 try {
132 callback.accept(listener);
133 } catch (Throwable e) {
134 logger.error("Listener callback failed with exception", e);
135 panicProcessor.panic("thread", String.format("Listener callback failed with exception %s", e.getMessage()));
136 }
137 }
138 }
139 }