diff --git a/data/lightspeed.sql b/data/lightspeed.sql
index cc27af8..439f8ab 100644
--- a/data/lightspeed.sql
+++ b/data/lightspeed.sql
@@ -1,7 +1,7 @@
CREATE TABLE IF NOT EXISTS builds (
id INTEGER PRIMARY KEY,
time INTEGER,
- server_id TEXT REFERENCES servers(id),
+ server_id TEXT,
build_string TEXT,
test_string TEXT,
compile_time REAL,
@@ -13,7 +13,7 @@ CREATE TABLE IF NOT EXISTS builds (
CREATE TABLE IF NOT EXISTS deployments (
id INTEGER PRIMARY KEY,
- server_id TEXT REFERENCES servers(id),
+ server_id TEXT,
build_id INTEGER REFERENCES builds(id),
start_time INTEGER,
end_time INTEGER
diff --git a/src/com/projectswg/common/data/HeavyweightBackendData.java b/src/com/projectswg/common/data/HeavyweightBackendData.java
index 0ecd061..0ced3ce 100644
--- a/src/com/projectswg/common/data/HeavyweightBackendData.java
+++ b/src/com/projectswg/common/data/HeavyweightBackendData.java
@@ -87,6 +87,7 @@ public class HeavyweightBackendData implements BackendData {
for (String serverId : serverTable.getServerStrings()) {
ServerServerData server = createServerFromInfo(serverTable.getServerById(serverId));
fetchBuildHistory(db, server);
+ fetchDeploymentHistory(db, server);
serverMap.put(serverId, server);
}
}
@@ -101,7 +102,6 @@ public class HeavyweightBackendData implements BackendData {
server.addBuild(build);
}
}
- fetchDeploymentHistory(db, server);
}
private void fetchDeploymentHistory(RelationalDatabase db, ServerServerData server) {
diff --git a/src/com/projectswg/common/utilities/TimeFormatUtilities.java b/src/com/projectswg/common/utilities/TimeFormatUtilities.java
new file mode 100644
index 0000000..ce4cafc
--- /dev/null
+++ b/src/com/projectswg/common/utilities/TimeFormatUtilities.java
@@ -0,0 +1,53 @@
+/***********************************************************************************
+* Copyright (c) 2015 /// Project SWG /// www.projectswg.com *
+* *
+* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
+* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
+* Our goal is to create an emulator which will provide a server for players to *
+* continue playing a game similar to the one they used to play. We are basing *
+* it on the final publish of the game prior to end-game events. *
+* *
+* This file is part of Holocore. *
+* *
+* -------------------------------------------------------------------------------- *
+* *
+* Holocore is free software: you can redistribute it and/or modify *
+* it under the terms of the GNU Affero General Public License as *
+* published by the Free Software Foundation, either version 3 of the *
+* License, or (at your option) any later version. *
+* *
+* Holocore is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU Affero General Public License for more details. *
+* *
+* You should have received a copy of the GNU Affero General Public License *
+* along with Holocore. If not, see . *
+* *
+***********************************************************************************/
+package com.projectswg.common.utilities;
+
+public class TimeFormatUtilities {
+
+ public static String getTime(long time) {
+ int days = (int) (time / (24 * 3600E3));
+ int hours = (int) (time % (24 * 3600E3) / 3600E3);
+ int minutes = (int) ((time % 3600E3) / 60E3);
+ int seconds = (int) (time % 60E3) / 1000;
+ String text = "";
+ text += getPlurality("Day", days);
+ text += getPlurality("Hour", hours);
+ text += getPlurality("Minute", minutes);
+ text += getPlurality("Second", seconds);
+ return text;
+ }
+
+ private static String getPlurality(String base, int amount) {
+ if (amount > 1)
+ return amount + " " + base + "s ";
+ if (amount == 1)
+ return amount + " " + base + " ";
+ return "";
+ }
+
+}
diff --git a/src/com/projectswg/lightspeed/CommunicationService.java b/src/com/projectswg/lightspeed/CommunicationService.java
index fd8d10b..343ec65 100644
--- a/src/com/projectswg/lightspeed/CommunicationService.java
+++ b/src/com/projectswg/lightspeed/CommunicationService.java
@@ -38,6 +38,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
@@ -55,6 +58,7 @@ import org.nanohttpd.protocols.http.threading.IAsyncRunner;
import resources.common.BCrypt;
import me.joshlarson.json.JSONObject;
+import com.projectswg.common.concurrency.PswgBasicScheduledThread;
import com.projectswg.common.concurrency.PswgThreadPool;
import com.projectswg.common.control.LightspeedService;
import com.projectswg.common.data.CsvTable;
@@ -70,8 +74,10 @@ public class CommunicationService extends LightspeedService {
private final NanoHTTPD httpServer;
private final Map responders;
+ private final PswgBasicScheduledThread userTableUpdater;
private final BoundRunner runner;
private final CsvTable users;
+ private final ReadWriteLock userLock;
public CommunicationService() {
this.httpServer = new NanoHTTPD(44444) {
@@ -80,8 +86,10 @@ public class CommunicationService extends LightspeedService {
}
};
this.responders = new HashMap<>();
- this.runner = new BoundRunner(20);
+ this.userTableUpdater = new PswgBasicScheduledThread("comm-user-table-updater", () -> updateUserTable());
+ this.runner = new BoundRunner(5);
this.users = new CsvTable(new File("data/users.csv"));
+ this.userLock = new ReentrantReadWriteLock(true);
httpServer.setAsyncRunner(runner);
registerForIntent(RegisterHttpListenerIntent.class, rhli -> handleRegisterListener(rhli));
@@ -97,6 +105,7 @@ public class CommunicationService extends LightspeedService {
File cert = new File("data", pubkey);
httpServer.makeSecure(createSSLSocketFactory(cert, pass), null);
}
+ userTableUpdater.startWithFixedDelay(0, 60000);
runner.start();
httpServer.start(config.getInt("HTTP-TIMEOUT", 2000), false);
} catch (IOException e) {
@@ -108,6 +117,7 @@ public class CommunicationService extends LightspeedService {
@Override
public boolean terminate() {
+ userTableUpdater.stop();
runner.stop();
httpServer.stop();
return super.terminate();
@@ -132,6 +142,18 @@ public class CommunicationService extends LightspeedService {
}
}
+ private void updateUserTable() {
+ Lock write = userLock.writeLock();
+ try {
+ write.lock();
+ users.read();
+ } catch (IOException e) {
+ Log.e(e);
+ } finally {
+ write.unlock();
+ }
+ }
+
private boolean authenticate(String combined, String host, String addr) {
if (combined == null)
return false;
@@ -143,12 +165,9 @@ public class CommunicationService extends LightspeedService {
split = combined.split(":", 2);
String user = split[0];
String pass = split[1];
- synchronized (users) {
- try {
- users.read();
- } catch (IOException e) {
- Log.e(e);
- }
+ Lock readLock = userLock.readLock();
+ try {
+ readLock.lock();
for (int i = 0; i < users.getRows(); i++) {
if (users.getRecord(i, "user").equals(user)) {
String recordedPass = users.getRecord(i, "pass");
@@ -159,8 +178,10 @@ public class CommunicationService extends LightspeedService {
return valid;
}
}
+ return false;
+ } finally {
+ readLock.unlock();
}
- return false;
}
private Response serve(IHTTPSession session) {
diff --git a/src/com/projectswg/lightspeed_frontend/Frontend.java b/src/com/projectswg/lightspeed_frontend/Frontend.java
index 581766b..5340b3e 100644
--- a/src/com/projectswg/lightspeed_frontend/Frontend.java
+++ b/src/com/projectswg/lightspeed_frontend/Frontend.java
@@ -55,7 +55,6 @@ import com.projectswg.common.network.packets.response.ResponseServerListPacket;
import com.projectswg.lightspeed_frontend.communication.FrontendCommunication;
import com.projectswg.lightspeed_frontend.communication.FrontendCommunication.ResponseCallback;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
-import com.projectswg.lightspeed_frontend.data.SharedBuildData.BuildState;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import com.projectswg.lightspeed_frontend.intents.InboundPacketIntent;
@@ -70,7 +69,8 @@ public class Frontend {
private final Config config;
public Frontend() {
- this.threadPool = new PswgThreadPool(10, "frontend-thread-pool");
+ this.threadPool = new PswgThreadPool(5, "frontend-thread-pool");
+ this.threadPool.setWaitForTermination(false);
this.scheduledUpdater = new PswgScheduledThreadPool(1, "frontend-updater");
this.data = new FrontendData();
File data = new File("cfg");
@@ -84,15 +84,21 @@ public class Frontend {
}
public void setAddress(InetSocketAddress address) {
- communication.setAddress(address);
+ Log.i("Changing remote address to %s", address);
+ if (!address.equals(communication.getAddress())) {
+ communication.setAddress(address);
+ Log.i("Clearing all frontend data - requesting complete reload");
+ data.clearAll();
+ requestCompleteLoad();
+ }
}
public void start() {
Assert.test(communication.start());
threadPool.start();
scheduledUpdater.start();
- scheduledUpdater.executeWithFixedDelay(5000, 5000, () -> requestCompleteLoad());
- scheduledUpdater.executeWithFixedDelay(1000, 1000, () -> requestLatestUpdates());
+ scheduledUpdater.executeWithFixedDelay(0, 10000, () -> requestCompleteLoad());
+ scheduledUpdater.executeWithFixedDelay(3000, 3000, () -> requestLatestUpdates());
}
public void stop() {
@@ -132,7 +138,7 @@ public class Frontend {
send(p, null);
}
- public void loadServerDetailed(String serverId, ResponseCallback callback) {
+ private void loadServerDetailed(String serverId, ResponseCallback callback) {
send(new RequestServerDetailedPacket(serverId), callback);
}
@@ -144,27 +150,19 @@ public class Frontend {
send(new RequestDeploymentDetailedPacket(deploymentId), callback);
}
- public void loadBuildHistory(String serverId, ResponseCallback callback) {
+ private void loadBuildHistory(String serverId, ResponseCallback callback) {
send(new RequestBuildListPacket(serverId), callback);
}
- public void loadDeploymentHistory(String serverId, ResponseCallback callback) {
+ private void loadDeploymentHistory(String serverId, ResponseCallback callback) {
send(new RequestDeploymentListPacket(serverId), callback);
}
- public void requestCompleteLoad() {
+ private void requestCompleteLoad() {
send(new RequestServerListPacket(), (response) -> {
for (SharedServerData server : ((ResponseServerListPacket) response).getServerList()) {
- loadBuildHistory(server.getName(), buildResponse -> {
- SharedBuildData lastBuild = data.getServer(server.getName()).getLastBuild();
- if (lastBuild != null)
- loadBuildDetailed(lastBuild.getId(), null);
- });
- loadDeploymentHistory(server.getName(), deployResponse -> {
- SharedDeploymentData lastDeployment = data.getServer(server.getName()).getLastDeployment();
- if (lastDeployment != null)
- loadDeploymentDetailed(lastDeployment.getId(), null);
- });
+ loadBuildHistory(server.getName(), null);
+ loadDeploymentHistory(server.getName(), null);
}
});
}
@@ -173,15 +171,14 @@ public class Frontend {
SharedServerData server = data.getSelectedServer();
if (server == null)
return;
- SharedBuildData lastBuild = data.getServer(server.getName()).getLastBuild();
- if (lastBuild != null) {
- BuildState state = lastBuild.getBuildState();
- if (state.isInProgress())
- loadBuildDetailed(lastBuild.getId(), null);
+ SharedBuildData lastBuild = server.getLastBuild();
+ if (lastBuild != null && lastBuild.getBuildState().isInProgress()) {
+ loadBuildDetailed(lastBuild.getId(), null);
}
- SharedDeploymentData lastDeployment = data.getServer(server.getName()).getLastDeployment();
- if (lastDeployment != null)
+ SharedDeploymentData lastDeployment = server.getLastDeployment();
+ if (lastDeployment != null) {
loadDeploymentDetailed(lastDeployment.getId(), null);
+ }
}
private void process(Packet packet) {
@@ -223,11 +220,15 @@ public class Frontend {
private void processBuildList(ResponseBuildListPacket list) {
SharedServerData server = data.getServer(list.getServerId());
+ SharedBuildData last = server.getLastBuild();
for (SharedBuildData build : list.getBuildList()) {
if (server.getBuildData(build.getId()) == null) {
server.addBuild(build);
}
}
+ SharedBuildData nLast = server.getLastBuild();
+ if (last != nLast && nLast != null)
+ loadBuildDetailed(nLast.getId(), null);
}
private void processBuildDetailed(ResponseBuildDetailedPacket detailed) {
@@ -247,11 +248,15 @@ public class Frontend {
private void processDeploymentList(ResponseDeploymentListPacket list) {
SharedServerData server = data.getServer(list.getServerId());
+ SharedDeploymentData last = server.getLastDeployment();
for (SharedDeploymentData deployment : list.getDeploymentList()) {
if (server.getDeploymentData(deployment.getId()) == null) {
server.addDeployment(deployment);
}
}
+ SharedDeploymentData nLast = server.getLastDeployment();
+ if (last != nLast && nLast != null)
+ loadDeploymentDetailed(nLast.getId(), null);
}
private void processDeploymentDetailed(ResponseDeploymentDetailedPacket detailed) {
diff --git a/src/com/projectswg/lightspeed_frontend/LightspeedFrontendGUI.java b/src/com/projectswg/lightspeed_frontend/LightspeedFrontendGUI.java
index 8aff9b0..69a7c9f 100644
--- a/src/com/projectswg/lightspeed_frontend/LightspeedFrontendGUI.java
+++ b/src/com/projectswg/lightspeed_frontend/LightspeedFrontendGUI.java
@@ -66,7 +66,6 @@ public class LightspeedFrontendGUI extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
IntentManager.getInstance().initialize();
- frontend.requestCompleteLoad();
primaryView = (LightspeedPrimaryView) FXMLUtilities.loadFxml("PrimaryView.fxml", Locale.ENGLISH);
Parent root = primaryView.getRoot();
primaryStage.setTitle("Lightspeed Frontend");
diff --git a/src/com/projectswg/lightspeed_frontend/communication/HttpClient.java b/src/com/projectswg/lightspeed_frontend/communication/HttpClient.java
index 8c933ce..9a5f7fd 100644
--- a/src/com/projectswg/lightspeed_frontend/communication/HttpClient.java
+++ b/src/com/projectswg/lightspeed_frontend/communication/HttpClient.java
@@ -98,7 +98,9 @@ public class HttpClient {
return null;
}
try {
+ long start = System.nanoTime();
String str = requestString(address, packet);
+ Log.d("Took %.3fms to request and receive a packet", (System.nanoTime()-start)/1E6);
JSONObject obj = JSON.readObject(str, false);
if (obj == null) {
Log.d("Invalid JSON: URL=%s%n%s", address, str);
@@ -140,7 +142,6 @@ public class HttpClient {
private static String generateURL(InetSocketAddress address, Packet packet) throws UnsupportedEncodingException {
StringBuilder url = new StringBuilder("https://"+address.getAddress().getHostAddress()+":"+address.getPort()+"/?");
- Log.d("URL: %s", url);
JSONObject obj = packet.getJSON();
if (packet instanceof PostPacket)
url.append("type=" + ((PostPacket) packet).getType().name().replace("POST_", "") + '&');
diff --git a/src/com/projectswg/lightspeed_frontend/gui/LightspeedPrimaryView.java b/src/com/projectswg/lightspeed_frontend/gui/LightspeedPrimaryView.java
index 68d4472..8a3da49 100644
--- a/src/com/projectswg/lightspeed_frontend/gui/LightspeedPrimaryView.java
+++ b/src/com/projectswg/lightspeed_frontend/gui/LightspeedPrimaryView.java
@@ -36,7 +36,6 @@ import java.util.ResourceBundle;
import com.projectswg.common.concurrency.PswgBasicScheduledThread;
import com.projectswg.common.concurrency.PswgThreadPool;
-import com.projectswg.common.debug.Log;
import com.projectswg.common.javafx.FXMLController;
import com.projectswg.common.javafx.FXMLUtilities;
import com.projectswg.common.network.packets.post.PostBuildPacket;
@@ -127,18 +126,8 @@ public class LightspeedPrimaryView implements FXMLController {
private void updateAddress() {
ipUpdater.execute(() -> {
InetSocketAddress addr = createAddress();
- InetSocketAddress prev = frontend.getCommunication().getAddress();
- boolean changed = (prev == null || addr == null) ? prev != addr : !prev.equals(addr);
- if (changed) {
- Log.i("Changing remote address to %s", addr);
- frontend.setAddress(addr);
- Platform.runLater(() -> validIpRegion.setBackground(addr == null ? invalidIpBackground : validIpBackground));
- if (addr != null) {
- Log.i("Clearing all frontend data - requesting complete reload");
- frontend.getData().clearAll();
- frontend.requestCompleteLoad();
- }
- }
+ frontend.setAddress(addr);
+ Platform.runLater(() -> validIpRegion.setBackground(addr == null ? invalidIpBackground : validIpBackground));
});
}
diff --git a/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/BuildTab.java b/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/BuildTab.java
index 1bd38e7..af62eeb 100644
--- a/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/BuildTab.java
+++ b/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/BuildTab.java
@@ -32,7 +32,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
-import com.projectswg.common.concurrency.PswgBasicScheduledThread;
+import com.projectswg.common.control.IntentManager;
import com.projectswg.common.data.TestDetails;
import com.projectswg.common.debug.Log;
import com.projectswg.common.javafx.FXMLController;
@@ -43,6 +43,7 @@ import com.projectswg.lightspeed_frontend.LightspeedFrontendGUI;
import com.projectswg.lightspeed_frontend.data.SharedBuildData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
import com.projectswg.lightspeed_frontend.data.SharedBuildData.BuildState;
+import com.projectswg.lightspeed_frontend.intents.InboundPacketIntent;
import javafx.application.Platform;
import javafx.fxml.FXML;
@@ -60,11 +61,9 @@ public class BuildTab implements FXMLController {
@FXML
private Label serverNameText, buildIdText, statusText, timeText, compileTimeText, testText;
- private final PswgBasicScheduledThread scheduledUpdater;
private final Frontend frontend;
public BuildTab() {
- this.scheduledUpdater = new PswgBasicScheduledThread("build-tab-updater", () -> requestUpdate());
this.frontend = LightspeedFrontendGUI.FRONTEND;
}
@@ -90,22 +89,9 @@ public class BuildTab implements FXMLController {
frontend.loadBuildDetailed(next.getId(), response -> Platform.runLater(() -> updateBuildDetails()));
updateBuildDetails();
});
+ IntentManager.getInstance().registerForIntent(InboundPacketIntent.class, ipi -> updateUi());
this.frontend.getData().getSelectedServerProperty().addListener((val, prev, next) -> updateUi());
updateUi();
- scheduledUpdater.startWithFixedRate(10000, 10000);
- }
-
- @Override
- public void terminate() {
- scheduledUpdater.stop();
- scheduledUpdater.awaitTermination(1000);
- }
-
- private void requestUpdate() {
- SharedBuildData selected = frontend.getData().getSelectedBuild();
- if (selected != null) {
- frontend.loadBuildDetailed(selected.getId(), response -> updateUi());
- }
}
private void updateUi() {
@@ -138,6 +124,10 @@ public class BuildTab implements FXMLController {
return 1;
return Long.compare(b.getId(), a.getId());
});
+ if (buildComboBox.getSelectionModel().getSelectedItem() == null) {
+ frontend.getData().setSelectedBuild(selectedServer.getLastBuild());
+ updateBuildDetails();
+ }
} else {
buildComboBox.getItems().clear();
buildComboBox.getItems().add(null);
@@ -262,12 +252,12 @@ public class BuildTab implements FXMLController {
public String toString(SharedBuildData build) {
if (build == null)
- return "";
+ return "latest";
return "B " + build.getId();
}
public SharedBuildData fromString(String string) {
- if (string.isEmpty())
+ if (string.isEmpty() || string.equals("latest"))
return null;
String [] parts = string.split(" ");
return frontend.getData().getBuild(Long.parseLong(parts[1]));
diff --git a/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/DeploymentTab.java b/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/DeploymentTab.java
index dadcab9..7dcfb09 100644
--- a/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/DeploymentTab.java
+++ b/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/DeploymentTab.java
@@ -34,14 +34,17 @@ import java.util.Locale;
import java.util.ResourceBundle;
import com.projectswg.common.concurrency.PswgScheduledThreadPool;
+import com.projectswg.common.control.IntentManager;
import com.projectswg.common.debug.Log;
import com.projectswg.common.javafx.FXMLController;
import com.projectswg.common.javafx.FXMLUtilities;
+import com.projectswg.common.utilities.TimeFormatUtilities;
import com.projectswg.common.utilities.TimeUtilities;
import com.projectswg.lightspeed_frontend.Frontend;
import com.projectswg.lightspeed_frontend.LightspeedFrontendGUI;
import com.projectswg.lightspeed_frontend.data.SharedDeploymentData;
import com.projectswg.lightspeed_frontend.data.SharedServerData;
+import com.projectswg.lightspeed_frontend.intents.InboundPacketIntent;
import javafx.application.Platform;
import javafx.fxml.FXML;
@@ -102,10 +105,10 @@ public class DeploymentTab implements FXMLController {
frontend.loadDeploymentDetailed(next.getId(), response -> Platform.runLater(() -> updateDeploymentDetails()));
updateDeploymentDetails();
});
+ IntentManager.getInstance().registerForIntent(InboundPacketIntent.class, ipi -> updateUi());
this.frontend.getData().getSelectedServerProperty().addListener((val, prev, next) -> updateUi());
updateUi();
scheduledUpdater.start();
- scheduledUpdater.executeWithFixedRate(10000, 10000, () -> requestUpdate());
scheduledUpdater.executeWithFixedRate(1000, 1000, () -> Platform.runLater(() -> updateDeploymentDetails()));
}
@@ -115,13 +118,6 @@ public class DeploymentTab implements FXMLController {
scheduledUpdater.awaitTermination(1000);
}
- private void requestUpdate() {
- SharedDeploymentData selected = frontend.getData().getSelectedDeployment();
- if (selected != null) {
- frontend.loadDeploymentDetailed(selected.getId(), response -> updateUi());
- }
- }
-
private void updateUi() {
Platform.runLater(() -> {
updateDeploymentList();
@@ -152,6 +148,10 @@ public class DeploymentTab implements FXMLController {
return 1;
return Long.compare(b.getId(), a.getId());
});
+ if (deploymentComboBox.getSelectionModel().getSelectedItem() == null) {
+ frontend.getData().setSelectedDeployment(selectedServer.getLastDeployment());
+ updateDeploymentDetails();
+ }
} else {
deploymentComboBox.getItems().clear();
deploymentComboBox.getItems().add(null);
@@ -231,9 +231,9 @@ public class DeploymentTab implements FXMLController {
long start = selectedDeployment.getStartTime();
long end = selectedDeployment.getEndTime();
if (end == 0) {
- uptimeText.setText(getTime(TimeUtilities.getTime()-start));
+ uptimeText.setText(TimeFormatUtilities.getTime(TimeUtilities.getTime()-start));
} else {
- uptimeText.setText(getTime(end-start));
+ uptimeText.setText(TimeFormatUtilities.getTime(end-start));
}
}
}
@@ -256,27 +256,6 @@ public class DeploymentTab implements FXMLController {
}
}
- private String getTime(long time) {
- int days = (int) (time / (24*3600E3));
- int hours = (int) (time % (24*3600E3) / 3600E3);
- int minutes = (int) ((time % 3600E3) / 60E3);
- int seconds = (int) (time % 60E3) / 1000;
- String text = "";
- text += getPlurality("Day", days);
- text += getPlurality("Hour", hours);
- text += getPlurality("Minute", minutes);
- text += getPlurality("Second", seconds);
- return text;
- }
-
- private String getPlurality(String base, int amount) {
- if (amount > 1)
- return amount + " " + base + "s ";
- if (amount == 1)
- return amount + " " + base + " ";
- return "";
- }
-
public interface SelectedDeploymentChangedCallback {
void onDeploymentChanged(SharedDeploymentData deployment);
}
@@ -285,12 +264,12 @@ public class DeploymentTab implements FXMLController {
public String toString(SharedDeploymentData deployment) {
if (deployment == null)
- return "";
+ return "latest";
return "D " + deployment.getId() + " - B " + deployment.getBuild().getId();
}
public SharedDeploymentData fromString(String string) {
- if (string.isEmpty())
+ if (string.isEmpty() || string.equals("latest"))
return null;
String [] parts = string.split(" ");
return frontend.getData().getDeployment(Long.parseLong(parts[1]));
diff --git a/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/GeneralTab.java b/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/GeneralTab.java
index a9ba434..5a6f7ab 100644
--- a/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/GeneralTab.java
+++ b/src/com/projectswg/lightspeed_frontend/gui/primary_tabs/GeneralTab.java
@@ -29,12 +29,14 @@ package com.projectswg.lightspeed_frontend.gui.primary_tabs;
import java.net.URL;
import java.util.ResourceBundle;
+import java.util.prefs.Preferences;
-import com.projectswg.common.concurrency.PswgBasicScheduledThread;
+import com.projectswg.common.concurrency.PswgScheduledThreadPool;
import com.projectswg.common.control.IntentManager;
import com.projectswg.common.debug.Log;
import com.projectswg.common.javafx.FXMLController;
import com.projectswg.common.javafx.FXMLUtilities;
+import com.projectswg.common.utilities.TimeFormatUtilities;
import com.projectswg.common.utilities.TimeUtilities;
import com.projectswg.lightspeed_frontend.Frontend;
import com.projectswg.lightspeed_frontend.LightspeedFrontendGUI;
@@ -68,11 +70,11 @@ public class GeneralTab implements FXMLController {
@FXML
private Label uptimeText;
- private final PswgBasicScheduledThread scheduledUpdater;
+ private final PswgScheduledThreadPool scheduledUpdater;
private final Frontend frontend;
public GeneralTab() {
- this.scheduledUpdater = new PswgBasicScheduledThread("general-tab-updater", () -> requestUpdate());
+ this.scheduledUpdater = new PswgScheduledThreadPool(1, "general-tab-updater");
this.frontend = LightspeedFrontendGUI.FRONTEND;
}
@@ -93,11 +95,14 @@ public class GeneralTab implements FXMLController {
serverComboBox.getSelectionModel().selectedItemProperty().addListener((val, prev, next) -> {
Log.d("selected server manually '%s'", next);
frontend.getData().setSelectedServer(next);
- updateUiDetails();
+ if (next != null)
+ getPreferences().put("selected-server", next.getName());
+ updateGeneralDetails();
});
- IntentManager.getInstance().registerForIntent(InboundPacketIntent.class, ipi -> Platform.runLater(() -> updateUi()));
+ IntentManager.getInstance().registerForIntent(InboundPacketIntent.class, ipi -> updateUi());
updateUi();
- scheduledUpdater.startWithFixedRate(10000, 10000);
+ scheduledUpdater.start();
+ scheduledUpdater.executeWithFixedRate(1000, 1000, () -> Platform.runLater(() -> updateGeneralDetails()));
}
@Override
@@ -106,138 +111,144 @@ public class GeneralTab implements FXMLController {
scheduledUpdater.awaitTermination(1000);
}
- private void requestUpdate() {
- SharedServerData selected = frontend.getData().getSelectedServer();
- if (selected != null) {
- frontend.loadServerDetailed(selected.getName(), response -> updateUi());
- }
- }
-
private void updateUi() {
Platform.runLater(() -> {
updateServerList();
- updateUiDetails();
+ updateGeneralDetails();
});
}
private void updateServerList() {
serverComboBox.setItems(frontend.getData().getServers());
- }
-
- private void updateUiDetails() {
- SharedServerData selected = frontend.getData().getSelectedServer();
- if (selected == null) {
- setServerName("N/A");
- setEmptyBuildStatus();
- setEmptyDeploymentStatus();
- setEmptyPopulationText();
- setEmptyUptimeText();
- } else {
- SharedBuildData lastBuild = selected.getLastBuild();
- SharedDeploymentData lastDeployment = selected.getLastDeployment();
- setServerName(selected == null ? "N/A" : selected.getName());
- if (lastBuild == null)
- setEmptyBuildStatus();
- else
- setBuildStatus(lastBuild.getBuildState());
- if (lastDeployment == null) {
- setEmptyDeploymentStatus();
- } else {
- if (lastDeployment.getEndTime() != -1) {
- setDeploymentStatus(false);
- setEmptyPopulationText();
- setUptimeText(lastDeployment.getEndTime()-lastDeployment.getStartTime());
- } else {
- setDeploymentStatus(true);
- setPopulationText(0);
- setUptimeText(TimeUtilities.getTime()-lastDeployment.getStartTime());
- }
- }
+ if (frontend.getData().getSelectedServer() == null) {
+ // If the user chose some other server last time around - use that, otherwise default to NGE
+ serverComboBox.getSelectionModel().select(frontend.getData().getServer(getPreferences().get("selected-server", "NGE")));
}
}
- private void setServerName(String name) {
- serverNameText.setText(name);
+ private void updateGeneralDetails() {
+ SharedServerData selected = frontend.getData().getSelectedServer();
+ setServerName(selected);
+ setBuildStatus(selected);
+ setDeploymentStatus(selected);
+ setPopulationText(selected);
+ setUptimeText(selected);
}
- private void setEmptyBuildStatus() {
- buildStatusText.getStyleClass().setAll("white-label");
- buildStatusText.setText("N/A");
+ private void setServerName(SharedServerData server) {
+ String name = server == null ? "N/A" : server.getName();
+ setText(serverNameText, TextStyle.WHITE, name);
}
- private void setBuildStatus(BuildState state) {
+ private void setBuildStatus(SharedServerData server) {
+ if (server == null) {
+ setText(buildStatusText, TextStyle.WHITE, "N/A");
+ return;
+ }
+ SharedBuildData lastBuild = server.getLastBuild();
+ if (lastBuild == null) {
+ setText(buildStatusText, TextStyle.WHITE, "Not Built");
+ return;
+ }
+ BuildState state = lastBuild.getBuildState();
+ TextStyle style = TextStyle.WHITE;
switch (state) {
case CREATED:
case UNKNOWN:
- buildStatusText.getStyleClass().setAll("white-label");
+ style = TextStyle.WHITE;
break;
case CANCELLED:
case COMPILE_FAILED:
case TEST_FAILED:
case INSTALL_FAILED:
case FAILED:
- buildStatusText.getStyleClass().setAll("red-label");
+ style = TextStyle.RED;
break;
case COMPILING:
case TESTING:
case INSTALLING:
case SUCCESS:
- buildStatusText.getStyleClass().setAll("green-label");
+ style = TextStyle.GREEN;
break;
}
- buildStatusText.setText(state.toString());
+ setText(buildStatusText, style, state.toString());
}
- private void setEmptyDeploymentStatus() {
- deploymentStatusText.getStyleClass().setAll("white-label");
- deploymentStatusText.setText("N/A");
+ private void setDeploymentStatus(SharedServerData server) {
+ if (server == null) {
+ setText(deploymentStatusText, TextStyle.WHITE, "N/A");
+ return;
+ }
+ SharedDeploymentData deployment = server.getLastDeployment();
+ if (deployment == null) {
+ setText(deploymentStatusText, TextStyle.WHITE, "Not Deployed");
+ return;
+ }
+ if (deployment.getEndTime() == 0) {
+ setText(deploymentStatusText, TextStyle.GREEN, "Running");
+ } else {
+ setText(deploymentStatusText, TextStyle.WHITE, "Stopped");
+ }
}
- private void setDeploymentStatus(boolean running) {
- deploymentStatusText.getStyleClass().setAll(running ? "green-label" : "white-label");
- deploymentStatusText.setText(running ? "Running" : "Idle");
+ private void setPopulationText(SharedServerData server) {
+ if (server == null) {
+ setText(populationText, TextStyle.WHITE, "N/A");
+ return;
+ }
+ SharedDeploymentData deployment = server.getLastDeployment();
+ if (deployment == null) {
+ setText(populationText, TextStyle.WHITE, "Not Deployed");
+ return;
+ }
+ populationText.setText(String.format("%d Characters Online", 0));
}
- private void setEmptyPopulationText() {
- populationText.setText("N/A");
+ private void setUptimeText(SharedServerData server) {
+ if (server == null) {
+ setText(uptimeText, TextStyle.WHITE, "N/A");
+ return;
+ }
+ SharedDeploymentData deployment = server.getLastDeployment();
+ if (deployment == null) {
+ setText(uptimeText, TextStyle.WHITE, "Not Deployed");
+ return;
+ }
+ long uptime;
+ TextStyle style;
+ if (deployment.getEndTime() == 0) {
+ uptime = TimeUtilities.getTime() - deployment.getStartTime();
+ style = TextStyle.GREEN;
+ } else {
+ uptime = deployment.getEndTime() - deployment.getStartTime();
+ style = TextStyle.WHITE;
+ }
+ setText(uptimeText, style, TimeFormatUtilities.getTime(uptime));
}
- private void setPopulationText(int count) {
- populationText.setText(String.format("%d Characters Online", count));
+ private void setText(Label label, TextStyle style, String text) {
+ switch (style) {
+ case WHITE: label.getStyleClass().setAll("white-label"); break;
+ case GREEN: label.getStyleClass().setAll("green-label"); break;
+ case RED: label.getStyleClass().setAll("red-label"); break;
+ }
+ label.setText(text);
}
- private void setEmptyUptimeText() {
- uptimeText.setText("N/A");
- }
-
- private void setUptimeText(long uptime) {
- uptime /= 1000;
- int seconds = (int) (uptime % 60);
- uptime /= 60;
- int minutes = (int) (uptime % 60);
- uptime /= 60;
- int hours = (int) (uptime % 24);
- uptime /= 24;
- String text = "";
- text += getPlurality("Day", (int) uptime);
- text += getPlurality("Hour", hours);
- text += getPlurality("Minute", minutes);
- text += getPlurality("Second", seconds);
- uptimeText.setText(text);
- }
-
- private String getPlurality(String base, int amount) {
- if (amount > 1)
- return amount + " " + base + "s ";
- if (amount == 1)
- return amount + " " + base + " ";
- return "";
+ private Preferences getPreferences() {
+ return frontend.getPreferences().node("general_tab");
}
public interface SelectedServerChangedCallback {
void onServerChanged(SharedServerData server);
}
+ private enum TextStyle {
+ WHITE,
+ GREEN,
+ RED
+ }
+
private class ServerStringConverter extends StringConverter {
public String toString(SharedServerData server) {