Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve startup routines #4583

Merged
merged 25 commits into from
Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b73fff0
Refactor: Move AsciiLogo to common
chimp1984 Oct 1, 2020
fe7ccbd
Refactor: extract method
chimp1984 Oct 1, 2020
b6e97e3
Refactor: add new setup method to CommonSetup with config (WIP) and c…
chimp1984 Oct 1, 2020
7ea3676
Refactor: Rename setup to setupUncaughtExceptionHandler
chimp1984 Oct 1, 2020
9232a57
Improve handling of UncaughtExceptionHandler
chimp1984 Oct 1, 2020
9d12bf7
Refactor: Move sig int handlers to CommonSetup
chimp1984 Oct 1, 2020
b927f97
Refactor: Move DevEnv setup to CommonSetup
chimp1984 Oct 1, 2020
516da22
Refactor: Add setup method in DevEnv
chimp1984 Oct 1, 2020
aa7315b
Refactor: Rename onUiReadyHandler to onApplicationStartedHandler
chimp1984 Oct 1, 2020
4f9a6ea
Refactor: Move periodic printSystemLoad to commonSetup
chimp1984 Oct 1, 2020
bb99eef
Refactor: Move AvoidStandbyModeService from BisqApp to BisqExecutable…
chimp1984 Oct 1, 2020
907fd66
Remove empty loop
chimp1984 Oct 1, 2020
fe577b3
Remove checkCryptoSetup as not needed anymore
chimp1984 Oct 1, 2020
4986650
Remove checkCryptoPolicySetup as not needed anymore
chimp1984 Oct 1, 2020
073f163
Remove Remove LimitedKeyStrengthException as not needed anymore
chimp1984 Oct 1, 2020
51ce37d
Refactor: Rearrange methods
chimp1984 Oct 1, 2020
a38f59a
Refactor: Move common bases setup code to CommonSetup
chimp1984 Oct 1, 2020
c3e1ae6
Remove cryptoSetupFailedHandler
chimp1984 Oct 1, 2020
346ad51
Refactor: Move osUserDataDir method to Utilities, rename to getUserDa…
chimp1984 Oct 1, 2020
11383b9
Refactor: Rename startAppSetup to runBisqSetup
chimp1984 Oct 1, 2020
6e7e975
Improve printSystemLoad
chimp1984 Oct 1, 2020
1b18886
Refactor: Move handler code to domain classes
chimp1984 Oct 1, 2020
a8a881e
Fix wrong printSystemLoad calls
chimp1984 Oct 1, 2020
ff13804
Merge branch 'master_upstream' into improve-startup-routines
chimp1984 Oct 1, 2020
d841222
Fix merge conflicts
chimp1984 Oct 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.core.app;
package bisq.common.app;

import lombok.extern.slf4j.Slf4j;

Expand Down
7 changes: 7 additions & 0 deletions common/src/main/java/bisq/common/app/DevEnv.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package bisq.common.app;

import bisq.common.config.Config;

import lombok.extern.slf4j.Slf4j;

@Slf4j
Expand All @@ -30,6 +32,11 @@ public class DevEnv {
public static final String DEV_PRIVILEGE_PUB_KEY = "027a381b5333a56e1cc3d90d3a7d07f26509adf7029ed06fc997c656621f8da1ee";
public static final String DEV_PRIVILEGE_PRIV_KEY = "6ac43ea1df2a290c1c8391736aa42e4339c5cb4f110ff0257a13b63211977b7a";

public static void setup(Config config) {
DevEnv.setDevMode(config.useDevMode);
DevEnv.setDaoActivated(config.daoActivated);
}

// If set to true we ignore several UI behavior like confirmation popups as well dummy accounts are created and
// offers are filled with default values. Intended to make dev testing faster.
private static boolean devMode = false;
Expand Down
10 changes: 0 additions & 10 deletions common/src/main/java/bisq/common/crypto/CryptoUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@

package bisq.common.crypto;

import javax.crypto.Cipher;

import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.X509EncodedKeySpec;
Expand All @@ -40,11 +37,4 @@ public static byte[] getRandomBytes(int size) {
new SecureRandom().nextBytes(bytes);
return bytes;
}

public static void checkCryptoPolicySetup() throws NoSuchAlgorithmException, LimitedKeyStrengthException {
if (Cipher.getMaxAllowedKeyLength("AES") > 128)
log.debug("Congratulations, you have unlimited key length support!");
else
throw new LimitedKeyStrengthException();
}
}

