UI topo model - Started fleshing out the UiSharedTopologyModel

- marked model listeners in TopolgyViewMessageHandler as deprecated.
 - UiWebSocket now creates a (currently inert) UiTopoSession.

Change-Id: Ic385d782a2f56a90565ad744128f8e469678bcc7
This commit is contained in:
Simon Hunt 2016-04-06 18:40:17 -07:00 committed by Gerrit Code Review
parent ba13871a2a
commit 7092cc4d4f
4 changed files with 191 additions and 21 deletions

View File

@ -714,6 +714,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
} }
// Cluster event listener. // Cluster event listener.
// TODO: Superceded by UiSharedTopologyModel.ModelEventListener
@Deprecated
private class InternalClusterListener implements ClusterEventListener { private class InternalClusterListener implements ClusterEventListener {
@Override @Override
public void event(ClusterEvent event) { public void event(ClusterEvent event) {
@ -722,6 +724,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
} }
// Mastership change listener // Mastership change listener
// TODO: Superceded by UiSharedTopologyModel.ModelEventListener
@Deprecated
private class InternalMastershipListener implements MastershipListener { private class InternalMastershipListener implements MastershipListener {
@Override @Override
public void event(MastershipEvent event) { public void event(MastershipEvent event) {
@ -736,6 +740,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
} }
// Device event listener. // Device event listener.
// TODO: Superceded by UiSharedTopologyModel.ModelEventListener
@Deprecated
private class InternalDeviceListener implements DeviceListener { private class InternalDeviceListener implements DeviceListener {
@Override @Override
public void event(DeviceEvent event) { public void event(DeviceEvent event) {
@ -748,6 +754,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
} }
// Link event listener. // Link event listener.
// TODO: Superceded by UiSharedTopologyModel.ModelEventListener
@Deprecated
private class InternalLinkListener implements LinkListener { private class InternalLinkListener implements LinkListener {
@Override @Override
public void event(LinkEvent event) { public void event(LinkEvent event) {
@ -758,6 +766,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
} }
// Host event listener. // Host event listener.
// TODO: Superceded by UiSharedTopologyModel.ModelEventListener
@Deprecated
private class InternalHostListener implements HostListener { private class InternalHostListener implements HostListener {
@Override @Override
public void event(HostEvent event) { public void event(HostEvent event) {
@ -768,6 +778,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
} }
// Intent event listener. // Intent event listener.
// TODO: Superceded by UiSharedTopologyModel.ModelEventListener
@Deprecated
private class InternalIntentListener implements IntentListener { private class InternalIntentListener implements IntentListener {
@Override @Override
public void event(IntentEvent event) { public void event(IntentEvent event) {
@ -777,6 +789,8 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
} }
// Intent event listener. // Intent event listener.
// TODO: Superceded by UiSharedTopologyModel.ModelEventListener
@Deprecated
private class InternalFlowListener implements FlowRuleListener { private class InternalFlowListener implements FlowRuleListener {
@Override @Override
public void event(FlowRuleEvent event) { public void event(FlowRuleEvent event) {

View File

@ -28,6 +28,7 @@ import org.onosproject.ui.UiExtensionService;
import org.onosproject.ui.UiMessageHandlerFactory; import org.onosproject.ui.UiMessageHandlerFactory;
import org.onosproject.ui.UiMessageHandler; import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.UiTopoOverlayFactory; import org.onosproject.ui.UiTopoOverlayFactory;
import org.onosproject.ui.impl.topo.UiTopoSession;
import org.onosproject.ui.topo.TopoConstants; import org.onosproject.ui.topo.TopoConstants;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -37,7 +38,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* Web socket capable of interacting with the GUI. * Web socket capable of interacting with the Web UI.
*/ */
public class UiWebSocket public class UiWebSocket
implements UiConnection, WebSocket.OnTextMessage, WebSocket.OnControl { implements UiConnection, WebSocket.OnTextMessage, WebSocket.OnControl {
@ -50,14 +51,14 @@ public class UiWebSocket
private static final byte PONG = 0xA; private static final byte PONG = 0xA;
private static final byte[] PING_DATA = new byte[]{(byte) 0xde, (byte) 0xad}; private static final byte[] PING_DATA = new byte[]{(byte) 0xde, (byte) 0xad};
private final ObjectMapper mapper = new ObjectMapper();
private final ServiceDirectory directory; private final ServiceDirectory directory;
private final UiTopoSession topoSession;
private Connection connection; private Connection connection;
private FrameConnection control; private FrameConnection control;
private String userName; private String userName;
private final ObjectMapper mapper = new ObjectMapper();
private long lastActive = System.currentTimeMillis(); private long lastActive = System.currentTimeMillis();
private Map<String, UiMessageHandler> handlers; private Map<String, UiMessageHandler> handlers;
@ -72,6 +73,7 @@ public class UiWebSocket
public UiWebSocket(ServiceDirectory directory, String userName) { public UiWebSocket(ServiceDirectory directory, String userName) {
this.directory = directory; this.directory = directory;
this.userName = userName; this.userName = userName;
this.topoSession = new UiTopoSession(this);
} }
@Override @Override
@ -115,6 +117,7 @@ public class UiWebSocket
this.connection = connection; this.connection = connection;
this.control = (FrameConnection) connection; this.control = (FrameConnection) connection;
try { try {
topoSession.init();
createHandlersAndOverlays(); createHandlersAndOverlays();
sendInstanceData(); sendInstanceData();
log.info("GUI client connected"); log.info("GUI client connected");
@ -129,6 +132,7 @@ public class UiWebSocket
@Override @Override
public synchronized void onClose(int closeCode, String message) { public synchronized void onClose(int closeCode, String message) {
topoSession.destroy();
destroyHandlersAndOverlays(); destroyHandlersAndOverlays();
log.info("GUI client disconnected [close-code={}, message={}]", log.info("GUI client disconnected [close-code={}, message={}]",
closeCode, message); closeCode, message);

View File

@ -36,31 +36,33 @@ import org.slf4j.LoggerFactory;
public class UiTopoSession { public class UiTopoSession {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private final String username;
private final UiWebSocket webSocket; private final UiWebSocket webSocket;
private final UiSharedTopologyModel sharedModel; private final String username;
final UiSharedTopologyModel sharedModel;
private boolean registered = false; private boolean registered = false;
private UiTopoLayoutService service; private UiTopoLayoutService service;
private UiTopoLayout layout; private UiTopoLayout currentLayout;
/** /**
* Creates a new topology layout. * Creates a new topology session for the specified web socket connection.
* @param username user name *
* @param webSocket web socket * @param webSocket web socket
*/ */
public UiTopoSession(String username, UiWebSocket webSocket) { public UiTopoSession(UiWebSocket webSocket) {
this.username = username;
this.webSocket = webSocket; this.webSocket = webSocket;
this.username = webSocket.userName();
this.sharedModel = UiSharedTopologyModel.instance(); this.sharedModel = UiSharedTopologyModel.instance();
} }
/** /**
* Initializes the layout; registering with the shared model. * Initializes the session; registering with the shared model.
*/ */
public void init() { public void init() {
if (!registered) { if (!registered) {
log.debug("{} : Registering with shared model", this);
sharedModel.register(this); sharedModel.register(this);
registered = true; registered = true;
} else { } else {
@ -69,10 +71,11 @@ public class UiTopoSession {
} }
/** /**
* Destroys the layout; unregistering from the shared model. * Destroys the session; unregistering from the shared model.
*/ */
public void destroy() { public void destroy() {
if (!registered) { if (registered) {
log.debug("{} : Unregistering from shared model", this);
sharedModel.unregister(this); sharedModel.unregister(this);
registered = false; registered = false;
} else { } else {

View File

@ -16,10 +16,43 @@
package org.onosproject.ui.impl.topo.model; package org.onosproject.ui.impl.topo.model;
import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ClusterEventListener;
import org.onosproject.cluster.ClusterService;
import org.onosproject.incubator.net.PortStatisticsService;
import org.onosproject.incubator.net.tunnel.TunnelService;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.link.LinkEvent;
import org.onosproject.net.link.LinkListener;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.region.RegionEvent;
import org.onosproject.net.region.RegionListener;
import org.onosproject.net.region.RegionService;
import org.onosproject.net.statistic.StatisticService;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.ui.impl.topo.UiTopoSession; import org.onosproject.ui.impl.topo.UiTopoSession;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.HashSet;
import java.util.Set;
/** /**
* A lazily-initialized Singleton that creates and maintains the UI-model * A lazily-initialized Singleton that creates and maintains the UI-model
* of the network topology. * of the network topology.
@ -29,16 +62,18 @@ public final class UiSharedTopologyModel {
private static final Logger log = private static final Logger log =
LoggerFactory.getLogger(UiSharedTopologyModel.class); LoggerFactory.getLogger(UiSharedTopologyModel.class);
private final ModelEventListener modelEventListener;
private final Set<UiTopoSession> sessions = new HashSet<>();
private UiSharedTopologyModel() { private UiSharedTopologyModel() {
// TODO: set up core model listeners and build the state of the model modelEventListener = new ModelEventListener().init();
// TODO: build and maintain the state of the model
// (1) query model for current state
// (2) update state as model events arrive
} }
// TODO: Note to Thomas (or others)..
// Don't we have a common pattern for adding/removing listeners and
// invoking them when things happen?
/** /**
* Registers a UI topology session with the topology model. * Registers a UI topology session with the topology model.
* *
@ -46,7 +81,7 @@ public final class UiSharedTopologyModel {
*/ */
public void register(UiTopoSession session) { public void register(UiTopoSession session) {
log.info("Registering topology session {}", session); log.info("Registering topology session {}", session);
// TODO: register the session sessions.add(session);
} }
/** /**
@ -56,9 +91,123 @@ public final class UiSharedTopologyModel {
*/ */
public void unregister(UiTopoSession session) { public void unregister(UiTopoSession session) {
log.info("Unregistering topology session {}", session); log.info("Unregistering topology session {}", session);
// TODO: unregister the session sessions.remove(session);
} }
// TODO: notify registered sessions when changes happen to the model
// ----------
// inner class to encapsulate the model listeners
private final class ModelEventListener {
// TODO: Review - is this good enough? couldn't otherwise see how to inject
private final ServiceDirectory directory = new DefaultServiceDirectory();
private ClusterService clusterService;
private MastershipService mastershipService;
private RegionService regionService;
private DeviceService deviceService;
private LinkService linkService;
private HostService hostService;
private IntentService intentService;
private FlowRuleService flowService;
private StatisticService flowStatsService;
private PortStatisticsService portStatsService;
private TopologyService topologyService;
private TunnelService tunnelService;
private ModelEventListener init() {
clusterService = directory.get(ClusterService.class);
mastershipService = directory.get(MastershipService.class);
regionService = directory.get(RegionService.class);
deviceService = directory.get(DeviceService.class);
linkService = directory.get(LinkService.class);
hostService = directory.get(HostService.class);
intentService = directory.get(IntentService.class);
flowService = directory.get(FlowRuleService.class);
// passive services (?) to whom we are not listening...
flowStatsService = directory.get(StatisticService.class);
portStatsService = directory.get(PortStatisticsService.class);
topologyService = directory.get(TopologyService.class);
tunnelService = directory.get(TunnelService.class);
return this;
}
private class InternalClusterListener implements ClusterEventListener {
@Override
public void event(ClusterEvent event) {
// TODO: handle cluster event
// (1) emit cluster member event
}
}
private class InternalMastershipListener implements MastershipListener {
@Override
public void event(MastershipEvent event) {
// TODO: handle mastership event
// (1) emit cluster member update for all members
// (2) emit update device event for he whose mastership changed
}
}
private class InternalRegionListener implements RegionListener {
@Override
public void event(RegionEvent event) {
// TODO: handle region event
// (1) emit region event
}
}
private class InternalDeviceListener implements DeviceListener {
@Override
public void event(DeviceEvent event) {
// TODO: handle device event
// (1) emit device event
}
}
private class InternalLinkListener implements LinkListener {
@Override
public void event(LinkEvent event) {
// TODO: handle link event
// (1) consolidate infrastructure links -> UiLink (?)
// (2) emit link event
}
}
private class InternalHostListener implements HostListener {
@Override
public void event(HostEvent event) {
// TODO: handle host event
// (1) emit host event
}
}
private class InternalIntentListener implements IntentListener {
@Override
public void event(IntentEvent event) {
// TODO: handle intent event
// (1) update cache of intent counts?
}
}
private class InternalFlowRuleListener implements FlowRuleListener {
@Override
public void event(FlowRuleEvent event) {
// TODO: handle flowrule event
// (1) update cache of flow counts?
}
}
}
// ----------
/** /**
* Bill Pugh Singleton pattern. INSTANCE won't be instantiated until the * Bill Pugh Singleton pattern. INSTANCE won't be instantiated until the
* LazyHolder class is loaded via a call to the instance() method below. * LazyHolder class is loaded via a call to the instance() method below.