forked from Qortal/qortal
Propagate JVM arguments through auto-update. Improve start-up error messages shown by GUI
This commit is contained in:
parent
339e757d34
commit
62ed4e322b
@ -1,11 +1,13 @@
|
||||
package org.qora;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.Security;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@ -42,7 +44,10 @@ public class ApplyUpdate {
|
||||
Security.insertProviderAt(new BouncyCastleJsseProvider(), 1);
|
||||
|
||||
// Load/check settings, which potentially sets up blockchain config, etc.
|
||||
Settings.getInstance();
|
||||
if (args.length > 0)
|
||||
Settings.fileInstance(args[0]);
|
||||
else
|
||||
Settings.getInstance();
|
||||
|
||||
LOGGER.info("Applying update...");
|
||||
|
||||
@ -54,7 +59,7 @@ public class ApplyUpdate {
|
||||
replaceJar();
|
||||
|
||||
// Restart node
|
||||
restartNode();
|
||||
restartNode(args);
|
||||
|
||||
LOGGER.info("Exiting...");
|
||||
}
|
||||
@ -122,7 +127,7 @@ public class ApplyUpdate {
|
||||
LOGGER.error("Failed to replace JAR - giving up");
|
||||
}
|
||||
|
||||
private static void restartNode() {
|
||||
private static void restartNode(String[] args) {
|
||||
String javaHome = System.getProperty("java.home");
|
||||
LOGGER.info(String.format("Java home: %s", javaHome));
|
||||
|
||||
@ -133,10 +138,23 @@ public class ApplyUpdate {
|
||||
LOGGER.info(String.format("Windows EXE launcher: %s", exeLauncher));
|
||||
|
||||
List<String> javaCmd;
|
||||
if (Files.exists(exeLauncher))
|
||||
if (Files.exists(exeLauncher)) {
|
||||
javaCmd = Arrays.asList(exeLauncher.toString());
|
||||
else
|
||||
javaCmd = Arrays.asList(javaBinary.toString(), "-jar", JAR_FILENAME);
|
||||
} else {
|
||||
javaCmd = new ArrayList<>();
|
||||
// Java runtime binary itself
|
||||
javaCmd.add(javaBinary.toString());
|
||||
|
||||
// JVM arguments
|
||||
javaCmd.addAll(ManagementFactory.getRuntimeMXBean().getInputArguments());
|
||||
|
||||
// Call mainClass in JAR
|
||||
javaCmd.addAll(Arrays.asList("-jar", JAR_FILENAME));
|
||||
|
||||
if (args.length > 0)
|
||||
// Add settings filename
|
||||
javaCmd.add(args[0]);
|
||||
}
|
||||
|
||||
try {
|
||||
LOGGER.info(String.format("Restarting node with: %s", String.join(" ", javaCmd)));
|
||||
|
@ -4,12 +4,14 @@ import java.awt.TrayIcon.MessageType;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@ -224,7 +226,21 @@ public class AutoUpdate extends Thread {
|
||||
LOGGER.debug(String.format("Java binary: %s", javaBinary));
|
||||
|
||||
try {
|
||||
List<String> javaCmd = Arrays.asList(javaBinary.toString(), "-cp", NEW_JAR_FILENAME, ApplyUpdate.class.getCanonicalName());
|
||||
List<String> javaCmd = new ArrayList<>();
|
||||
// Java runtime binary itself
|
||||
javaCmd.add(javaBinary.toString());
|
||||
|
||||
// JVM arguments
|
||||
javaCmd.addAll(ManagementFactory.getRuntimeMXBean().getInputArguments());
|
||||
|
||||
// Call ApplyUpdate using new JAR
|
||||
javaCmd.addAll(Arrays.asList("-cp", NEW_JAR_FILENAME, ApplyUpdate.class.getCanonicalName()));
|
||||
|
||||
// Are we running with different settings?
|
||||
String settingsFilename = Controller.getInstance().getSettingsFilename();
|
||||
if (settingsFilename != null)
|
||||
javaCmd.add(settingsFilename);
|
||||
|
||||
LOGGER.info(String.format("Applying update with: %s", String.join(" ", javaCmd)));
|
||||
|
||||
SysTray.getInstance().showMessage("Auto Update", "Applying automatic update and restarting...", MessageType.INFO);
|
||||
|
@ -121,6 +121,7 @@ public class Controller extends Thread {
|
||||
|
||||
private final String buildVersion;
|
||||
private final long buildTimestamp; // seconds
|
||||
private String settingsFilename;
|
||||
|
||||
private AtomicReference<BlockData> chainTip = new AtomicReference<>();
|
||||
|
||||
@ -229,6 +230,10 @@ public class Controller extends Thread {
|
||||
return this.blockchainLock;
|
||||
}
|
||||
|
||||
/* package */ String getSettingsFilename() {
|
||||
return this.settingsFilename;
|
||||
}
|
||||
|
||||
// Entry point
|
||||
|
||||
public static void main(String[] args) {
|
||||
@ -259,8 +264,16 @@ public class Controller extends Thread {
|
||||
RepositoryFactory repositoryFactory = new HSQLDBRepositoryFactory(getRepositoryUrl());
|
||||
RepositoryManager.setRepositoryFactory(repositoryFactory);
|
||||
} catch (DataException e) {
|
||||
LOGGER.error("Unable to start repository", e);
|
||||
System.exit(1);
|
||||
// If exception has no cause then repository is in use by some other process.
|
||||
if (e.getCause() == null) {
|
||||
LOGGER.info("Repository in use by another process?");
|
||||
Gui.getInstance().fatalError("Repository issue", "Repository in use by another process?");
|
||||
} else {
|
||||
LOGGER.error("Unable to start repository", e);
|
||||
Gui.getInstance().fatalError("Repository issue", e);
|
||||
}
|
||||
|
||||
return; // Not System.exit() so that GUI can display error
|
||||
}
|
||||
|
||||
LOGGER.info("Validating blockchain");
|
||||
@ -276,7 +289,8 @@ public class Controller extends Thread {
|
||||
}
|
||||
} catch (DataException e) {
|
||||
LOGGER.error("Couldn't validate blockchain", e);
|
||||
System.exit(2);
|
||||
Gui.getInstance().fatalError("Blockchain validation issue", e);
|
||||
return; // Not System.exit() so that GUI can display error
|
||||
}
|
||||
|
||||
LOGGER.info("Starting controller");
|
||||
@ -288,7 +302,8 @@ public class Controller extends Thread {
|
||||
network.start();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Unable to start networking", e);
|
||||
System.exit(1);
|
||||
Gui.getInstance().fatalError("Networking failure", e);
|
||||
return; // Not System.exit() so that GUI can display error
|
||||
}
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@ -318,7 +333,8 @@ public class Controller extends Thread {
|
||||
apiService.start();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Unable to start API", e);
|
||||
System.exit(1);
|
||||
Gui.getInstance().fatalError("API failure", e);
|
||||
return; // Not System.exit() so that GUI can display error
|
||||
}
|
||||
|
||||
LOGGER.info(String.format("Starting node management UI on port %d", Settings.getInstance().getUiPort()));
|
||||
@ -327,7 +343,8 @@ public class Controller extends Thread {
|
||||
uiService.start();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Unable to start node management UI", e);
|
||||
System.exit(1);
|
||||
Gui.getInstance().fatalError("Node management UI failure", e);
|
||||
return; // Not System.exit() so that GUI can display error
|
||||
}
|
||||
|
||||
// If GUI is enabled, we're no longer starting up but actually running now
|
||||
|
@ -90,4 +90,12 @@ public class Gui {
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
public void fatalError(String title, Exception e) {
|
||||
String message = e.getLocalizedMessage();
|
||||
if (e.getCause() != null && e.getCause().getLocalizedMessage() != null)
|
||||
message += ": " + e.getCause().getLocalizedMessage();
|
||||
|
||||
this.fatalError(title, message);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -136,10 +136,10 @@ public class Network {
|
||||
serverChannel.register(channelSelector, SelectionKey.OP_ACCEPT);
|
||||
} catch (UnknownHostException e) {
|
||||
LOGGER.error(String.format("Can't bind listen socket to address %s", Settings.getInstance().getBindAddress()));
|
||||
throw new RuntimeException("Can't bind listen socket to address");
|
||||
throw new RuntimeException("Can't bind listen socket to address", e);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error(String.format("Can't create listen socket: %s", e.getMessage()));
|
||||
throw new RuntimeException("Can't create listen socket");
|
||||
throw new RuntimeException("Can't create listen socket", e);
|
||||
}
|
||||
|
||||
connectedPeers = new ArrayList<>();
|
||||
|
@ -26,6 +26,13 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory {
|
||||
private String connectionUrl;
|
||||
private HSQLDBPool connectionPool;
|
||||
|
||||
/**
|
||||
* Constructs new RepositoryFactory using passed <tt>connectionUrl</tt>.
|
||||
*
|
||||
* @param connectionUrl
|
||||
* @throws DataException <i>without throwable</i> if repository in use by another process.
|
||||
* @throws DataException <i>with throwable</i> if repository cannot be opened for someother reason.
|
||||
*/
|
||||
public HSQLDBRepositoryFactory(String connectionUrl) throws DataException {
|
||||
// one-time initialization goes in here
|
||||
this.connectionUrl = connectionUrl;
|
||||
@ -36,12 +43,15 @@ public class HSQLDBRepositoryFactory implements RepositoryFactory {
|
||||
} catch (SQLException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (!(cause instanceof HsqlException))
|
||||
throw new DataException("Unable to open repository: " + e.getMessage());
|
||||
throw new DataException("Unable to open repository: " + e.getMessage(), e);
|
||||
|
||||
HsqlException he = (HsqlException) cause;
|
||||
if (he.getErrorCode() != -ErrorCode.ERROR_IN_LOG_FILE && he.getErrorCode() != -ErrorCode.M_DatabaseScriptReader_read)
|
||||
if (he.getErrorCode() == -ErrorCode.LOCK_FILE_ACQUISITION_FAILURE)
|
||||
throw new DataException("Unable to open repository: " + e.getMessage());
|
||||
|
||||
if (he.getErrorCode() != -ErrorCode.ERROR_IN_LOG_FILE && he.getErrorCode() != -ErrorCode.M_DatabaseScriptReader_read)
|
||||
throw new DataException("Unable to open repository: " + e.getMessage(), e);
|
||||
|
||||
// Attempt recovery?
|
||||
HSQLDBRepository.attemptRecovery(connectionUrl);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user