WalletAppKit/Template: Cleaner way to check if the app is already running. Backport from Lighthouse.

This commit is contained in:
Mike Hearn 2014-07-10 21:44:38 +02:00
parent 13b2f2104c
commit 8e6e2256bc
2 changed files with 37 additions and 22 deletions

View File

@ -30,12 +30,10 @@ import com.google.common.util.concurrent.Service;
import com.subgraph.orchid.TorClient;
import org.bitcoinj.wallet.Protos;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.channels.FileLock;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -188,6 +186,29 @@ public class WalletAppKit extends AbstractIdleService {
*/
protected void onSetupCompleted() { }
/**
* Tests to see if the spvchain file has an operating system file lock on it. Useful for checking if your app
* is already running. If another copy of your app is running and you start the appkit anyway, an exception will
* be thrown during the startup process. Returns false if the chain file does not exist.
*/
public boolean isChainFileLocked() throws IOException {
RandomAccessFile file2 = null;
try {
File file = new File(directory, filePrefix + ".spvchain");
if (!file.exists())
return false;
file2 = new RandomAccessFile(file, "rw");
FileLock lock = file2.getChannel().tryLock();
if (lock == null)
return true;
lock.close();
return false;
} finally {
if (file2 != null)
file2.close();
}
}
@Override
protected void startUp() throws Exception {
// Runs in a separate thread.

View File

@ -5,10 +5,8 @@ import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.kits.WalletAppKit;
import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.params.RegTestParams;
import com.google.bitcoin.store.BlockStoreException;
import com.google.bitcoin.utils.BriefLogFormatter;
import com.google.bitcoin.utils.Threading;
import com.google.common.base.Throwables;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
@ -41,22 +39,12 @@ public class Main extends Application {
instance = this;
// Show the crash dialog for any exceptions that we don't handle and that hit the main loop.
GuiUtils.handleCrashesOnThisThread();
try {
init(mainWindow);
} catch (Throwable t) {
// Nicer message for the case where the block store file is locked.
if (Throwables.getRootCause(t) instanceof BlockStoreException) {
GuiUtils.informationalAlert("Already running", "This application is already running and cannot be started twice.");
} else {
throw t;
}
}
}
private void init(Stage mainWindow) throws IOException {
// Match Aqua UI style.
if (System.getProperty("os.name").toLowerCase().contains("mac")) {
AquaFx.style();
}
// Load the GUI. The Controller class will be automagically created and wired up.
URL location = getClass().getResource("main.fxml");
FXMLLoader loader = new FXMLLoader(location);
@ -78,6 +66,16 @@ public class Main extends Application {
Threading.USER_THREAD = Platform::runLater;
// Create the app kit. It won't do any heavyweight initialization until after we start it.
bitcoin = new WalletAppKit(params, new File("."), APP_NAME);
if (bitcoin.isChainFileLocked()) {
informationalAlert("Already running", "This application is already running and cannot be started twice.");
Platform.exit();
return;
}
mainWindow.show();
// Now configure and start the appkit. This will take a second or two - we could show a temporary splash screen
// or progress widget to keep the user engaged whilst we initialise, but we don't.
if (params == RegTestParams.get()) {
bitcoin.connectToLocalHost(); // You should run a regtest mode bitcoind locally.
} else if (params == MainNetParams.get()) {
@ -89,9 +87,6 @@ public class Main extends Application {
// As an example!
// bitcoin.useTor();
}
// Now configure and start the appkit. This will take a second or two - we could show a temporary splash screen
// or progress widget to keep the user engaged whilst we initialise, but we don't.
bitcoin.setDownloadListener(controller.progressBarUpdater())
.setBlockingStartup(false)
.setUserAgent(APP_NAME, "1.0");
@ -102,7 +97,6 @@ public class Main extends Application {
bitcoin.peerGroup().setMaxConnections(11);
System.out.println(bitcoin.wallet());
controller.onBitcoinSetup();
mainWindow.show();
}
public class OverlayUI<T> {