mirror of
https://bitbucket.org/projectswg/lightspeed.git
synced 2026-07-13 21:01:05 -04:00
Improved the speed of the server and frontend, primarily by making both more efficient
This commit is contained in:
+2
-2
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***********************************************************************************/
|
||||
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 "";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<PacketType, HttpResponder> 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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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_", "") + '&');
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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]));
|
||||
|
||||
@@ -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]));
|
||||
|
||||
@@ -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<SharedServerData> {
|
||||
|
||||
public String toString(SharedServerData server) {
|
||||
|
||||
Reference in New Issue
Block a user