mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-19 01:40:26 +01:00
Peer: migrate pingIntervals
field to java.time
API
This commit is contained in:
parent
dce930f487
commit
04c72ce003
@ -58,6 +58,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@ -167,8 +168,8 @@ public class Peer extends PeerSocketHandler {
|
||||
@GuardedBy("getAddrFutures") private final LinkedList<CompletableFuture<AddressMessage>> getAddrFutures;
|
||||
|
||||
// Outstanding pings against this peer and how long the last one took to complete.
|
||||
private final ReentrantLock lastPingTimesLock = new ReentrantLock();
|
||||
@GuardedBy("lastPingTimesLock") private long[] lastPingTimes = null;
|
||||
private final ReentrantLock pingIntervalsLock = new ReentrantLock();
|
||||
@GuardedBy("pingIntervalsLock") private Duration[] pingIntervals = null;
|
||||
private final CopyOnWriteArrayList<PendingPing> pendingPings;
|
||||
// Disconnect from a peer that is not responding to Pings
|
||||
private static final int PENDING_PINGS_LIMIT = 50;
|
||||
@ -1498,7 +1499,7 @@ public class Peer extends PeerSocketHandler {
|
||||
public void complete() {
|
||||
if (!future.isDone()) {
|
||||
Duration elapsed = TimeUtils.elapsedTime(startTime);
|
||||
Peer.this.addPingTimeData(elapsed.toMillis());
|
||||
Peer.this.addPingInterval(elapsed);
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("{}: ping time is {} ms", Peer.this.toString(), elapsed.toMillis());
|
||||
future.complete(elapsed);
|
||||
@ -1507,28 +1508,28 @@ public class Peer extends PeerSocketHandler {
|
||||
}
|
||||
|
||||
/** Adds a ping time sample to the averaging window. */
|
||||
private void addPingTimeData(long sample) {
|
||||
lastPingTimesLock.lock();
|
||||
private void addPingInterval(Duration sample) {
|
||||
pingIntervalsLock.lock();
|
||||
try {
|
||||
if (lastPingTimes == null) {
|
||||
lastPingTimes = new long[PING_MOVING_AVERAGE_WINDOW];
|
||||
if (pingIntervals == null) {
|
||||
pingIntervals = new Duration[PING_MOVING_AVERAGE_WINDOW];
|
||||
// Initialize the averaging window to the first sample.
|
||||
Arrays.fill(lastPingTimes, sample);
|
||||
Arrays.fill(pingIntervals, sample);
|
||||
} else {
|
||||
// Shift all elements backwards by one.
|
||||
System.arraycopy(lastPingTimes, 1, lastPingTimes, 0, lastPingTimes.length - 1);
|
||||
System.arraycopy(pingIntervals, 1, pingIntervals, 0, pingIntervals.length - 1);
|
||||
// And append the new sample to the end.
|
||||
lastPingTimes[lastPingTimes.length - 1] = sample;
|
||||
pingIntervals[pingIntervals.length - 1] = sample;
|
||||
}
|
||||
} finally {
|
||||
lastPingTimesLock.unlock();
|
||||
pingIntervalsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the peer a ping message and returns a future that will be completed when the pong is received back.
|
||||
* The future provides a {@link Duration} which contains the time elapsed between the ping and the pong.
|
||||
* Once the pong is received the value returned by {@link Peer#getLastPingTime()} is updated.
|
||||
* Once the pong is received the value returned by {@link Peer#lastPingInterval()} is updated.
|
||||
* The future completes exceptionally with a {@link ProtocolException} if the peer version is too low to support measurable pings.
|
||||
* @return A future for the duration representing elapsed time
|
||||
*/
|
||||
@ -1560,37 +1561,57 @@ public class Peer extends PeerSocketHandler {
|
||||
|
||||
/**
|
||||
* Returns the elapsed time of the last ping/pong cycle. If {@link Peer#sendPing()} has never
|
||||
* been called or we did not hear back the "pong" message yet, returns {@link Long#MAX_VALUE}.
|
||||
* been called or we did not hear back the "pong" message yet, returns empty.
|
||||
* @return last ping, or empty
|
||||
*/
|
||||
public long getLastPingTime() {
|
||||
lastPingTimesLock.lock();
|
||||
public Optional<Duration> lastPingInterval() {
|
||||
pingIntervalsLock.lock();
|
||||
try {
|
||||
if (lastPingTimes == null)
|
||||
return Long.MAX_VALUE;
|
||||
return lastPingTimes[lastPingTimes.length - 1];
|
||||
if (pingIntervals == null || pingIntervals.length == 0)
|
||||
return Optional.empty();
|
||||
return Optional.of(pingIntervals[pingIntervals.length - 1]);
|
||||
} finally {
|
||||
lastPingTimesLock.unlock();
|
||||
pingIntervalsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #lastPingInterval()} */
|
||||
@Deprecated
|
||||
public long getLastPingTime() {
|
||||
Optional<Duration> lastPingInterval = lastPingInterval();
|
||||
return lastPingInterval.isPresent() ?
|
||||
lastPingInterval.get().toMillis() :
|
||||
Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a moving average of the last N ping/pong cycles. If {@link Peer#sendPing()} has never
|
||||
* been called or we did not hear back the "pong" message yet, returns {@link Long#MAX_VALUE}. The moving average
|
||||
* been called or we did not hear back the "pong" message yet, returns empty. The moving average
|
||||
* window is 5 buckets.
|
||||
* @return moving average, or empty
|
||||
*/
|
||||
public long getPingTime() {
|
||||
lastPingTimesLock.lock();
|
||||
public Optional<Duration> pingInterval() {
|
||||
pingIntervalsLock.lock();
|
||||
try {
|
||||
if (lastPingTimes == null)
|
||||
return Long.MAX_VALUE;
|
||||
long sum = 0;
|
||||
for (long i : lastPingTimes) sum += i;
|
||||
return (long)((double) sum / lastPingTimes.length);
|
||||
if (pingIntervals == null || pingIntervals.length == 0)
|
||||
return Optional.empty();
|
||||
Duration sum = Duration.ZERO;
|
||||
for (Duration i : pingIntervals) sum = sum.plus(i);
|
||||
return Optional.of(sum.dividedBy(pingIntervals.length));
|
||||
} finally {
|
||||
lastPingTimesLock.unlock();
|
||||
pingIntervalsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #pingInterval()} */
|
||||
@Deprecated
|
||||
public long getPingTime() {
|
||||
Optional<Duration> pingInterval = pingInterval();
|
||||
return pingInterval.isPresent() ?
|
||||
pingInterval.get().toMillis() :
|
||||
Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
private void processPing(Ping m) {
|
||||
if (m.hasNonce())
|
||||
sendMessage(new Pong(m.getNonce()));
|
||||
|
@ -2248,7 +2248,7 @@ public class PeerGroup implements TransactionBroadcaster {
|
||||
|
||||
/**
|
||||
* Returns the period between pings for an individual peer. Setting this lower means more accurate and timely ping
|
||||
* times are available via {@link Peer#getLastPingTime()} but it increases load on the
|
||||
* times are available via {@link Peer#lastPingInterval()} but it increases load on the
|
||||
* remote node. It defaults to {@link PeerGroup#DEFAULT_PING_INTERVAL_MSEC}.
|
||||
*/
|
||||
public long getPingIntervalMsec() {
|
||||
@ -2262,7 +2262,7 @@ public class PeerGroup implements TransactionBroadcaster {
|
||||
|
||||
/**
|
||||
* Sets the period between pings for an individual peer. Setting this lower means more accurate and timely ping
|
||||
* times are available via {@link Peer#getLastPingTime()} but it increases load on the
|
||||
* times are available via {@link Peer#lastPingInterval()} but it increases load on the
|
||||
* remote node. It defaults to {@link PeerGroup#DEFAULT_PING_INTERVAL_MSEC}.
|
||||
* Setting the value to be smaller or equals 0 disables pinging entirely, although you can still request one yourself
|
||||
* using {@link Peer#sendPing()}.
|
||||
|
@ -35,6 +35,7 @@ import javax.swing.table.TableColumnModel;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@ -255,9 +256,9 @@ public class PeerMonitor {
|
||||
Coin feeFilter = peer.getFeeFilter();
|
||||
return feeFilter != null ? feeFilter.toFriendlyString() : "";
|
||||
case PING_TIME:
|
||||
return peer.getPingTime();
|
||||
return peer.pingInterval().map(Duration::toMillis).orElse(0L);
|
||||
case LAST_PING_TIME:
|
||||
return peer.getLastPingTime();
|
||||
return peer.lastPingInterval().map(Duration::toMillis).orElse(0L);
|
||||
case ADDRESSES:
|
||||
return getAddressesForPeer(peer);
|
||||
|
||||
|
@ -459,7 +459,7 @@ public class PeerGroupTest extends TestWithPeerGroup {
|
||||
versionMessage.localServices = VersionMessage.NODE_NETWORK;
|
||||
connectPeer(1, versionMessage);
|
||||
peerGroup.waitForPeers(1).get();
|
||||
assertFalse(peerGroup.getConnectedPeers().get(0).getLastPingTime() < Long.MAX_VALUE);
|
||||
assertFalse(peerGroup.getConnectedPeers().get(0).lastPingInterval().isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -473,11 +473,11 @@ public class PeerGroupTest extends TestWithPeerGroup {
|
||||
Ping ping = (Ping) waitForOutbound(p1);
|
||||
inbound(p1, new Pong(ping.getNonce()));
|
||||
pingAndWait(p1);
|
||||
assertTrue(peerGroup.getConnectedPeers().get(0).getLastPingTime() < Long.MAX_VALUE);
|
||||
assertTrue(peerGroup.getConnectedPeers().get(0).lastPingInterval().isPresent());
|
||||
// The call to outbound should block until a ping arrives.
|
||||
ping = (Ping) waitForOutbound(p1);
|
||||
inbound(p1, new Pong(ping.getNonce()));
|
||||
assertTrue(peerGroup.getConnectedPeers().get(0).getLastPingTime() < Long.MAX_VALUE);
|
||||
assertTrue(peerGroup.getConnectedPeers().get(0).lastPingInterval().isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -506,11 +506,11 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
connect();
|
||||
TimeUtils.setMockClock();
|
||||
// No ping pong happened yet.
|
||||
assertEquals(Long.MAX_VALUE, peer.getLastPingTime());
|
||||
assertEquals(Long.MAX_VALUE, peer.getPingTime());
|
||||
assertFalse(peer.lastPingInterval().isPresent());
|
||||
assertFalse(peer.pingInterval().isPresent());
|
||||
CompletableFuture<Duration> future = peer.sendPing();
|
||||
assertEquals(Long.MAX_VALUE, peer.getLastPingTime());
|
||||
assertEquals(Long.MAX_VALUE, peer.getPingTime());
|
||||
assertFalse(peer.lastPingInterval().isPresent());
|
||||
assertFalse(peer.pingInterval().isPresent());
|
||||
assertFalse(future.isDone());
|
||||
Ping pingMsg = (Ping) outbound(writeTarget);
|
||||
TimeUtils.rollMockClock(Duration.ofSeconds(5));
|
||||
@ -520,16 +520,16 @@ public class PeerTest extends TestWithNetworkConnections {
|
||||
assertTrue(future.isDone());
|
||||
Duration elapsed = future.get();
|
||||
assertTrue(elapsed.toMillis() + " ms", elapsed.toMillis() > 1000);
|
||||
assertEquals(elapsed.toMillis(), peer.getLastPingTime());
|
||||
assertEquals(elapsed.toMillis(), peer.getPingTime());
|
||||
assertEquals(elapsed, peer.lastPingInterval().get());
|
||||
assertEquals(elapsed, peer.pingInterval().get());
|
||||
// Do it again and make sure it affects the average.
|
||||
CompletableFuture<Duration> future2 = peer.sendPing();
|
||||
pingMsg = (Ping) outbound(writeTarget);
|
||||
TimeUtils.rollMockClock(Duration.ofSeconds(50));
|
||||
inbound(writeTarget, new Pong(pingMsg.getNonce()));
|
||||
Duration elapsed2 = future2.get();
|
||||
assertEquals(elapsed2.toMillis(), peer.getLastPingTime());
|
||||
assertEquals(7250, peer.getPingTime());
|
||||
assertEquals(elapsed2, peer.lastPingInterval().get());
|
||||
assertEquals(Duration.ofMillis(7250), peer.pingInterval().get());
|
||||
TimeUtils.clearMockClock();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user