mirror of
https://github.com/Qortal/qortal.git
synced 2025-11-03 11:57:03 +00:00
delay database writes to the shutdown phase since the database is only read on startup
This commit is contained in:
@@ -235,6 +235,8 @@ public class Network {
|
|||||||
this.allKnownPeers.addAll(repository.getNetworkRepository().getAllPeers());
|
this.allKnownPeers.addAll(repository.getNetworkRepository().getAllPeers());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGGER.debug("starting with {} known peers", this.allKnownPeers.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to set up UPnP. All errors are ignored.
|
// Attempt to set up UPnP. All errors are ignored.
|
||||||
@@ -711,63 +713,49 @@ public class Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Peer getConnectablePeer(final Long now) throws InterruptedException {
|
private Peer getConnectablePeer(final Long now) throws InterruptedException {
|
||||||
// We can't block here so use tryRepository(). We don't NEED to connect a new peer.
|
|
||||||
try (Repository repository = RepositoryManager.tryRepository()) {
|
|
||||||
if (repository == null) {
|
|
||||||
LOGGER.warn("Unable to get repository connection : Network.getConnectablePeer()");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find an address to connect to
|
// Find an address to connect to
|
||||||
List<PeerData> peers = this.getAllKnownPeers();
|
List<PeerData> peers = this.getAllKnownPeers();
|
||||||
|
|
||||||
// Don't consider peers with recent connection failures
|
// Don't consider peers with recent connection failures
|
||||||
final long lastAttemptedThreshold = now - CONNECT_FAILURE_BACKOFF;
|
final long lastAttemptedThreshold = now - CONNECT_FAILURE_BACKOFF;
|
||||||
peers.removeIf(peerData -> peerData.getLastAttempted() != null
|
peers.removeIf(peerData -> peerData.getLastAttempted() != null
|
||||||
&& (peerData.getLastConnected() == null
|
&& (peerData.getLastConnected() == null
|
||||||
|| peerData.getLastConnected() < peerData.getLastAttempted())
|
|| peerData.getLastConnected() < peerData.getLastAttempted())
|
||||||
&& peerData.getLastAttempted() > lastAttemptedThreshold);
|
&& peerData.getLastAttempted() > lastAttemptedThreshold);
|
||||||
|
|
||||||
// Don't consider peers that we know loop back to ourself
|
// Don't consider peers that we know loop back to ourself
|
||||||
synchronized (this.selfPeers) {
|
synchronized (this.selfPeers) {
|
||||||
peers.removeIf(isSelfPeer);
|
peers.removeIf(isSelfPeer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't consider already connected peers (simple address match)
|
// Don't consider already connected peers (simple address match)
|
||||||
peers.removeIf(isConnectedPeer);
|
peers.removeIf(isConnectedPeer);
|
||||||
|
|
||||||
// Don't consider already connected peers (resolved address match)
|
// Don't consider already connected peers (resolved address match)
|
||||||
// Disabled because this might be too slow if we end up waiting a long time for hostnames to resolve via DNS
|
// Disabled because this might be too slow if we end up waiting a long time for hostnames to resolve via DNS
|
||||||
// Which is ok because duplicate connections to the same peer are handled during handshaking
|
// Which is ok because duplicate connections to the same peer are handled during handshaking
|
||||||
// peers.removeIf(isResolvedAsConnectedPeer);
|
// peers.removeIf(isResolvedAsConnectedPeer);
|
||||||
|
|
||||||
this.checkLongestConnection(now);
|
this.checkLongestConnection(now);
|
||||||
|
|
||||||
// Any left?
|
// Any left?
|
||||||
if (peers.isEmpty()) {
|
if (peers.isEmpty()) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pick random peer
|
|
||||||
int peerIndex = new Random().nextInt(peers.size());
|
|
||||||
|
|
||||||
// Pick candidate
|
|
||||||
PeerData peerData = peers.get(peerIndex);
|
|
||||||
Peer newPeer = new Peer(peerData);
|
|
||||||
newPeer.setIsDataPeer(false);
|
|
||||||
|
|
||||||
// Update connection attempt info
|
|
||||||
peerData.setLastAttempted(now);
|
|
||||||
synchronized (this.allKnownPeers) {
|
|
||||||
repository.getNetworkRepository().save(peerData);
|
|
||||||
repository.saveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
return newPeer;
|
|
||||||
} catch (DataException e) {
|
|
||||||
LOGGER.error("Repository issue while finding a connectable peer", e);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pick random peer
|
||||||
|
int peerIndex = new Random().nextInt(peers.size());
|
||||||
|
|
||||||
|
// Pick candidate
|
||||||
|
PeerData peerData = peers.get(peerIndex);
|
||||||
|
Peer newPeer = new Peer(peerData);
|
||||||
|
newPeer.setIsDataPeer(false);
|
||||||
|
|
||||||
|
// Update connection attempt info
|
||||||
|
peerData.setLastAttempted(now);
|
||||||
|
|
||||||
|
return newPeer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean connectPeer(Peer newPeer) throws InterruptedException {
|
public boolean connectPeer(Peer newPeer) throws InterruptedException {
|
||||||
@@ -947,18 +935,6 @@ public class Network {
|
|||||||
public void peerMisbehaved(Peer peer) {
|
public void peerMisbehaved(Peer peer) {
|
||||||
PeerData peerData = peer.getPeerData();
|
PeerData peerData = peer.getPeerData();
|
||||||
peerData.setLastMisbehaved(NTP.getTime());
|
peerData.setLastMisbehaved(NTP.getTime());
|
||||||
|
|
||||||
// Only update repository if outbound peer
|
|
||||||
if (peer.isOutbound()) {
|
|
||||||
try (Repository repository = RepositoryManager.getRepository()) {
|
|
||||||
synchronized (this.allKnownPeers) {
|
|
||||||
repository.getNetworkRepository().save(peerData);
|
|
||||||
repository.saveChanges();
|
|
||||||
}
|
|
||||||
} catch (DataException e) {
|
|
||||||
LOGGER.warn("Repository issue while updating peer synchronization info", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1148,19 +1124,6 @@ public class Network {
|
|||||||
// Make a note that we've successfully completed handshake (and when)
|
// Make a note that we've successfully completed handshake (and when)
|
||||||
peer.getPeerData().setLastConnected(NTP.getTime());
|
peer.getPeerData().setLastConnected(NTP.getTime());
|
||||||
|
|
||||||
// Update connection info for outbound peers only
|
|
||||||
if (peer.isOutbound()) {
|
|
||||||
try (Repository repository = RepositoryManager.getRepository()) {
|
|
||||||
synchronized (this.allKnownPeers) {
|
|
||||||
repository.getNetworkRepository().save(peer.getPeerData());
|
|
||||||
repository.saveChanges();
|
|
||||||
}
|
|
||||||
} catch (DataException e) {
|
|
||||||
LOGGER.error("[{}] Repository issue while trying to update outbound peer {}",
|
|
||||||
peer.getPeerConnectionId(), peer, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process any pending signature requests, as this peer may have been connected for this purpose only
|
// Process any pending signature requests, as this peer may have been connected for this purpose only
|
||||||
List<byte[]> pendingSignatureRequests = new ArrayList<>(peer.getPendingSignatureRequests());
|
List<byte[]> pendingSignatureRequests = new ArrayList<>(peer.getPendingSignatureRequests());
|
||||||
if (pendingSignatureRequests != null && !pendingSignatureRequests.isEmpty()) {
|
if (pendingSignatureRequests != null && !pendingSignatureRequests.isEmpty()) {
|
||||||
@@ -1424,32 +1387,23 @@ public class Network {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean forgetPeer(PeerAddress peerAddress) throws DataException {
|
public boolean forgetPeer(PeerAddress peerAddress) throws DataException {
|
||||||
int numDeleted;
|
boolean numDeleted;
|
||||||
|
|
||||||
synchronized (this.allKnownPeers) {
|
synchronized (this.allKnownPeers) {
|
||||||
this.allKnownPeers.removeIf(peerData -> peerData.getAddress().equals(peerAddress));
|
numDeleted = this.allKnownPeers.removeIf(peerData -> peerData.getAddress().equals(peerAddress));
|
||||||
|
|
||||||
try (Repository repository = RepositoryManager.getRepository()) {
|
|
||||||
numDeleted = repository.getNetworkRepository().delete(peerAddress);
|
|
||||||
repository.saveChanges();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectPeer(peerAddress);
|
disconnectPeer(peerAddress);
|
||||||
|
|
||||||
return numDeleted != 0;
|
return numDeleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int forgetAllPeers() throws DataException {
|
public int forgetAllPeers() throws DataException {
|
||||||
int numDeleted;
|
int numDeleted;
|
||||||
|
|
||||||
synchronized (this.allKnownPeers) {
|
synchronized (this.allKnownPeers) {
|
||||||
|
numDeleted = this.allKnownPeers.size();
|
||||||
this.allKnownPeers.clear();
|
this.allKnownPeers.clear();
|
||||||
|
|
||||||
try (Repository repository = RepositoryManager.getRepository()) {
|
|
||||||
numDeleted = repository.getNetworkRepository().deleteAllPeers();
|
|
||||||
repository.saveChanges();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Peer peer : this.getImmutableConnectedPeers()) {
|
for (Peer peer : this.getImmutableConnectedPeers()) {
|
||||||
@@ -1498,48 +1452,36 @@ public class Network {
|
|||||||
|
|
||||||
// Prune 'old' peers from repository...
|
// Prune 'old' peers from repository...
|
||||||
// Pruning peers isn't critical so no need to block for a repository instance.
|
// Pruning peers isn't critical so no need to block for a repository instance.
|
||||||
try (Repository repository = RepositoryManager.tryRepository()) {
|
synchronized (this.allKnownPeers) {
|
||||||
if (repository == null) {
|
// Fetch all known peers
|
||||||
LOGGER.warn("Unable to get repository connection : Network.prunePeers()");
|
List<PeerData> peers = new ArrayList<>(this.allKnownPeers);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (this.allKnownPeers) {
|
// 'Old' peers:
|
||||||
// Fetch all known peers
|
// We attempted to connect within the last day
|
||||||
List<PeerData> peers = new ArrayList<>(this.allKnownPeers);
|
// but we last managed to connect over a week ago.
|
||||||
|
Predicate<PeerData> isNotOldPeer = peerData -> {
|
||||||
// 'Old' peers:
|
if (peerData.getLastAttempted() == null
|
||||||
// We attempted to connect within the last day
|
|| peerData.getLastAttempted() < now - OLD_PEER_ATTEMPTED_PERIOD) {
|
||||||
// but we last managed to connect over a week ago.
|
return true;
|
||||||
Predicate<PeerData> isNotOldPeer = peerData -> {
|
|
||||||
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'
|
|
||||||
peers.removeIf(isNotOldPeer);
|
|
||||||
|
|
||||||
// Don't consider already connected peers (simple address match)
|
|
||||||
peers.removeIf(isConnectedPeer);
|
|
||||||
|
|
||||||
for (PeerData peerData : peers) {
|
|
||||||
LOGGER.debug("Deleting old peer {} from repository", peerData.getAddress().toString());
|
|
||||||
repository.getNetworkRepository().delete(peerData.getAddress());
|
|
||||||
|
|
||||||
// Delete from known peer cache too
|
|
||||||
this.allKnownPeers.remove(peerData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
repository.saveChanges();
|
if (peerData.getLastConnected() == null
|
||||||
|
|| peerData.getLastConnected() > now - OLD_PEER_CONNECTION_PERIOD) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Disregard peers that are NOT 'old'
|
||||||
|
peers.removeIf(isNotOldPeer);
|
||||||
|
|
||||||
|
// Don't consider already connected peers (simple address match)
|
||||||
|
peers.removeIf(isConnectedPeer);
|
||||||
|
|
||||||
|
for (PeerData peerData : peers) {
|
||||||
|
// Delete from known peer cache too
|
||||||
|
this.allKnownPeers.remove(peerData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1547,8 +1489,8 @@ public class Network {
|
|||||||
public boolean mergePeers(String addedBy, long addedWhen, List<PeerAddress> peerAddresses) throws DataException {
|
public boolean mergePeers(String addedBy, long addedWhen, List<PeerAddress> peerAddresses) throws DataException {
|
||||||
mergePeersLock.lock();
|
mergePeersLock.lock();
|
||||||
|
|
||||||
try (Repository repository = RepositoryManager.getRepository()) {
|
try{
|
||||||
return this.mergePeers(repository, addedBy, addedWhen, peerAddresses);
|
return this.mergePeersUnlocked(addedBy, addedWhen, peerAddresses);
|
||||||
} finally {
|
} finally {
|
||||||
mergePeersLock.unlock();
|
mergePeersLock.unlock();
|
||||||
}
|
}
|
||||||
@@ -1567,23 +1509,17 @@ public class Network {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Merging peers isn't critical so don't block for a repository instance.
|
// Merging peers isn't critical so don't block for a repository instance.
|
||||||
try (Repository repository = RepositoryManager.tryRepository()) {
|
|
||||||
if (repository == null) {
|
|
||||||
LOGGER.warn("Unable to get repository connection : Network.opportunisticMergePeers()");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mergePeers(repository, addedBy, addedWhen, peerAddresses);
|
this.mergePeersUnlocked(addedBy, addedWhen, peerAddresses);
|
||||||
|
|
||||||
} catch (DataException e) {
|
} catch (DataException e) {
|
||||||
// Already logged by this.mergePeers()
|
// Already logged by this.mergePeersUnlocked()
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
mergePeersLock.unlock();
|
mergePeersLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mergePeers(Repository repository, String addedBy, long addedWhen, List<PeerAddress> peerAddresses)
|
private boolean mergePeersUnlocked(String addedBy, long addedWhen, List<PeerAddress> peerAddresses)
|
||||||
throws DataException {
|
throws DataException {
|
||||||
List<String> fixedNetwork = Settings.getInstance().getFixedNetwork();
|
List<String> fixedNetwork = Settings.getInstance().getFixedNetwork();
|
||||||
if (fixedNetwork != null && !fixedNetwork.isEmpty()) {
|
if (fixedNetwork != null && !fixedNetwork.isEmpty()) {
|
||||||
@@ -1608,19 +1544,6 @@ public class Network {
|
|||||||
|
|
||||||
this.allKnownPeers.addAll(newPeers);
|
this.allKnownPeers.addAll(newPeers);
|
||||||
|
|
||||||
try {
|
|
||||||
// Save new peers into database
|
|
||||||
for (PeerData peerData : newPeers) {
|
|
||||||
LOGGER.info("Adding new peer {} to repository", peerData.getAddress());
|
|
||||||
repository.getNetworkRepository().save(peerData);
|
|
||||||
}
|
|
||||||
|
|
||||||
repository.saveChanges();
|
|
||||||
} catch (DataException e) {
|
|
||||||
LOGGER.error("Repository issue while merging peers list from {}", addedBy, e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1665,6 +1588,33 @@ public class Network {
|
|||||||
LOGGER.warn("Interrupted while waiting for networking threads to terminate");
|
LOGGER.warn("Interrupted while waiting for networking threads to terminate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try( Repository repository = RepositoryManager.getRepository() ){
|
||||||
|
|
||||||
|
// reset all known peers in database
|
||||||
|
int deletedCount = repository.getNetworkRepository().deleteAllPeers();
|
||||||
|
|
||||||
|
LOGGER.debug("Deleted {} known peers", deletedCount);
|
||||||
|
|
||||||
|
List<PeerData> knownPeersToProcess;
|
||||||
|
synchronized (this.allKnownPeers) {
|
||||||
|
knownPeersToProcess = new ArrayList<>(this.allKnownPeers);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addedPeerCount = 0;
|
||||||
|
|
||||||
|
// save all known peers for next start up
|
||||||
|
for (PeerData knownPeerToProcess : knownPeersToProcess) {
|
||||||
|
repository.getNetworkRepository().save(knownPeerToProcess);
|
||||||
|
addedPeerCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
repository.saveChanges();
|
||||||
|
|
||||||
|
LOGGER.debug("Added {} known peers", addedPeerCount);
|
||||||
|
} catch (DataException e) {
|
||||||
|
LOGGER.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
// Close all peer connections
|
// Close all peer connections
|
||||||
for (Peer peer : this.getImmutableConnectedPeers()) {
|
for (Peer peer : this.getImmutableConnectedPeers()) {
|
||||||
peer.shutdown();
|
peer.shutdown();
|
||||||
|
|||||||
Reference in New Issue
Block a user