From 5382ab2d30d235d42aea0ff9e3bab4bcbb364b90 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 13 Dec 2018 09:25:37 -0800 Subject: [PATCH] corefx - initial work to add option to display throughputs received from core rest --- corefx/src/main/java/com/core/Controller.java | 59 +++++++++++++++++++ .../java/com/core/client/ICoreClient.java | 4 ++ .../com/core/client/rest/CoreRestClient.java | 12 ++++ .../java/com/core/data/BridgeThroughput.java | 9 +++ .../src/main/java/com/core/data/CoreLink.java | 4 ++ .../com/core/data/InterfaceThroughput.java | 12 ++++ .../main/java/com/core/data/Throughputs.java | 12 ++++ .../java/com/core/graph/NetworkGraph.java | 12 ++++ .../com/core/websocket/CoreWebSocket.java | 14 ++++- corefx/src/main/resources/fxml/main.fxml | 7 +++ 10 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 corefx/src/main/java/com/core/data/BridgeThroughput.java create mode 100644 corefx/src/main/java/com/core/data/InterfaceThroughput.java create mode 100644 corefx/src/main/java/com/core/data/Throughputs.java diff --git a/corefx/src/main/java/com/core/Controller.java b/corefx/src/main/java/com/core/Controller.java index 74128e28..78e7791e 100644 --- a/corefx/src/main/java/com/core/Controller.java +++ b/corefx/src/main/java/com/core/Controller.java @@ -14,10 +14,12 @@ import com.jfoenix.controls.JFXDecorator; import com.jfoenix.controls.JFXProgressBar; import javafx.application.Application; import javafx.application.Platform; +import javafx.concurrent.Task; import javafx.embed.swing.SwingNode; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; +import javafx.scene.control.CheckMenuItem; import javafx.scene.control.MenuItem; import javafx.scene.layout.BorderPane; import javafx.scene.layout.StackPane; @@ -48,7 +50,9 @@ public class Controller implements Initializable { @FXML private SwingNode swingNode; @FXML private MenuItem saveXmlMenuItem; @FXML private JFXProgressBar progressBar; + @FXML private CheckMenuItem throughputMenuItem; + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); private final Map mobilityScripts = new HashMap<>(); private final Map mobilityPlayerDialogs = new HashMap<>(); private Application application; @@ -228,6 +232,27 @@ public class Controller implements Initializable { return result; } + public void handleThroughputs(Throughputs throughputs) { + for (InterfaceThroughput interfaceThroughput : throughputs.getInterfaces()) { + int nodeId = interfaceThroughput.getNode(); + CoreNode node = networkGraph.getVertex(nodeId); + Collection links = networkGraph.getGraph().getIncidentEdges(node); + int interfaceId = interfaceThroughput.getNodeInterface(); + for (CoreLink link : links) { + if (nodeId == link.getNodeOne()) { + if (interfaceId == link.getInterfaceOne().getId()) { + link.setThroughput(interfaceThroughput.getThroughput()); + } + } else { + if (interfaceId == link.getInterfaceTwo().getId()) { + link.setThroughput(interfaceThroughput.getThroughput()); + } + } + } + } + networkGraph.getGraphViewer().repaint(); + } + private void setCoreDefaultServices() { try { coreClient.setDefaultServices(defaultServices); @@ -453,6 +478,9 @@ public class Controller implements Initializable { // setup snackbar Toast.setSnackbarRoot(stackPane); + // setup throughput menu item + throughputMenuItem.setOnAction(event -> executorService.submit(new ChangeThroughputTask())); + // node details networkGraph.getGraphViewer().getPickedVertexState().addItemListener(event -> { CoreNode node = (CoreNode) event.getItem(); @@ -481,4 +509,35 @@ public class Controller implements Initializable { } }); } + + private class ChangeThroughputTask extends Task { + @Override + protected Boolean call() throws Exception { + if (throughputMenuItem.isSelected()) { + return coreClient.startThroughput(); + } else { + return coreClient.stopThroughput(); + } + } + + @Override + protected void succeeded() { + if (getValue()) { + if (throughputMenuItem.isSelected()) { + networkGraph.setShowThroughput(true); + } else { + networkGraph.setShowThroughput(false); + networkGraph.getGraph().getEdges().forEach(edge -> edge.setThroughput(0)); + networkGraph.getGraphViewer().repaint(); + } + } else { + Toast.error("Failure changing throughput"); + } + } + + @Override + protected void failed() { + Toast.error("Error changing throughput", new RuntimeException(getException())); + } + } } diff --git a/corefx/src/main/java/com/core/client/ICoreClient.java b/corefx/src/main/java/com/core/client/ICoreClient.java index d1e31f78..fa06395d 100644 --- a/corefx/src/main/java/com/core/client/ICoreClient.java +++ b/corefx/src/main/java/com/core/client/ICoreClient.java @@ -18,6 +18,10 @@ public interface ICoreClient { Integer currentSession(); + boolean startThroughput() throws IOException; + + boolean stopThroughput() throws IOException; + void updateSession(Integer sessionId); void updateState(SessionState state); diff --git a/corefx/src/main/java/com/core/client/rest/CoreRestClient.java b/corefx/src/main/java/com/core/client/rest/CoreRestClient.java index a3617383..3e963583 100644 --- a/corefx/src/main/java/com/core/client/rest/CoreRestClient.java +++ b/corefx/src/main/java/com/core/client/rest/CoreRestClient.java @@ -144,6 +144,18 @@ public class CoreRestClient implements ICoreClient { return WebUtils.postFile(url, file); } + @Override + public boolean startThroughput() throws IOException { + String url = getUrl("throughput/start"); + return WebUtils.putJson(url); + } + + @Override + public boolean stopThroughput() throws IOException { + String url = getUrl("throughput/stop"); + return WebUtils.putJson(url); + } + @Override public Map> getDefaultServices() throws IOException { String url = getUrl(String.format("sessions/%s/services/default", sessionId)); diff --git a/corefx/src/main/java/com/core/data/BridgeThroughput.java b/corefx/src/main/java/com/core/data/BridgeThroughput.java new file mode 100644 index 00000000..167fb402 --- /dev/null +++ b/corefx/src/main/java/com/core/data/BridgeThroughput.java @@ -0,0 +1,9 @@ +package com.core.data; + +import lombok.Data; + +@Data +public class BridgeThroughput { + private int node; + private Double throughput; +} diff --git a/corefx/src/main/java/com/core/data/CoreLink.java b/corefx/src/main/java/com/core/data/CoreLink.java index 99a284a2..f3d4a215 100644 --- a/corefx/src/main/java/com/core/data/CoreLink.java +++ b/corefx/src/main/java/com/core/data/CoreLink.java @@ -12,12 +12,16 @@ import lombok.NoArgsConstructor; public class CoreLink { @EqualsAndHashCode.Include private Integer id; + @JsonIgnore private Float weight = 1.0f; @JsonIgnore private boolean loaded = true; + @JsonIgnore + private double throughput; + @JsonIgnore private boolean visible = true; diff --git a/corefx/src/main/java/com/core/data/InterfaceThroughput.java b/corefx/src/main/java/com/core/data/InterfaceThroughput.java new file mode 100644 index 00000000..1c6303e0 --- /dev/null +++ b/corefx/src/main/java/com/core/data/InterfaceThroughput.java @@ -0,0 +1,12 @@ +package com.core.data; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class InterfaceThroughput { + private int node; + @JsonProperty("interface") + private int nodeInterface; + private double throughput; +} diff --git a/corefx/src/main/java/com/core/data/Throughputs.java b/corefx/src/main/java/com/core/data/Throughputs.java new file mode 100644 index 00000000..c02a7f6f --- /dev/null +++ b/corefx/src/main/java/com/core/data/Throughputs.java @@ -0,0 +1,12 @@ +package com.core.data; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class Throughputs { + private List interfaces = new ArrayList<>(); + private List bridges = new ArrayList<>(); +} diff --git a/corefx/src/main/java/com/core/graph/NetworkGraph.java b/corefx/src/main/java/com/core/graph/NetworkGraph.java index c1dc04fd..69b8b571 100644 --- a/corefx/src/main/java/com/core/graph/NetworkGraph.java +++ b/corefx/src/main/java/com/core/graph/NetworkGraph.java @@ -41,6 +41,7 @@ import java.util.stream.Collectors; @Data public class NetworkGraph { private static final Logger logger = LogManager.getLogger(); + private static final int EDGE_LABEL_OFFSET = -5; private Controller controller; private ObservableGraph graph; private StaticLayout graphLayout; @@ -61,6 +62,9 @@ public class NetworkGraph { private BackgroundPaintable backgroundPaintable; private CoreVertexLabelRenderer nodeLabelRenderer = new CoreVertexLabelRenderer(); + // display options + private boolean showThroughput = false; + public NetworkGraph(Controller controller) { this.controller = controller; graph = new CoreObservableGraph<>(new UndirectedSimpleGraph<>()); @@ -86,6 +90,14 @@ public class NetworkGraph { }); // link render properties + renderContext.setEdgeLabelTransformer(link -> { + if (!showThroughput || link == null) { + return null; + } + double kbps = link.getThroughput() / 1000.0; + return String.format("%.2f kbps", kbps); + }); + renderContext.setLabelOffset(EDGE_LABEL_OFFSET); renderContext.setEdgeStrokeTransformer(edge -> { LinkTypes linkType = LinkTypes.get(edge.getType()); if (LinkTypes.WIRELESS == linkType) { diff --git a/corefx/src/main/java/com/core/websocket/CoreWebSocket.java b/corefx/src/main/java/com/core/websocket/CoreWebSocket.java index 6b497f4a..3019c622 100644 --- a/corefx/src/main/java/com/core/websocket/CoreWebSocket.java +++ b/corefx/src/main/java/com/core/websocket/CoreWebSocket.java @@ -2,7 +2,6 @@ package com.core.websocket; import com.core.Controller; import com.core.data.*; -import com.core.ui.dialogs.MobilityDialog; import com.core.ui.dialogs.MobilityPlayerDialog; import com.core.utils.JsonUtils; import io.socket.client.IO; @@ -30,6 +29,7 @@ public class CoreWebSocket { socket.on("event", this::handleEvents); socket.on("config", this::handleConfigs); socket.on("link", this::handleLinks); + socket.on("throughput", this::handleThroughputs); socket.on(Socket.EVENT_DISCONNECT, args -> logger.info("disconnected from web socket")); logger.info("attempting to connect to web socket!"); @@ -45,6 +45,18 @@ public class CoreWebSocket { } } + private void handleThroughputs(Object... args) { + for (Object arg : args) { + logger.info("throughput update: {}", arg); + try { + Throughputs throughputs = JsonUtils.read(arg.toString(), Throughputs.class); + controller.handleThroughputs(throughputs); + } catch (IOException ex) { + logger.error("error getting throughputs", ex); + } + } + } + private void handleNodes(Object... args) { for (Object arg : args) { try { diff --git a/corefx/src/main/resources/fxml/main.fxml b/corefx/src/main/resources/fxml/main.fxml index 263e2129..5cc9f1b4 100644 --- a/corefx/src/main/resources/fxml/main.fxml +++ b/corefx/src/main/resources/fxml/main.fxml @@ -2,6 +2,7 @@ + @@ -40,6 +41,12 @@ + + + + + +