diff --git a/src/main/java/org/qortal/block/Block.java b/src/main/java/org/qortal/block/Block.java index c48ab234..2ef97ef5 100644 --- a/src/main/java/org/qortal/block/Block.java +++ b/src/main/java/org/qortal/block/Block.java @@ -1220,6 +1220,7 @@ public class Block { } } } catch (DataException e) { + LOGGER.info("DataException during transaction validation", e); return ValidationResult.TRANSACTION_INVALID; } finally { // Rollback repository changes made by test-processing transactions above diff --git a/src/main/java/org/qortal/network/Network.java b/src/main/java/org/qortal/network/Network.java index 10f02d52..57073e99 100644 --- a/src/main/java/org/qortal/network/Network.java +++ b/src/main/java/org/qortal/network/Network.java @@ -1375,26 +1375,17 @@ public class Network { // We attempted to connect within the last day // but we last managed to connect over a week ago. Predicate isNotOldPeer = peerData -> { - - // First check if there was a connection attempt within the last day - if (peerData.getLastAttempted() != null - && peerData.getLastAttempted() > now - OLD_PEER_ATTEMPTED_PERIOD) { - - // There was, so now check if we had a successful connection in the last 7 days - if (peerData.getLastConnected() != null - && peerData.getLastConnected() > now - OLD_PEER_CONNECTION_PERIOD) { - - // We did, so this is NOT an 'old' peer - return true; - } - - // Last successful connection was more than 1 week ago - this is an 'old' peer - return false; - } - else { - // Best to wait until we have a connection attempt - assume not an 'old' peer until then + if (peerData.getLastAttempted() == null + || peerData.getLastAttempted() < now - OLD_PEER_ATTEMPTED_PERIOD) { return true; } + + if (peerData.getLastConnected() == null + || peerData.getLastConnected() > now - OLD_PEER_CONNECTION_PERIOD) { + return true; + } + + return false; }; // Disregard peers that are NOT 'old' diff --git a/src/main/java/org/qortal/network/Peer.java b/src/main/java/org/qortal/network/Peer.java index f99a94b1..cac0ccc9 100644 --- a/src/main/java/org/qortal/network/Peer.java +++ b/src/main/java/org/qortal/network/Peer.java @@ -27,6 +27,8 @@ import java.nio.channels.SocketChannel; import java.security.SecureRandom; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.atomic.LongAccumulator; +import java.util.concurrent.atomic.LongAdder; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -153,6 +155,16 @@ public class Peer { */ private CommonBlockData commonBlockData; + // Message stats + + private static class MessageStats { + public final LongAdder count = new LongAdder(); + public final LongAdder totalBytes = new LongAdder(); + } + + private final Map receivedMessageStats = new ConcurrentHashMap<>(); + private final Map sentMessageStats = new ConcurrentHashMap<>(); + // Constructors /** @@ -542,11 +554,18 @@ public class Peer { // Tidy up buffers: this.byteBuffer.flip(); // Read-only, flipped buffer's position will be after end of message, so copy that + long messageByteSize = readOnlyBuffer.position(); this.byteBuffer.position(readOnlyBuffer.position()); // Copy bytes after read message to front of buffer, // adjusting position accordingly, reset limit to capacity this.byteBuffer.compact(); + // Record message stats + MessageStats messageStats = this.receivedMessageStats.computeIfAbsent(message.getType(), k -> new MessageStats()); + // Ideally these two operations would be atomic, we could pack 'count' in top X bits of the 64-bit long, but meh + messageStats.count.increment(); + messageStats.totalBytes.add(messageByteSize); + // Unsupported message type? Discard with no further processing if (message.getType() == MessageType.UNSUPPORTED) continue; @@ -609,6 +628,12 @@ public class Peer { LOGGER.trace("[{}] Sending {} message with ID {} to peer {}", this.peerConnectionId, this.outputMessageType, this.outputMessageId, this); + + // Record message stats + MessageStats messageStats = this.sentMessageStats.computeIfAbsent(message.getType(), k -> new MessageStats()); + // Ideally these two operations would be atomic, we could pack 'count' in top X bits of the 64-bit long, but meh + messageStats.count.increment(); + messageStats.totalBytes.add(this.outputBuffer.limit()); } catch (MessageException e) { // Something went wrong converting message to bytes, so discard but allow another round LOGGER.warn("[{}] Failed to send {} message with ID {} to peer {}: {}", this.peerConnectionId, @@ -799,8 +824,11 @@ public class Peer { } public void shutdown() { + boolean logStats = false; + if (!isStopping) { LOGGER.debug("[{}] Shutting down peer {}", this.peerConnectionId, this); + logStats = true; } isStopping = true; @@ -812,8 +840,34 @@ public class Peer { LOGGER.debug("[{}] IOException while trying to close peer {}", this.peerConnectionId, this); } } + + if (logStats && this.receivedMessageStats.size() > 0) { + StringBuilder statsBuilder = new StringBuilder(1024); + statsBuilder.append("peer ").append(this).append(" message stats:\n=received="); + appendMessageStats(statsBuilder, this.receivedMessageStats); + statsBuilder.append("\n=sent="); + appendMessageStats(statsBuilder, this.sentMessageStats); + + LOGGER.debug(statsBuilder.toString()); + } } + private static void appendMessageStats(StringBuilder statsBuilder, Map messageStats) { + if (messageStats.isEmpty()) { + statsBuilder.append("\n none"); + return; + } + + messageStats.keySet().stream() + .sorted(Comparator.comparing(MessageType::name)) + .forEach(messageType -> { + MessageStats stats = messageStats.get(messageType); + + statsBuilder.append("\n ").append(messageType.name()) + .append(": count=").append(stats.count.sum()) + .append(", total bytes=").append(stats.totalBytes.sum()); + }); + } // Minimum version diff --git a/src/main/java/org/qortal/settings/Settings.java b/src/main/java/org/qortal/settings/Settings.java index d21cdba6..f063b71d 100644 --- a/src/main/java/org/qortal/settings/Settings.java +++ b/src/main/java/org/qortal/settings/Settings.java @@ -211,9 +211,9 @@ public class Settings { private boolean allowConnectionsWithOlderPeerVersions = true; /** Minimum time (in seconds) that we should attempt to remain connected to a peer for */ - private int minPeerConnectionTime = 5 * 60; // seconds + private int minPeerConnectionTime = 60 * 60; // seconds /** Maximum time (in seconds) that we should attempt to remain connected to a peer for */ - private int maxPeerConnectionTime = 60 * 60; // seconds + private int maxPeerConnectionTime = 4 * 60 * 60; // seconds /** Maximum time (in seconds) that a peer should remain connected when requesting QDN data */ private int maxDataPeerConnectionTime = 2 * 60; // seconds