This file was deleted.

73 changes: 62 additions & 11 deletions common/src/main/java/bisq/common/setup/CommonSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,51 @@
package bisq.common.setup;

import bisq.common.UserThread;
import bisq.common.crypto.CryptoUtils;
import bisq.common.crypto.LimitedKeyStrengthException;
import bisq.common.app.AsciiLogo;
import bisq.common.app.DevEnv;
import bisq.common.app.Log;
import bisq.common.app.Version;
import bisq.common.config.Config;
import bisq.common.util.Profiler;
import bisq.common.util.Utilities;

import org.bitcoinj.store.BlockStoreException;

import org.apache.commons.lang3.exception.ExceptionUtils;

import java.security.NoSuchAlgorithmException;
import java.net.URISyntaxException;

import java.nio.file.Paths;

import java.util.concurrent.TimeUnit;

import ch.qos.logback.classic.Level;

import lombok.extern.slf4j.Slf4j;



import sun.misc.Signal;

@Slf4j
public class CommonSetup {

public static void setup(UncaughtExceptionHandler uncaughtExceptionHandler) {
setupErrorHandler(uncaughtExceptionHandler);
public static void setup(Config config, GracefulShutDownHandler gracefulShutDownHandler) {
AsciiLogo.showAsciiLogo();
setupLog(config);
Version.setBaseCryptoNetworkId(config.baseCurrencyNetwork.ordinal());
Version.printVersion();
maybePrintPathOfCodeSource();
Profiler.printSystemLoad();
UserThread.runPeriodically(Profiler::printSystemLoad, 10, TimeUnit.MINUTES);

if (Utilities.isLinux())
System.setProperty("prism.lcdtext", "false");
setSystemProperties();
setupSigIntHandlers(gracefulShutDownHandler);

DevEnv.setup(config);
}

private static void setupErrorHandler(UncaughtExceptionHandler uncaughtExceptionHandler) {
public static void setupUncaughtExceptionHandler(UncaughtExceptionHandler uncaughtExceptionHandler) {
Thread.UncaughtExceptionHandler handler = (thread, throwable) -> {
// Might come from another thread
if (throwable.getCause() != null && throwable.getCause().getCause() != null &&
Expand All @@ -60,12 +82,41 @@ private static void setupErrorHandler(UncaughtExceptionHandler uncaughtException
};
Thread.setDefaultUncaughtExceptionHandler(handler);
Thread.currentThread().setUncaughtExceptionHandler(handler);
}

private static void setupLog(Config config) {
String logPath = Paths.get(config.appDataDir.getPath(), "bisq").toString();
Log.setup(logPath);
log.info("Log files under: {}", logPath);
Utilities.printSysInfo();
Log.setLevel(Level.toLevel(config.logLevel));
}

protected static void setSystemProperties() {
if (Utilities.isLinux())
System.setProperty("prism.lcdtext", "false");
}

protected static void setupSigIntHandlers(GracefulShutDownHandler gracefulShutDownHandler) {
Signal.handle(new Signal("INT"), signal -> {
gracefulShutDownHandler.gracefulShutDown(() -> {
});
});

Signal.handle(new Signal("TERM"), signal -> {
gracefulShutDownHandler.gracefulShutDown(() -> {
});
});
}

protected static void maybePrintPathOfCodeSource() {
try {
CryptoUtils.checkCryptoPolicySetup();
} catch (NoSuchAlgorithmException | LimitedKeyStrengthException e) {
final String pathOfCodeSource = Utilities.getPathOfCodeSource();
if (!pathOfCodeSource.endsWith("classes"))
log.info("Path to Bisq jar file: " + pathOfCodeSource);
} catch (URISyntaxException e) {
log.error(e.toString());
e.printStackTrace();
UserThread.execute(() -> uncaughtExceptionHandler.handleUncaughtException(e, true));
}
}
}
15 changes: 9 additions & 6 deletions common/src/main/java/bisq/common/util/Profiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@

package bisq.common.util;

import org.slf4j.Logger;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Profiler {
public static void printSystemLoad(Logger log) {
log.info(printSystemLoadString());
}
public static void printSystemLoad() {
Runtime runtime = Runtime.getRuntime();
long free = runtime.freeMemory() / 1024 / 1024;
long total = runtime.totalMemory() / 1024 / 1024;
long used = total - free;

public static String printSystemLoadString() {
return "System load: Memory (MB): " + getUsedMemoryInMB() + " / No. of threads: " + Thread.activeCount();
log.info("System report: Used memory: {} MB; Free memory: {} MB; Total memory: {} MB; No. of threads: {}",
used, free, total, Thread.activeCount());
}

public static long getUsedMemoryInMB() {
Expand Down
16 changes: 16 additions & 0 deletions common/src/main/java/bisq/common/util/Utilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import java.net.URI;
import java.net.URISyntaxException;

import java.nio.file.Paths;

import java.io.File;
import java.io.IOException;

Expand Down Expand Up @@ -198,6 +200,20 @@ public static String getOSVersion() {
return System.getProperty("os.version").toLowerCase(Locale.US);
}

/**
* Returns the well-known "user data directory" for the current operating system.
*/
public static File getUserDataDir() {
if (Utilities.isWindows())
return new File(System.getenv("APPDATA"));

if (Utilities.isOSX())
return Paths.get(System.getProperty("user.home"), "Library", "Application Support").toFile();

// *nix
return Paths.get(System.getProperty("user.home"), ".local", "share").toFile();
}

public static int getMinorVersion() throws InvalidVersionException {
String version = getOSVersion();
String[] tokens = version.split("\\.");
Expand Down
67 changes: 26 additions & 41 deletions core/src/main/java/bisq/core/app/BisqExecutable.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,18 @@
import bisq.common.config.ConfigException;
import bisq.common.handlers.ResultHandler;
import bisq.common.proto.persistable.PersistedDataHost;
import bisq.common.setup.CommonSetup;
import bisq.common.setup.GracefulShutDownHandler;
import bisq.common.setup.UncaughtExceptionHandler;
import bisq.common.util.Utilities;

import com.google.inject.Guice;
import com.google.inject.Injector;

import java.nio.file.Paths;

import java.io.File;

import lombok.extern.slf4j.Slf4j;



import sun.misc.Signal;

@Slf4j
public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSetup.BisqSetupListener {
public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSetup.BisqSetupListener, UncaughtExceptionHandler {

private static final int EXIT_SUCCESS = 0;
private static final int EXIT_FAILURE = 1;
Expand All @@ -78,7 +72,7 @@ public BisqExecutable(String fullName, String scriptName, String appName, String

public void execute(String[] args) {
try {
config = new Config(appName, osUserDataDir(), args);
config = new Config(appName, Utilities.getUserDataDir(), args);
if (config.helpRequested) {
config.printHelp(System.out, new BisqHelpFormatter(fullName, scriptName, version));
System.exit(EXIT_SUCCESS);
Expand All @@ -101,20 +95,11 @@ public void execute(String[] args) {
///////////////////////////////////////////////////////////////////////////////////////////

protected void doExecute() {
AsciiLogo.showAsciiLogo();
configUserThread();
CommonSetup.setup(config, this);
CoreSetup.setup(config);
addCapabilities();

Signal.handle(new Signal("INT"), signal -> {
gracefulShutDown(() -> {
});
});

Signal.handle(new Signal("TERM"), signal -> {
gracefulShutDown(() -> {
});
});
configUserThread();
addCapabilities();

// If application is JavaFX application we need to wait until it is initialized
launchApplication();
Expand All @@ -136,7 +121,12 @@ protected void addCapabilities() {

// Headless versions can call inside launchApplication the onApplicationLaunched() manually
protected void onApplicationLaunched() {
// As the handler method might be overwritten by subclasses and they use the application as handler
// we need to setup the handler after the application is created.
CommonSetup.setupUncaughtExceptionHandler(this);

setupGuice();
setupAvoidStandbyMode();
startApplication();
}

Expand All @@ -158,16 +148,9 @@ protected Injector getInjector() {
}

protected void applyInjector() {
setupDevEnv();

setupPersistedDataHosts(injector);
}

protected void setupDevEnv() {
DevEnv.setDevMode(config.useDevMode);
DevEnv.setDaoActivated(config.daoActivated);
}

protected void setupPersistedDataHosts(Injector injector) {
try {
PersistedDataHost.apply(CorePersistedDataHost.getPersistedDataHosts(injector));
Expand All @@ -182,14 +165,17 @@ protected void setupPersistedDataHosts(Injector injector) {
}
}

protected void setupAvoidStandbyMode() {
}

protected abstract void startApplication();

// Once the application is ready we get that callback and we start the setup
protected void onApplicationStarted() {
startAppSetup();
runBisqSetup();
}

protected void startAppSetup() {
protected void runBisqSetup() {
BisqSetup bisqSetup = injector.getInstance(BisqSetup.class);
bisqSetup.addBisqSetupListener(this);
bisqSetup.start();
Expand Down Expand Up @@ -260,17 +246,16 @@ public void gracefulShutDown(ResultHandler resultHandler) {
}
}

/**
* Returns the well-known "user data directory" for the current operating system.
*/
private static File osUserDataDir() {
if (Utilities.isWindows())
return new File(System.getenv("APPDATA"));

if (Utilities.isOSX())
return Paths.get(System.getProperty("user.home"), "Library", "Application Support").toFile();
///////////////////////////////////////////////////////////////////////////////////////////
// UncaughtExceptionHandler implementation
///////////////////////////////////////////////////////////////////////////////////////////

@Override
public void handleUncaughtException(Throwable throwable, boolean doShutDown) {
log.error(throwable.toString());

// *nix
return Paths.get(System.getProperty("user.home"), ".local", "share").toFile();
if (doShutDown)
gracefulShutDown(() -> log.info("gracefulShutDown complete"));
}
}
4 changes: 0 additions & 4 deletions core/src/main/java/bisq/core/app/BisqHeadlessApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import bisq.common.UserThread;
import bisq.common.setup.GracefulShutDownHandler;
import bisq.common.storage.CorruptedDatabaseFilesHandler;
import bisq.common.util.Profiler;

import com.google.inject.Injector;

Expand Down Expand Up @@ -60,8 +59,6 @@ public void startApplication() {
tradeManager = injector.getInstance(TradeManager.class);

setupHandlers();

UserThread.runPeriodically(() -> Profiler.printSystemLoad(log), LOG_MEMORY_PERIOD_MIN, TimeUnit.MINUTES);
} catch (Throwable throwable) {
log.error("Error during app init", throwable);
handleUncaughtException(throwable, false);
Expand All @@ -78,7 +75,6 @@ protected void setupHandlers() {
log.info("onDisplayTacHandler: We accept the tacs automatically in headless mode");
acceptedHandler.run();
});
bisqSetup.setCryptoSetupFailedHandler(msg -> log.error("onCryptoSetupFailedHandler: msg={}", msg));
bisqSetup.setDisplayTorNetworkSettingsHandler(show -> log.info("onDisplayTorNetworkSettingsHandler: show={}", show));
bisqSetup.setSpvFileCorruptedHandler(msg -> log.error("onSpvFileCorruptedHandler: msg={}", msg));
bisqSetup.setChainFileLockedExceptionHandler(msg -> log.error("onChainFileLockedExceptionHandler: msg={}", msg));
Expand Down
Loading