Browse Source

Add periodic system-tray pop-up if Windows Time service not running

pull/67/head
catbref 5 years ago
parent
commit
82910b6524
  1. 53
      src/main/java/org/qora/controller/Controller.java
  2. 3
      src/main/resources/i18n/SysTray_en.properties
  3. 3
      src/main/resources/i18n/SysTray_zh.properties
  4. 49
      src/test/java/org/qora/test/WindowsTimeServiceTests.java

53
src/main/java/org/qora/controller/Controller.java

@ -1,5 +1,6 @@
package org.qora.controller; package org.qora.controller;
import java.awt.TrayIcon.MessageType;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.SecureRandom; import java.security.SecureRandom;
@ -15,6 +16,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Random; import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -33,6 +35,7 @@ import org.qora.data.block.BlockSummaryData;
import org.qora.data.network.PeerData; import org.qora.data.network.PeerData;
import org.qora.data.transaction.ArbitraryTransactionData; import org.qora.data.transaction.ArbitraryTransactionData;
import org.qora.data.transaction.ArbitraryTransactionData.DataType; import org.qora.data.transaction.ArbitraryTransactionData.DataType;
import org.qora.globalization.Translator;
import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransactionData;
import org.qora.gui.Gui; import org.qora.gui.Gui;
import org.qora.gui.SysTray; import org.qora.gui.SysTray;
@ -87,6 +90,7 @@ public class Controller extends Thread {
private static final String repositoryUrlTemplate = "jdbc:hsqldb:file:%s/blockchain;create=true;hsqldb.full_log_replay=true"; private static final String repositoryUrlTemplate = "jdbc:hsqldb:file:%s/blockchain;create=true;hsqldb.full_log_replay=true";
private static final long ARBITRARY_REQUEST_TIMEOUT = 5 * 1000; // ms private static final long ARBITRARY_REQUEST_TIMEOUT = 5 * 1000; // ms
private static final long REPOSITORY_BACKUP_PERIOD = 123 * 60 * 1000; // ms private static final long REPOSITORY_BACKUP_PERIOD = 123 * 60 * 1000; // ms
private static final long NTP_NAG_PERIOD = 5 * 60 * 1000; // ms
private static volatile boolean isStopping = false; private static volatile boolean isStopping = false;
private static BlockGenerator blockGenerator = null; private static BlockGenerator blockGenerator = null;
@ -97,6 +101,7 @@ public class Controller extends Thread {
private final long buildTimestamp; // seconds private final long buildTimestamp; // seconds
private long repositoryBackupTimestamp = startTime + REPOSITORY_BACKUP_PERIOD; private long repositoryBackupTimestamp = startTime + REPOSITORY_BACKUP_PERIOD;
private long ntpNagTimestamp = startTime + NTP_NAG_PERIOD;
/** /**
* Map of recent requests for ARBITRARY transaction data payloads. * Map of recent requests for ARBITRARY transaction data payloads.
@ -307,6 +312,12 @@ public class Controller extends Thread {
repositoryBackupTimestamp += REPOSITORY_BACKUP_PERIOD; repositoryBackupTimestamp += REPOSITORY_BACKUP_PERIOD;
RepositoryManager.backup(true); RepositoryManager.backup(true);
} }
// Potentially nag end-user about NTP
if (System.currentTimeMillis() >= ntpNagTimestamp) {
ntpNagTimestamp += NTP_NAG_PERIOD;
ntpNag();
}
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
// Fall-through to exit // Fall-through to exit
@ -383,6 +394,48 @@ public class Controller extends Thread {
} }
} }
/** Nag Windows users that don't have many/any peers and not using Windows' auto time sync. */
private void ntpNag() {
// Only for Windows users
if (!System.getProperty("os.name").toLowerCase().contains("win"))
return;
// Suffering from lack of peers?
final int numberOfPeers = Network.getInstance().getUniqueHandshakedPeers().size();
if (numberOfPeers > 0)
return;
// Do we actually know any peers to connect to?
try (final Repository repository = RepositoryManager.getRepository()) {
final int numberOfKnownPeers = repository.getNetworkRepository().getAllPeers().size();
if (numberOfKnownPeers == 0)
return;
} catch (DataException e) {
// Not important
return;
}
String[] detectCmd = new String[] { "net", "start" };
try {
Process process = new ProcessBuilder(Arrays.asList(detectCmd)).start();
try (InputStream in = process.getInputStream(); Scanner scanner = new Scanner(in, "UTF8")) {
scanner.useDelimiter("\\A");
String output = scanner.hasNext() ? scanner.next() : "";
boolean isRunning = output.contains("Windows Time");
if (isRunning)
return;
}
} catch (IOException e) {
// Not important
return;
}
// Time to nag
String caption = Translator.INSTANCE.translate("SysTray", "NTP_NAG_CAPTION");
String text = Translator.INSTANCE.translate("SysTray", "NTP_NAG_TEXT");
SysTray.getInstance().showMessage(caption, text, MessageType.INFO);
}
public void updateSysTray() { public void updateSysTray() {
final int numberOfPeers = Network.getInstance().getUniqueHandshakedPeers().size(); final int numberOfPeers = Network.getInstance().getUniqueHandshakedPeers().size();

3
src/main/resources/i18n/SysTray_en.properties

@ -0,0 +1,3 @@
# Nagging about lack of NTP time sync
NTP_NAG_CAPTION=No connections?
NTP_NAG_TEXT=Please enable Windows automatic time synchronization

3
src/main/resources/i18n/SysTray_zh.properties

@ -0,0 +1,3 @@
# Nagging about lack of NTP time sync
NTP_NAG_CAPTION=No connections?
NTP_NAG_TEXT=Please enable Windows automatic time synchronization

49
src/test/java/org/qora/test/WindowsTimeServiceTests.java

@ -0,0 +1,49 @@
package org.qora.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Scanner;
public class WindowsTimeServiceTests {
public static void main(String[] args) {
System.out.println("Detecting Windows Time Service...");
String[] detectCmd = new String[] { "net", "start" };
try {
Process process = new ProcessBuilder(Arrays.asList(detectCmd)).start();
try (InputStream in = process.getInputStream(); Scanner scanner = new Scanner(in, "UTF8")) {
scanner.useDelimiter("\\A");
String output = scanner.hasNext() ? scanner.next() : "";
boolean isRunning = output.contains("Windows Time");
System.out.println(String.format("Windows Time Service running: %s", isRunning ? "yes" : "no"));
}
int exitStatus = process.waitFor();
System.out.println(String.format("Exit status: %d", exitStatus));
} catch (IOException | InterruptedException e) {
System.err.println(String.format("Failed to detect Windows Time Service: %s", e.getMessage()));
}
System.out.println("Starting Windows Time Service...");
String[] startCmd = new String[] { "net", "start", "w32time" };
try {
Process process = new ProcessBuilder(Arrays.asList(startCmd)).start();
int exitStatus = process.waitFor();
System.out.println(String.format("Exit status: %d", exitStatus));
} catch (IOException | InterruptedException e) {
System.err.println(String.format("Failed to start Windows Time Service: %s", e.getMessage()));
}
System.out.println("Force syncing Windows Time Service...");
String[] resyncCmd = new String[] { "w32tm", "/resync" };
try {
Process process = new ProcessBuilder(Arrays.asList(resyncCmd)).start();
int exitStatus = process.waitFor();
System.out.println(String.format("Exit status: %d", exitStatus));
} catch (IOException | InterruptedException e) {
System.err.println(String.format("Failed to force sync Windows Time Service: %s", e.getMessage()));
}
}
}
Loading…
Cancel
Save