forked from Qortal/qortal
Merge remote-tracking branch 'alphax/master'
This commit is contained in:
commit
497259f652
2
pom.xml
2
pom.xml
@ -49,7 +49,7 @@
|
|||||||
<maven-reproducible-build-plugin.version>0.17</maven-reproducible-build-plugin.version>
|
<maven-reproducible-build-plugin.version>0.17</maven-reproducible-build-plugin.version>
|
||||||
<maven-resources-plugin.version>3.3.1</maven-resources-plugin.version>
|
<maven-resources-plugin.version>3.3.1</maven-resources-plugin.version>
|
||||||
<maven-shade-plugin.version>3.6.0</maven-shade-plugin.version>
|
<maven-shade-plugin.version>3.6.0</maven-shade-plugin.version>
|
||||||
<maven-surefire-plugin.version>3.5.1</maven-surefire-plugin.version>
|
<maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
|
||||||
<protobuf.version>3.25.3</protobuf.version>
|
<protobuf.version>3.25.3</protobuf.version>
|
||||||
<replacer.version>1.5.3</replacer.version>
|
<replacer.version>1.5.3</replacer.version>
|
||||||
<simplemagic.version>1.17</simplemagic.version>
|
<simplemagic.version>1.17</simplemagic.version>
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
package org.qortal;
|
package org.qortal;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
|
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
|
||||||
import org.qortal.api.ApiKey;
|
import org.qortal.api.ApiKey;
|
||||||
import org.qortal.api.ApiRequest;
|
import org.qortal.api.ApiRequest;
|
||||||
|
import org.qortal.controller.Controller;
|
||||||
import org.qortal.controller.RestartNode;
|
import org.qortal.controller.RestartNode;
|
||||||
import org.qortal.settings.Settings;
|
import org.qortal.settings.Settings;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -16,6 +19,8 @@ import java.nio.file.Path;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.qortal.controller.RestartNode.AGENTLIB_JVM_HOLDER_ARG;
|
import static org.qortal.controller.RestartNode.AGENTLIB_JVM_HOLDER_ARG;
|
||||||
@ -57,15 +62,32 @@ public class ApplyRestart {
|
|||||||
if (!shutdownNode())
|
if (!shutdownNode())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Give some time for shutdown
|
||||||
|
TimeUnit.SECONDS.sleep(30);
|
||||||
|
|
||||||
|
// Remove blockchain lock if exist
|
||||||
|
ReentrantLock blockchainLock = Controller.getInstance().getBlockchainLock();
|
||||||
|
if (blockchainLock.isLocked())
|
||||||
|
blockchainLock.unlock();
|
||||||
|
|
||||||
|
// Remove blockchain lock file if exist
|
||||||
|
TimeUnit.SECONDS.sleep(60);
|
||||||
|
deleteLock();
|
||||||
|
|
||||||
// Restart node
|
// Restart node
|
||||||
|
TimeUnit.SECONDS.sleep(30);
|
||||||
restartNode(args);
|
restartNode(args);
|
||||||
|
|
||||||
LOGGER.info("Restarting...");
|
LOGGER.info("Restarting...");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("Unable to restart", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shutdownNode() {
|
private static boolean shutdownNode() {
|
||||||
String baseUri = "http://localhost:" + Settings.getInstance().getApiPort() + "/";
|
String baseUri = "http://localhost:" + Settings.getInstance().getApiPort() + "/";
|
||||||
LOGGER.info(() -> String.format("Shutting down node using API via %s", baseUri));
|
LOGGER.debug(() -> String.format("Shutting down node using API via %s", baseUri));
|
||||||
|
|
||||||
// The /admin/stop endpoint requires an API key, which may or may not be already generated
|
// The /admin/stop endpoint requires an API key, which may or may not be already generated
|
||||||
boolean apiKeyNewlyGenerated = false;
|
boolean apiKeyNewlyGenerated = false;
|
||||||
@ -134,7 +156,22 @@ public class ApplyRestart {
|
|||||||
apiKey.delete();
|
apiKey.delete();
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.info("Error loading or deleting API key: {}", e.getMessage());
|
LOGGER.error("Error loading or deleting API key: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void deleteLock() {
|
||||||
|
// Get the repository path from settings
|
||||||
|
String repositoryPath = Settings.getInstance().getRepositoryPath();
|
||||||
|
LOGGER.debug(String.format("Repository path is: %s", repositoryPath));
|
||||||
|
|
||||||
|
try {
|
||||||
|
Path root = Paths.get(repositoryPath);
|
||||||
|
File lockFile = new File(root.resolve("blockchain.lck").toUri());
|
||||||
|
LOGGER.debug("Lockfile is: {}", lockFile);
|
||||||
|
FileUtils.forceDelete(FileUtils.getFile(lockFile));
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.error("Error deleting blockchain lock file: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,9 +187,10 @@ public class ApplyRestart {
|
|||||||
|
|
||||||
List<String> javaCmd;
|
List<String> javaCmd;
|
||||||
if (Files.exists(exeLauncher)) {
|
if (Files.exists(exeLauncher)) {
|
||||||
javaCmd = Arrays.asList(exeLauncher.toString());
|
javaCmd = List.of(exeLauncher.toString());
|
||||||
} else {
|
} else {
|
||||||
javaCmd = new ArrayList<>();
|
javaCmd = new ArrayList<>();
|
||||||
|
|
||||||
// Java runtime binary itself
|
// Java runtime binary itself
|
||||||
javaCmd.add(javaBinary.toString());
|
javaCmd.add(javaBinary.toString());
|
||||||
|
|
||||||
|
@ -500,7 +500,6 @@ public class Controller extends Thread {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Thread.currentThread().setName("Shutdown hook");
|
Thread.currentThread().setName("Shutdown hook");
|
||||||
|
|
||||||
Controller.getInstance().shutdown();
|
Controller.getInstance().shutdown();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -580,10 +579,31 @@ public class Controller extends Thread {
|
|||||||
// If GUI is enabled, we're no longer starting up but actually running now
|
// If GUI is enabled, we're no longer starting up but actually running now
|
||||||
Gui.getInstance().notifyRunning();
|
Gui.getInstance().notifyRunning();
|
||||||
|
|
||||||
// Check every 10 minutes to see if the block minter is running
|
// Check every 10 minutes if we have enough connected peers
|
||||||
Timer timer = new Timer();
|
Timer checkConnectedPeers = new Timer();
|
||||||
|
|
||||||
timer.schedule(new TimerTask() {
|
checkConnectedPeers.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Get the connected peers
|
||||||
|
int myConnectedPeers = Network.getInstance().getImmutableHandshakedPeers().size();
|
||||||
|
LOGGER.debug("Node have {} connected peers", myConnectedPeers);
|
||||||
|
if (myConnectedPeers == 0) {
|
||||||
|
// Restart node if we have 0 peers
|
||||||
|
LOGGER.info("Node have no connected peers, restarting node");
|
||||||
|
try {
|
||||||
|
RestartNode.attemptToRestart();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Unable to restart the node", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 10*60*1000, 10*60*1000);
|
||||||
|
|
||||||
|
// Check every 10 minutes to see if the block minter is running
|
||||||
|
Timer checkBlockMinter = new Timer();
|
||||||
|
|
||||||
|
checkBlockMinter.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (blockMinter.isAlive()) {
|
if (blockMinter.isAlive()) {
|
||||||
|
@ -21,7 +21,7 @@ public class BlockArchiver implements Runnable {
|
|||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(BlockArchiver.class);
|
private static final Logger LOGGER = LogManager.getLogger(BlockArchiver.class);
|
||||||
|
|
||||||
private static final long INITIAL_SLEEP_PERIOD = 5 * 60 * 1000L + 1234L; // ms
|
private static final long INITIAL_SLEEP_PERIOD = 15 * 60 * 1000L; // ms
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
Thread.currentThread().setName("Block archiver");
|
Thread.currentThread().setName("Block archiver");
|
||||||
@ -52,9 +52,29 @@ public class BlockArchiver implements Runnable {
|
|||||||
|
|
||||||
Thread.sleep(Settings.getInstance().getArchiveInterval());
|
Thread.sleep(Settings.getInstance().getArchiveInterval());
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
BlockData chainTip = Controller.getInstance().getChainTip();
|
BlockData chainTip = Controller.getInstance().getChainTip();
|
||||||
if (chainTip == null || NTP.getTime() == null) {
|
if (chainTip == null || NTP.getTime() == null) {
|
||||||
continue;
|
continue;
|
||||||
|
=======
|
||||||
|
// We've reached the limit of the blocks we can archive
|
||||||
|
// Sleep for a while to allow more to become available
|
||||||
|
case NOT_ENOUGH_BLOCKS:
|
||||||
|
// We didn't reach our file size target, so that must mean that we don't have enough blocks
|
||||||
|
// yet or something went wrong. Sleep for a while and then try again.
|
||||||
|
repository.discardChanges();
|
||||||
|
Thread.sleep(2 * 60 * 60 * 1000L); // 2 hour around 100 blocks
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLOCK_NOT_FOUND:
|
||||||
|
// We tried to archive a block that didn't exist. This is a major failure and likely means
|
||||||
|
// that a bootstrap or re-sync is needed. Try again every minute until then.
|
||||||
|
LOGGER.info("Error: block not found when building archive. If this error persists, " +
|
||||||
|
"a bootstrap or re-sync may be needed.");
|
||||||
|
repository.discardChanges();
|
||||||
|
Thread.sleep(60 * 1000L); // 1 minute
|
||||||
|
break;
|
||||||
|
>>>>>>> alphax/master
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't even attempt if we're mid-sync as our repository requests will be delayed for ages
|
// Don't even attempt if we're mid-sync as our repository requests will be delayed for ages
|
||||||
|
@ -53,7 +53,7 @@ public class Network {
|
|||||||
/**
|
/**
|
||||||
* How long between informational broadcasts to all connected peers, in milliseconds.
|
* How long between informational broadcasts to all connected peers, in milliseconds.
|
||||||
*/
|
*/
|
||||||
private static final long BROADCAST_INTERVAL = 60 * 1000L; // ms
|
private static final long BROADCAST_INTERVAL = 30 * 1000L; // ms
|
||||||
/**
|
/**
|
||||||
* Maximum time since last successful connection for peer info to be propagated, in milliseconds.
|
* Maximum time since last successful connection for peer info to be propagated, in milliseconds.
|
||||||
*/
|
*/
|
||||||
@ -83,12 +83,12 @@ public class Network {
|
|||||||
"node6.qortalnodes.live", "node7.qortalnodes.live", "node8.qortalnodes.live"
|
"node6.qortalnodes.live", "node7.qortalnodes.live", "node8.qortalnodes.live"
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final long NETWORK_EPC_KEEPALIVE = 10L; // seconds
|
private static final long NETWORK_EPC_KEEPALIVE = 5L; // seconds
|
||||||
|
|
||||||
public static final int MAX_SIGNATURES_PER_REPLY = 500;
|
public static final int MAX_SIGNATURES_PER_REPLY = 500;
|
||||||
public static final int MAX_BLOCK_SUMMARIES_PER_REPLY = 500;
|
public static final int MAX_BLOCK_SUMMARIES_PER_REPLY = 500;
|
||||||
|
|
||||||
private static final long DISCONNECTION_CHECK_INTERVAL = 10 * 1000L; // milliseconds
|
private static final long DISCONNECTION_CHECK_INTERVAL = 20 * 1000L; // milliseconds
|
||||||
|
|
||||||
private static final int BROADCAST_CHAIN_TIP_DEPTH = 7; // Just enough to fill a SINGLE TCP packet (~1440 bytes)
|
private static final int BROADCAST_CHAIN_TIP_DEPTH = 7; // Just enough to fill a SINGLE TCP packet (~1440 bytes)
|
||||||
|
|
||||||
|
@ -197,21 +197,21 @@ public class Settings {
|
|||||||
/** Target number of outbound connections to peers we should make. */
|
/** Target number of outbound connections to peers we should make. */
|
||||||
private int minOutboundPeers = 32;
|
private int minOutboundPeers = 32;
|
||||||
/** Maximum number of peer connections we allow. */
|
/** Maximum number of peer connections we allow. */
|
||||||
private int maxPeers = 60;
|
private int maxPeers = 64;
|
||||||
/** Number of slots to reserve for short-lived QDN data transfers */
|
/** Number of slots to reserve for short-lived QDN data transfers */
|
||||||
private int maxDataPeers = 5;
|
private int maxDataPeers = 5;
|
||||||
/** Maximum number of threads for network engine. */
|
/** Maximum number of threads for network engine. */
|
||||||
private int maxNetworkThreadPoolSize = 620;
|
private int maxNetworkThreadPoolSize = 512;
|
||||||
/** Maximum number of threads for network proof-of-work compute, used during handshaking. */
|
/** Maximum number of threads for network proof-of-work compute, used during handshaking. */
|
||||||
private int networkPoWComputePoolSize = 2;
|
private int networkPoWComputePoolSize = 4;
|
||||||
/** Maximum number of retry attempts if a peer fails to respond with the requested data */
|
/** Maximum number of retry attempts if a peer fails to respond with the requested data */
|
||||||
private int maxRetries = 2;
|
private int maxRetries = 3;
|
||||||
|
|
||||||
/** The number of seconds of no activity before recovery mode begins */
|
/** The number of seconds of no activity before recovery mode begins */
|
||||||
public long recoveryModeTimeout = 9999999999999L;
|
public long recoveryModeTimeout = 9999999999999L;
|
||||||
|
|
||||||
/** Minimum peer version number required in order to sync with them */
|
/** Minimum peer version number required in order to sync with them */
|
||||||
private String minPeerVersion = "4.5.2";
|
private String minPeerVersion = "4.6.0";
|
||||||
/** Whether to allow connections with peers below minPeerVersion
|
/** Whether to allow connections with peers below minPeerVersion
|
||||||
* If true, we won't sync with them but they can still sync with us, and will show in the peers list
|
* If true, we won't sync with them but they can still sync with us, and will show in the peers list
|
||||||
* If false, sync will be blocked both ways, and they will not appear in the peers list */
|
* If false, sync will be blocked both ways, and they will not appear in the peers list */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user