GUI -- Further work on refactoring Topology View server side code.
- includes some cleanup of UiMessageHandler and subclasses thereof.
Change-Id: Ie48d830447a4abe1b3accda41a934530a4d55d0e
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/AltTopoViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/AltTopoViewMessageHandler.java
index 8a7534f..fc16133 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/AltTopoViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/AltTopoViewMessageHandler.java
@@ -53,6 +53,7 @@
private static final String TOPO_START = "topoStart";
private static final String TOPO_STOP = "topoStop";
private static final String REQ_SUMMARY = "requestSummary";
+ private static final String CANCEL_SUMMARY = "cancelSummary";
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -80,6 +81,13 @@
currentSummaryGenerator = defaultSummaryGenerator;
}
+ @Override
+ public void destroy() {
+// cancelAllMonitoring();
+// stopListeningToModel();
+ super.destroy();
+ }
+
private String getVersion() {
String ver = directory.get(CoreService.class).version().toString();
@@ -88,11 +96,12 @@
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(
new TopoStart(),
new TopoStop(),
- new ReqSummary()
+ new ReqSummary(),
+ new CancelSummary()
// TODO: add more handlers here.....
);
}
@@ -157,6 +166,17 @@
}
}
+ private final class CancelSummary extends RequestHandler {
+ private CancelSummary() {
+ super(CANCEL_SUMMARY);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ modelService.stopSummaryMonitoring();
+ }
+ }
+
// =====================================================================
private final class DefSummaryGenerator extends AbstractSummaryGenerator {
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationViewMessageHandler.java
index 61a543a..77a5897 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationViewMessageHandler.java
@@ -57,7 +57,7 @@
};
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(
new AppDataRequest(),
new AppMgmtRequest()
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/ClusterViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/ClusterViewMessageHandler.java
index 6ae987e..da0eae0 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/ClusterViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/ClusterViewMessageHandler.java
@@ -54,7 +54,7 @@
private static final String ICON_ID_OFFLINE = "inactive";
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(new ClusterDataRequest());
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
index 01ec738..d1cbcb4 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/DeviceViewMessageHandler.java
@@ -84,7 +84,7 @@
private static final String ICON_ID_OFFLINE = "inactive";
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(
new DataRequestHandler(),
new DetailRequestHandler()
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
index ae01890..0217911 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/FlowViewMessageHandler.java
@@ -65,7 +65,7 @@
};
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(new FlowDataRequest());
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/GroupViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/GroupViewMessageHandler.java
index 105a99f..d7e1047 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/GroupViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/GroupViewMessageHandler.java
@@ -56,7 +56,7 @@
};
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(new GroupDataRequest());
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/HostViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/HostViewMessageHandler.java
index a42ed90..12a2b66 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/HostViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/HostViewMessageHandler.java
@@ -56,7 +56,7 @@
};
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(new HostDataRequest());
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/IntentViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/IntentViewMessageHandler.java
index 29ec648..8ac51dd 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/IntentViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/IntentViewMessageHandler.java
@@ -63,7 +63,7 @@
};
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(new IntentDataRequest());
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/LinkViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/LinkViewMessageHandler.java
index f594a92..9d4608a 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/LinkViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/LinkViewMessageHandler.java
@@ -59,7 +59,7 @@
private static final String ICON_ID_OFFLINE = "inactive";
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(new LinkDataRequest());
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/PortViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/PortViewMessageHandler.java
index dbb7032..92ebcf7 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/PortViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/PortViewMessageHandler.java
@@ -54,7 +54,7 @@
};
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(new PortDataRequest());
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
index 232393c..478bfe7 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
@@ -167,7 +167,7 @@
}
@Override
- protected Collection<RequestHandler> getHandlers() {
+ protected Collection<RequestHandler> createRequestHandlers() {
return ImmutableSet.of(
new TopoStart(),
new TopoStop(),
@@ -254,8 +254,8 @@
@Override
public void process(long sid, ObjectNode payload) {
- ObjectNode root = mapper.createObjectNode();
- ArrayNode names = mapper.createArrayNode();
+ ObjectNode root = objectNode();
+ ArrayNode names = arrayNode();
get(SpriteService.class).getNames().forEach(names::add);
root.set("names", names);
sendMessage("spriteListResponse", sid, root);
@@ -270,7 +270,7 @@
@Override
public void process(long sid, ObjectNode payload) {
String name = string(payload, "name");
- ObjectNode root = mapper.createObjectNode();
+ ObjectNode root = objectNode();
root.set("data", get(SpriteService.class).get(name));
sendMessage("spriteDataResponse", sid, root);
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java
index 9f24f39..f87ad7e 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandlerBase.java
@@ -171,7 +171,7 @@
// Produces JSON structure from annotations.
private JsonNode props(Annotations annotations) {
- ObjectNode props = mapper.createObjectNode();
+ ObjectNode props = objectNode();
if (annotations != null) {
for (String key : annotations.keys()) {
props.put(key, annotations.value(key));
@@ -197,7 +197,7 @@
// Produces a log message event bound to the client.
private ObjectNode message(String severity, long id, String message) {
- ObjectNode payload = mapper.createObjectNode()
+ ObjectNode payload = objectNode()
.put("severity", severity)
.put("message", message);
@@ -266,14 +266,14 @@
protected ObjectNode instanceMessage(ClusterEvent event, String messageType) {
ControllerNode node = event.subject();
int switchCount = mastershipService.getDevicesOf(node.id()).size();
- ObjectNode payload = mapper.createObjectNode()
+ ObjectNode payload = objectNode()
.put("id", node.id().toString())
.put("ip", node.ip().toString())
.put("online", clusterService.getState(node.id()) == ACTIVE)
.put("uiAttached", node.equals(clusterService.getLocalNode()))
.put("switches", switchCount);
- ArrayNode labels = mapper.createArrayNode();
+ ArrayNode labels = arrayNode();
labels.add(node.id().toString());
labels.add(node.ip().toString());
@@ -291,7 +291,7 @@
// Produces a device event message to the client.
protected ObjectNode deviceMessage(DeviceEvent event) {
Device device = event.subject();
- ObjectNode payload = mapper.createObjectNode()
+ ObjectNode payload = objectNode()
.put("id", device.id().toString())
.put("type", device.type().toString().toLowerCase())
.put("online", deviceService.isAvailable(device.id()))
@@ -299,7 +299,7 @@
// Generate labels: id, chassis id, no-label, optional-name
String name = device.annotations().value(AnnotationKeys.NAME);
- ArrayNode labels = mapper.createArrayNode();
+ ArrayNode labels = arrayNode();
labels.add("");
labels.add(isNullOrEmpty(name) ? device.id().toString() : name);
labels.add(device.id().toString());
@@ -318,7 +318,7 @@
// Produces a link event message to the client.
protected ObjectNode linkMessage(LinkEvent event) {
Link link = event.subject();
- ObjectNode payload = mapper.createObjectNode()
+ ObjectNode payload = objectNode()
.put("id", compactLinkString(link))
.put("type", link.type().toString().toLowerCase())
.put("online", link.state() == Link.State.ACTIVE)
@@ -336,13 +336,13 @@
protected ObjectNode hostMessage(HostEvent event) {
Host host = event.subject();
String hostType = host.annotations().value(AnnotationKeys.TYPE);
- ObjectNode payload = mapper.createObjectNode()
+ ObjectNode payload = objectNode()
.put("id", host.id().toString())
.put("type", isNullOrEmpty(hostType) ? "endstation" : hostType)
.put("ingress", compactLinkString(edgeLink(host, true)))
.put("egress", compactLinkString(edgeLink(host, false)));
- payload.set("cp", hostConnect(mapper, host.location()));
- payload.set("labels", labels(mapper, ip(host.ipAddresses()),
+ payload.set("cp", hostConnect(host.location()));
+ payload.set("labels", labels(ip(host.ipAddresses()),
host.mac().toString()));
payload.set("props", props(host.annotations()));
addGeoLocation(host, payload);
@@ -354,15 +354,15 @@
}
// Encodes the specified host location into a JSON object.
- private ObjectNode hostConnect(ObjectMapper mapper, HostLocation location) {
- return mapper.createObjectNode()
+ private ObjectNode hostConnect(HostLocation location) {
+ return objectNode()
.put("device", location.deviceId().toString())
.put("port", location.port().toLong());
}
// Encodes the specified list of labels a JSON array.
- private ArrayNode labels(ObjectMapper mapper, String... labels) {
- ArrayNode json = mapper.createArrayNode();
+ private ArrayNode labels(String... labels) {
+ ArrayNode json = arrayNode();
for (String label : labels) {
json.add(label);
}
@@ -402,7 +402,7 @@
if (slat != null && slng != null && !slat.isEmpty() && !slng.isEmpty()) {
double lat = Double.parseDouble(slat);
double lng = Double.parseDouble(slng);
- ObjectNode loc = mapper.createObjectNode()
+ ObjectNode loc = objectNode()
.put("type", "latlng").put("lat", lat).put("lng", lng);
payload.set("location", loc);
}
@@ -531,22 +531,22 @@
// Produces JSON message to trigger traffic overview visualization
protected ObjectNode trafficSummaryMessage() {
- ObjectNode payload = mapper.createObjectNode();
- ArrayNode paths = mapper.createArrayNode();
+ ObjectNode payload = objectNode();
+ ArrayNode paths = arrayNode();
payload.set("paths", paths);
- ObjectNode pathNodeN = mapper.createObjectNode();
- ArrayNode linksNodeN = mapper.createArrayNode();
- ArrayNode labelsN = mapper.createArrayNode();
+ ObjectNode pathNodeN = objectNode();
+ ArrayNode linksNodeN = arrayNode();
+ ArrayNode labelsN = arrayNode();
pathNodeN.put("class", "plain").put("traffic", false);
pathNodeN.set("links", linksNodeN);
pathNodeN.set("labels", labelsN);
paths.add(pathNodeN);
- ObjectNode pathNodeT = mapper.createObjectNode();
- ArrayNode linksNodeT = mapper.createArrayNode();
- ArrayNode labelsT = mapper.createArrayNode();
+ ObjectNode pathNodeT = objectNode();
+ ArrayNode linksNodeT = arrayNode();
+ ArrayNode labelsT = arrayNode();
pathNodeT.put("class", "secondary").put("traffic", true);
pathNodeT.set("links", linksNodeT);
@@ -581,8 +581,8 @@
// Produces JSON message to trigger flow overview visualization
protected ObjectNode flowSummaryMessage(Set<Device> devices) {
- ObjectNode payload = mapper.createObjectNode();
- ArrayNode paths = mapper.createArrayNode();
+ ObjectNode payload = objectNode();
+ ArrayNode paths = arrayNode();
payload.set("paths", paths);
for (Device device : devices) {
@@ -595,9 +595,9 @@
}
private void addLinkFlows(Link link, ArrayNode paths, Integer count) {
- ObjectNode pathNode = mapper.createObjectNode();
- ArrayNode linksNode = mapper.createArrayNode();
- ArrayNode labels = mapper.createArrayNode();
+ ObjectNode pathNode = objectNode();
+ ArrayNode linksNode = arrayNode();
+ ArrayNode labels = arrayNode();
boolean noFlows = count == null || count == 0;
pathNode.put("class", noFlows ? "secondary" : "primary");
pathNode.put("traffic", false);
@@ -610,8 +610,8 @@
// Produces JSON message to trigger traffic visualization
protected ObjectNode trafficMessage(TrafficClass... trafficClasses) {
- ObjectNode payload = mapper.createObjectNode();
- ArrayNode paths = mapper.createArrayNode();
+ ObjectNode payload = objectNode();
+ ArrayNode paths = arrayNode();
payload.set("paths", paths);
// Classify links based on their traffic traffic first...
@@ -624,10 +624,10 @@
String tc = (biLink.classes() + (hasTraffic ? " animated" : "")).trim();
ObjectNode pathNode = pathNodes.get(tc);
if (pathNode == null) {
- pathNode = mapper.createObjectNode()
+ pathNode = objectNode()
.put("class", tc).put("traffic", hasTraffic);
- pathNode.set("links", mapper.createArrayNode());
- pathNode.set("labels", mapper.createArrayNode());
+ pathNode.set("links", arrayNode());
+ pathNode.set("labels", arrayNode());
pathNodes.put(tc, pathNode);
paths.add(pathNode);
}
@@ -701,11 +701,11 @@
// connectivity intent
protected void addPathTraffic(ArrayNode paths, String type, String trafficType,
Iterable<Link> links) {
- ObjectNode pathNode = mapper.createObjectNode();
- ArrayNode linksNode = mapper.createArrayNode();
+ ObjectNode pathNode = objectNode();
+ ArrayNode linksNode = arrayNode();
if (links != null) {
- ArrayNode labels = mapper.createArrayNode();
+ ArrayNode labels = arrayNode();
boolean hasTraffic = false;
for (Link link : links) {
if (isInfrastructureEgress(link)) {
@@ -767,10 +767,10 @@
// Produces JSON property details.
private ObjectNode json(String id, String type, Prop... props) {
ObjectMapper mapper = new ObjectMapper();
- ObjectNode result = mapper.createObjectNode()
+ ObjectNode result = objectNode()
.put("id", id).put("type", type);
- ObjectNode pnode = mapper.createObjectNode();
- ArrayNode porder = mapper.createArrayNode();
+ ObjectNode pnode = objectNode();
+ ArrayNode porder = arrayNode();
for (Prop p : props) {
porder.add(p.key);
pnode.put(p.key, p.value);
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
index 3295b9e..c571f8f 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
@@ -41,7 +41,7 @@
private static final Logger log = LoggerFactory.getLogger(UiWebSocket.class);
- private static final long MAX_AGE_MS = 15000;
+ private static final long MAX_AGE_MS = 15_000;
private static final byte PING = 0x9;
private static final byte PONG = 0xA;
@@ -83,8 +83,10 @@
* @return true if idle or closed
*/
synchronized boolean isIdle() {
- boolean idle = (System.currentTimeMillis() - lastActive) > MAX_AGE_MS;
+ long quietFor = System.currentTimeMillis() - lastActive;
+ boolean idle = quietFor > MAX_AGE_MS;
if (idle || (connection != null && !connection.isOpen())) {
+ log.debug("IDLE (or closed) websocket [{} ms]", quietFor);
return true;
} else if (connection != null) {
try {
@@ -108,7 +110,8 @@
@Override
public synchronized void onClose(int closeCode, String message) {
destroyHandlers();
- log.info("GUI client disconnected");
+ log.info("GUI client disconnected [close-code={}, message={}]",
+ closeCode, message);
}
@Override
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoUiModelManager.java b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoUiModelManager.java
index 7cb0e40..3a3bf68 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoUiModelManager.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/topo/TopoUiModelManager.java
@@ -50,6 +50,8 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED;
import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
@@ -67,6 +69,9 @@
@Service
public class TopoUiModelManager implements TopoUiModelService {
+ // TODO: put back to 30,000 ms for production
+ private static final long SUMMARY_PERIOD = 15_000;
+
private final Logger log = LoggerFactory.getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -105,6 +110,11 @@
private final TopoMessageFactory messageFactory = new TopoMessageFactory();
private final MetaDb metaDb = new MetaDb();
+ private final Timer timer = new Timer("topology-view");
+
+ private TimerTask summaryTask = null;
+ private boolean summaryRunning = false;
+
@Activate
public void activate() {
@@ -135,7 +145,8 @@
// causes the listener (for an AltTopoViewMessageHandler instance) to
// be removed.
// ==== Somehow need to tie this in to the GUI-disconnected event.
-
+ // This probably requires client-generated heartbeat messages to
+ // Keep the connection alive.
@Override
@@ -159,16 +170,32 @@
}
@Override
- public void startSummaryMonitoring() {
- // TODO: set up periodic monitoring task
- // send a summary now, and periodically...
- post(new TopoUiEvent(SUMMARY_UPDATE, null));
+ public synchronized void startSummaryMonitoring() {
+ // first, cancel previous task if not canceled already
+ stopSummaryMonitoring();
+
+ // create and start a summary task, to execute with no delay, and
+ // every SUMMARY_PERIOD milliseconds thereafter.
+ summaryTask = new TimerTask() {
+ @Override
+ public void run() {
+ if (summaryRunning) {
+ post(new TopoUiEvent(SUMMARY_UPDATE, null));
+ }
+ }
+ };
+
+ timer.schedule(summaryTask, 0, SUMMARY_PERIOD);
+ summaryRunning = true;
}
@Override
- public void stopSummaryMonitoring() {
- // TODO: cancel monitoring task
-
+ public synchronized void stopSummaryMonitoring() {
+ if (summaryTask != null) {
+ summaryTask.cancel();
+ summaryTask = null;
+ }
+ summaryRunning = false;
}
@Override