Java tutorial
/* * Copyright 2014 Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.sse; import com.google.common.collect.Lists; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import org.eclipse.jetty.websocket.WebSocket; import org.onosproject.cluster.ClusterEvent; import org.onosproject.cluster.ClusterEventListener; import org.onosproject.cluster.ControllerNode; import org.onosproject.core.ApplicationId; import org.onosproject.core.CoreService; //import org.onosproject.event.AbstractEventAccumulator; import org.onosproject.event.Event; //import org.onosproject.event.EventAccumulator; import org.onosproject.mastership.MastershipAdminService; import org.onosproject.mastership.MastershipEvent; import org.onosproject.mastership.MastershipListener; import org.onosproject.net.ConnectPoint; import org.onosproject.net.Device; import org.onosproject.net.Host; import org.onosproject.net.HostId; import org.onosproject.net.HostLocation; import org.onosproject.net.Link; import org.onosproject.net.device.DeviceEvent; import org.onosproject.net.device.DeviceListener; import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.FlowRuleEvent; import org.onosproject.net.flow.FlowRuleListener; import org.onosproject.net.flow.TrafficSelector; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.host.HostEvent; import org.onosproject.net.host.HostListener; import org.onosproject.net.intent.MultiPointToSinglePointIntent; import org.onosproject.net.intent.HostToHostIntent; import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.IntentEvent; import org.onosproject.net.intent.IntentListener; //import org.onosproject.net.intent.IntentOperations; import org.onosproject.net.intent.IntentService; import org.onosproject.net.intent.IntentState; import org.onosproject.net.intent.OpticalConnectivityIntent; import org.onosproject.net.intent.OpticalPathIntent; import org.onosproject.net.link.LinkEvent; import org.onosproject.net.link.LinkListener; import org.onosproject.net.topology.LinkWeight; import org.onosproject.net.topology.PathService; import org.onosproject.net.topology.TopologyEdge; import org.onosproject.net.Path; import org.onosproject.net.resource.link.LambdaResource; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ExecutionException; import java.lang.InterruptedException; //import org.onosproject.sse.SseOpticalPathHandler;//hlk import org.onlab.osgi.ServiceDirectory; import org.onlab.util.AbstractAccumulator; import org.onlab.util.Accumulator; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import static com.google.common.base.Strings.isNullOrEmpty; import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED; import static org.onosproject.net.DeviceId.deviceId; import static org.onosproject.net.HostId.hostId; import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED; import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_UPDATED; import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED; import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; /** * Web socket capable of interacting with the GUI topology view. */ public class SseTopologyViewWebSocket extends SseTopologyViewMessages implements WebSocket.OnTextMessage, WebSocket.OnControl { private static final long MAX_AGE_MS = 15000; private static final byte PING = 0x9; private static final byte PONG = 0xA; private static final byte[] PING_DATA = new byte[] { (byte) 0xde, (byte) 0xad }; private static final String APP_ID = "org.onosproject.sse"; private static final long TRAFFIC_FREQUENCY = 5000; private static final long SUMMARY_FREQUENCY = 30000; private static final Comparator<? super ControllerNode> NODE_COMPARATOR = new Comparator<ControllerNode>() { @Override public int compare(ControllerNode o1, ControllerNode o2) { return o1.id().toString().compareTo(o2.id().toString()); } }; private final Timer timer = new Timer("topology-view"); private static final int MAX_EVENTS = 1000; private static final int MAX_BATCH_MS = 5000; private static final int MAX_IDLE_MS = 1000; private final ApplicationId appId; private Connection connection; private FrameConnection control; private final ClusterEventListener clusterListener = new InternalClusterListener(); private final MastershipListener mastershipListener = new InternalMastershipListener(); private final DeviceListener deviceListener = new InternalDeviceListener(); private final LinkListener linkListener = new InternalLinkListener(); private final HostListener hostListener = new InternalHostListener(); private final IntentListener intentListener = new InternalIntentListener(); private final FlowRuleListener flowListener = new InternalFlowListener(); protected static SseGUIMessageHandler sseGUIMessageHandler;//hlk private final Accumulator<Event> eventAccummulator = new InternalEventAccummulator(); protected final Map<ConnectPoint, OpticalConnectivityIntent> inStatusTportMap = new ConcurrentHashMap<>(); protected final Map<ConnectPoint, OpticalConnectivityIntent> outStatusTportMap = new ConcurrentHashMap<>(); protected final Map<ConnectPoint, Map<ConnectPoint, Intent>> intentMap = new ConcurrentHashMap<>(); private TimerTask trafficTask; private ObjectNode trafficEvent; private TimerTask summaryTask; private ObjectNode summaryEvent; private long lastActive = System.currentTimeMillis(); private boolean listenersRemoved = false; private SseTopologyViewIntentFilter intentFilter; private ScheduledExecutorService executorService;// added by yby //private SseBatchServiceProvider provider = new SseBatchServiceProvider();//added by hlk // Current selection context private Set<Host> selectedHosts; private Set<Device> selectedDevices; private List<Intent> selectedIntents; private int currentIntentIndex = -1; /** * Creates a new web-socket for serving data to GUI topology view. * * @param directory service directory */ public SseTopologyViewWebSocket(ServiceDirectory directory, ScheduledExecutorService executorService) { super(directory); this.executorService = executorService; intentFilter = new SseTopologyViewIntentFilter(intentService, deviceService, hostService, linkService); appId = directory.get(CoreService.class).registerApplication(APP_ID); sseGUIMessageHandler = new SseGUIMessageHandler(directory, executorService, this); } /** * Issues a close on the connection. */ synchronized void close() { removeListeners(); if (connection.isOpen()) { connection.close(); } } /** * Indicates if this connection is idle. * * @return true if idle or closed */ synchronized boolean isIdle() { boolean idle = (System.currentTimeMillis() - lastActive) > MAX_AGE_MS; if (idle || !connection.isOpen()) { return true; } try { control.sendControl(PING, PING_DATA, 0, PING_DATA.length); } catch (IOException e) { log.warn("Unable to send ping message due to: ", e); } return false; } @Override public void onOpen(Connection connection) { log.info("SSE GUI client connected"); this.connection = connection; this.control = (FrameConnection) connection; addListeners(); sendAllInstances(null); sendAllDevices(); sendAllLinks(); sendAllHosts(); SseInventory.setWebsocket(this); //sendAllLambdas();//send all links lambdas } @Override public synchronized void onClose(int closeCode, String message) { removeListeners(); timer.cancel(); log.info("SSE GUI client disconnected"); } @Override public boolean onControl(byte controlCode, byte[] data, int offset, int length) { lastActive = System.currentTimeMillis(); return true; } @Override public void onMessage(String data) { lastActive = System.currentTimeMillis(); try { processMessage((ObjectNode) mapper.reader().readTree(data)); //log.info("HLKSSE event is {}", (ObjectNode) mapper.reader().readTree(data)); } catch (Exception e) { //e.printStackTrace(); log.warn("Unable to parse GUI request {} due to {}", data, e.getStackTrace()); log.debug("Boom!!!", e); } } // Processes the specified event. private void processMessage(ObjectNode event) { String type = string(event, "event", "unknown"); log.info("Request type is {}", type); if (type.equals("requestDetails")) { requestDetails(event); } else if (type.equals("updateMeta")) { updateMetaUi(event); } /*else if (type.equals("addHostIntent")) { createHostIntent(event); } else if (type.equals("addMultiSourceIntent")) { createMultiSourceIntent(event); } */else if (type.equals("requestRelatedIntents")) { stopTrafficMonitoring(); requestRelatedIntents(event); } else if (type.equals("requestNextRelatedIntent")) { stopTrafficMonitoring(); requestAnotherRelatedIntent(event, +1); } else if (type.equals("requestPrevRelatedIntent")) { stopTrafficMonitoring(); requestAnotherRelatedIntent(event, -1); } else if (type.equals("requestSelectedIntentTraffic")) { requestSelectedIntentTraffic(event); startTrafficMonitoring(event); } else if (type.equals("requestAllTraffic")) { requestAllTraffic(event); startTrafficMonitoring(event); } else if (type.equals("requestDeviceLinkFlows")) { requestDeviceLinkFlows(event); startTrafficMonitoring(event); } else if (type.equals("cancelTraffic")) { cancelTraffic(event); } else if (type.equals("requestSummary")) { requestSummary(event); startSummaryMonitoring(event); } else if (type.equals("cancelSummary")) { stopSummaryMonitoring(); } else if (type.equals("equalizeMasters")) { equalizeMasters(event); } else if (type.equals("addOpticalPathIntent")) { log.info("HLK process addOpticalPath"); createOpticalPathIntent(event); } else if (type.equals("delCurrentService")) { //log.info("HLK delete currentOpticalPath"); deleteCurrentService(event); } else if (type.equals("cancelScheduledService")) { //log.info("HLK cancel Scheduled Service in local Map"); cancelScheduledService(event);//hlk will change the payload } else if (type.equals("scheduledServiceQuery")) { //log.info("HLK GUI scheduled service query"); queryScheduledService(event); } else if (type.equals("currentServiceQuery")) { //log.info("HLK GUI current service query"); queryCurrentService(event); } else if (type.equals("sendBaseTime")) { //log.info("HLK get BaseTime"); initBaseTime(event); } else if (type.equals("showPreview")) { //log.info("HLK GUI showPreview"); showOverallPreview(event); } else if (type.equals("showLinkDetailInit")) { //log.info("HLK GUI showLinkDetailInit"); showLinkDetailInitial(event); } else if (type.equals("ServiceReschedule")) { //log.info("HLK GUI ServiceReschedule"); reScheduleService(event); } } //---------------------------------------create optical path private void createOpticalPathIntent(ObjectNode event) { long sid = number(event, "sid"); //ObjectNode pathReservationResult = mapper.createObjectNode(); log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%method"); Intent intent = sseGUIMessageHandler.sseOpticalPathHandler(event); if (intent != null) { startMonitoringIntent(event, intent);//hlk 5.21 } else { } showOverallPreview(event); //TO DO, send a confirm message to GUI. } //*******************cancel current and scheduled service******************** private void deleteCurrentService(ObjectNode event) { ObjectNode payload = payload(event); long sid = number(event, "sid"); int serviceId = Integer.parseInt(string(payload, "serviceid"));//hlk to define serviceId in json //First REMOVE THE INTENT FROM THE TIME QUEUE OF YBY sseGUIMessageHandler.sseDeleteCurrentService(event);//remove intent sendMessage(deleteMessage("delCurrentService", sid, serviceId)); sendStateMessage("Current Service Delete!", serviceId); } private void cancelScheduledService(ObjectNode event) { ObjectNode payload = payload(event); long sid = number(event, "sid"); int serviceId = Integer.parseInt(string(payload, "serviceid")); // to cancel a scheduled service. 3 Three steps // first. DELETE IT From The TIME QUEUE Of YBY sseGUIMessageHandler.sseDeleteScheduledService(event); // second. release the lambda resource in local resourceMap sendMessage(deleteMessage("cancelScheduledService", sid, serviceId)); sendStateMessage("Scheduled Service Delete!", serviceId); } //*******************Query current and scheduled service************************************************ private void queryScheduledService(ObjectNode event) { ObjectNode payload = payload(event); long sid = number(payload, "sid"); //log.info("5.22----scheduledNum is {}", (SseInventory.scheduledForwardServices).size()); for (Map.Entry<Integer, SseOpticalPathParameter> serviceEntry : SseInventory.scheduledForwardServices .entrySet()) { sendMessage(queryServiceMessage("scheduledServiceQuery", sid, serviceEntry.getValue())); } } private void queryCurrentService(ObjectNode event) { ObjectNode payload = payload(event); long sid = number(payload, "sid"); //log.info("5.22----got sid & payload"); //int serviceNo = (SseInventory.currentServicesPara).size(); for (Map.Entry<Integer, SseOpticalPathParameter> serviceEntry : SseInventory.currentForwardServices .entrySet()) { sendMessage(queryServiceMessage("currentServiceQuery", sid, serviceEntry.getValue())); } } private void showOverallPreview(ObjectNode event) { //show overall preview //log.info("5.26 into showOverallPreview"); long sid = number(event, "sid"); //log.info("before reforming method"); SseInventory.reformingTimeLinkResource();//reform Map<Link, Map<Integer, Integer>> map = SseInventory.reformedTimeLinkResource; for (Map.Entry<Link, Map<Integer, Integer>> linkEntry : map.entrySet()) { sendMessage(showPreviewMessage("showPreview", sid, linkEntry.getKey(), linkEntry.getValue())); } } private void showLinkDetailInitial(ObjectNode event) { long sid = number(event, "sid"); ObjectNode payload = payload(event); String linkString = string(payload, "link"); SseInventory.linkMark = linkString; SseInventory.reformingTimeLinkServiceResource(); if (linkString != "") { for (Map.Entry<Link, Map<Integer, Map<Integer, Set<LambdaResource>>>> entry1 : SseInventory.reformedTimeLinkServiceResource .entrySet()) { // log.info("6.8----into"); if (compactLinkString(entry1.getKey()).equals(linkString)) { for (Map.Entry<Integer, Map<Integer, Set<LambdaResource>>> entry2 : entry1.getValue() .entrySet()) { int timeItem = entry2.getKey(); if (timeItem > 40) { break; } ObjectNode returnPayload = mapper.createObjectNode(); ArrayNode services = mapper.createArrayNode(); returnPayload.put("link", linkString); returnPayload.put("time", String.valueOf(timeItem)); for (Map.Entry<Integer, Set<LambdaResource>> entry3 : entry2.getValue().entrySet()) { ObjectNode service = mapper.createObjectNode(); ArrayNode lambdas = mapper.createArrayNode(); service.put("id", String.valueOf(entry3.getKey())); for (LambdaResource lambdaItem : entry3.getValue()) { ObjectNode lambda = mapper.createObjectNode(); lambda.put("lambda", String.valueOf(lambdaItem.toInt())); lambdas.add(lambda); } service.put("lambdas", lambdas); services.add(service); } returnPayload.put("services", services); ObjectNode sendBack = envelope("showLinkDetailInit", sid, returnPayload); //log.info("6.7--HLK--payload2 {}",returnPayload); sendMessage(sendBack); } } else { continue; } } } } private void reScheduleService(ObjectNode event) { long sid = number(event, "sid"); ObjectNode payload = payload(event); //String viewType=string("viewType",payload); String linkString = string(payload, "link"); try { sseGUIMessageHandler.reSchedule(); } catch (Exception e) { //log.error("6.10 &&&&&&&&&&&&&&&&&&& reschedule error"); } // //Map<Link, Map<Long, Integer>> map = SseInventory.reformedTimeLinkResource; if (linkString != "") { showLinkDetailInitial(event); } else { SseInventory.reformingTimeLinkResource();//reform Map<Link, Map<Integer, Integer>> map = SseInventory.reformedTimeLinkResource; for (Map.Entry<Link, Map<Integer, Integer>> linkEntry : map.entrySet()) { sendMessage(showPreviewMessage("showPreview", sid, linkEntry.getKey(), linkEntry.getValue())); } } //sendMessage(showLinkDetailInitialMessage(sid, linkString)); } protected void initBaseTime(ObjectNode event) { ObjectNode payload = payload(event); sseGUIMessageHandler.baseTimeReset(event); } //---------------------local method------------------------------------- //hlk 5.26 call back state message to GUI public void sendStateMessage(String string, int serviceId) { ObjectNode message = mapper.createObjectNode(); ObjectNode payload = mapper.createObjectNode(); payload.put("State", string); message = envelope("processStateMessage", 404L, payload); sendMessage(message); } //hlk when build a real light path, callback a message to GUI about that path right now! public void sendPathResultMessage(ObjectNode data) { //long sid = number(data, "sid"); sendMessage(data); } //Sends the specified data to the client. protected synchronized void sendMessage(ObjectNode data) { try { if (connection.isOpen()) { connection.sendMessage(data.toString()); //log.info("HLK SSE sendMessage run! data is {}",data.toString()); } } catch (IOException e) { log.warn("Unable to send message {} to GUI due to {}", data, e); log.debug("Boom!!!", e); } } // Sends all controller nodes to the client as node-added messages. private void sendAllInstances(String messageType) { List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes()); Collections.sort(nodes, NODE_COMPARATOR); for (ControllerNode node : nodes) { sendMessage(instanceMessage(new ClusterEvent(INSTANCE_ADDED, node), messageType)); } } // Sends all devices to the client as device-added messages. private void sendAllDevices() { // Send optical first, others later for layered rendering for (Device device : deviceService.getDevices()) { if (device.type() == Device.Type.ROADM) { sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device))); } } for (Device device : deviceService.getDevices()) { if (device.type() != Device.Type.ROADM) { sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device))); } } } // Sends all links to the client as link-added messages. private void sendAllLinks() { // Send optical first, others later for layered rendering for (Link link : linkService.getLinks()) { if (link.type() == Link.Type.OPTICAL) { sendMessage(linkMessage(new LinkEvent(LINK_ADDED, link))); //log.info("5.24 ******************Optical LINK {}", link); } } for (Link link : linkService.getLinks()) { if (link.type() != Link.Type.OPTICAL) { sendMessage(linkMessage(new LinkEvent(LINK_ADDED, link))); } } } // Sends all hosts to the client as host-added messages. private void sendAllHosts() { for (Host host : hostService.getHosts()) { sendMessage(hostMessage(new HostEvent(HOST_ADDED, host))); } } // Sends back device or host details. private void requestDetails(ObjectNode event) { ObjectNode payload = payload(event); String type = string(payload, "class", "unknown"); long sid = number(event, "sid"); if (type.equals("device")) { sendMessage(deviceDetails(deviceId(string(payload, "id")), sid)); } else if (type.equals("host")) { sendMessage(hostDetails(hostId(string(payload, "id")), sid)); } } // Creates host-to-host intent. /*private void createHostIntent(ObjectNode event) { ObjectNode payload = payload(event); long id = number(event, "sid"); // TODO: add protection against device ids and non-existent hosts. HostId one = hostId(string(payload, "one")); HostId two = hostId(string(payload, "two")); HostToHostIntent intent = new HostToHostIntent(appId, one, two, DefaultTrafficSelector.builder().build(), DefaultTrafficTreatment.builder().build()); intentService.submit(intent); startMonitoringIntent(event, intent); //log.info("HLKSSE createHostIntent: {} & startMonitor", intent); } //Creates multi-source-to-single-dest intent. private void createMultiSourceIntent(ObjectNode event) { ObjectNode payload = payload(event); long id = number(event, "sid"); // TODO: add protection against device ids and non-existent hosts. Set<HostId> src = getHostIds((ArrayNode) payload.path("src")); HostId dst = hostId(string(payload, "dst")); Host dstHost = hostService.getHost(dst); Set<ConnectPoint> ingressPoints = getHostLocations(src); // FIXME: clearly, this is not enough TrafficSelector selector = DefaultTrafficSelector.builder() .matchEthDst(dstHost.mac()).build(); TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); MultiPointToSinglePointIntent intent = new MultiPointToSinglePointIntent(appId, selector, treatment, ingressPoints, dstHost.location()); intentService.submit(intent); startMonitoringIntent(event, intent); }*/ private synchronized void startMonitoringIntent(ObjectNode event, Intent intent) { selectedHosts = new HashSet<>(); selectedDevices = new HashSet<>(); selectedIntents = new ArrayList<>(); selectedIntents.add(intent); currentIntentIndex = -1; requestAnotherRelatedIntent(event, +1); requestSelectedIntentTraffic(event); } private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) { Set<ConnectPoint> points = new HashSet<>(); for (HostId hostId : hostIds) { points.add(getHostLocation(hostId)); } return points; } private HostLocation getHostLocation(HostId hostId) { return hostService.getHost(hostId).location(); } // Produces a list of host ids from the specified JSON array. private Set<HostId> getHostIds(ArrayNode ids) { Set<HostId> hostIds = new HashSet<>(); for (JsonNode id : ids) { hostIds.add(hostId(id.asText())); } return hostIds; } private synchronized long startTrafficMonitoring(ObjectNode event) { stopTrafficMonitoring(); trafficEvent = event; trafficTask = new TrafficMonitor(); timer.schedule(trafficTask, TRAFFIC_FREQUENCY, TRAFFIC_FREQUENCY); return number(event, "sid"); } private synchronized void stopTrafficMonitoring() { if (trafficTask != null) { trafficTask.cancel(); trafficTask = null; trafficEvent = null; } } // Subscribes for host traffic messages. private synchronized void requestAllTraffic(ObjectNode event) { long sid = startTrafficMonitoring(event); sendMessage(trafficSummaryMessage(sid)); } private void requestDeviceLinkFlows(ObjectNode event) { ObjectNode payload = payload(event); long sid = startTrafficMonitoring(event); // Get the set of selected hosts and their intents. ArrayNode ids = (ArrayNode) payload.path("ids"); Set<Host> hosts = new HashSet<>(); Set<Device> devices = getDevices(ids); // If there is a hover node, include it in the hosts and find intents. String hover = string(payload, "hover"); if (!isNullOrEmpty(hover)) { addHover(hosts, devices, hover); } sendMessage(flowSummaryMessage(sid, devices)); } // Requests related intents message. private synchronized void requestRelatedIntents(ObjectNode event) { ObjectNode payload = payload(event); if (!payload.has("ids")) { return; } long sid = number(event, "sid"); // Cancel any other traffic monitoring mode. stopTrafficMonitoring(); // Get the set of selected hosts and their intents. ArrayNode ids = (ArrayNode) payload.path("ids"); selectedHosts = getHosts(ids); selectedDevices = getDevices(ids); selectedIntents = intentFilter.findPathIntents(selectedHosts, selectedDevices, intentService.getIntents()); currentIntentIndex = -1; if (haveSelectedIntents()) { // Send a message to highlight all links of all monitored intents. sendMessage(trafficMessage(sid, new TrafficClass("primary", selectedIntents))); } // FIXME: Re-introduce one the client click vs hover gesture stuff is sorted out. // String hover = string(payload, "hover"); // if (!isNullOrEmpty(hover)) { // // If there is a hover node, include it in the selection and find intents. // processHoverExtendedSelection(sid, hover); // } } private boolean haveSelectedIntents() { return selectedIntents != null && !selectedIntents.isEmpty(); } // Processes the selection extended with hovered item to segregate items // into primary (those including the hover) vs secondary highlights. private void processHoverExtendedSelection(long sid, String hover) { Set<Host> hoverSelHosts = new HashSet<>(selectedHosts); Set<Device> hoverSelDevices = new HashSet<>(selectedDevices); addHover(hoverSelHosts, hoverSelDevices, hover); List<Intent> primary = selectedIntents == null ? new ArrayList<>() : intentFilter.findPathIntents(hoverSelHosts, hoverSelDevices, selectedIntents); Set<Intent> secondary = new HashSet<>(selectedIntents); secondary.removeAll(primary); // Send a message to highlight all links of all monitored intents. sendMessage(trafficMessage(sid, new TrafficClass("primary", primary), new TrafficClass("secondary", secondary))); } // Requests next or previous related intent. private void requestAnotherRelatedIntent(ObjectNode event, int offset) { if (haveSelectedIntents()) { currentIntentIndex = currentIntentIndex + offset; if (currentIntentIndex < 0) { currentIntentIndex = selectedIntents.size() - 1; } else if (currentIntentIndex >= selectedIntents.size()) { currentIntentIndex = 0; } sendSelectedIntent(event); } } // Sends traffic information on the related intents with the currently // selected intent highlighted. private void sendSelectedIntent(ObjectNode event) { Intent selectedIntent = selectedIntents.get(currentIntentIndex); log.info("Requested next intent {} ", selectedIntent.id()); Set<Intent> primary = new HashSet<>(); primary.add(selectedIntent); Set<Intent> secondary = new HashSet<>(selectedIntents); secondary.remove(selectedIntent); // Send a message to highlight all links of the selected intent. sendMessage(trafficMessage(number(event, "sid"), new TrafficClass("primary", primary), new TrafficClass("secondary", secondary))); } // Requests monitoring of traffic for the selected intent. private void requestSelectedIntentTraffic(ObjectNode event) { if (haveSelectedIntents()) { if (currentIntentIndex < 0) { currentIntentIndex = 0; } Intent selectedIntent = selectedIntents.get(currentIntentIndex); log.info("Requested traffic for selected {} ", selectedIntent.id()); Set<Intent> primary = new HashSet<>(); primary.add(selectedIntent); // Send a message to highlight all links of the selected intent. sendMessage(trafficMessage(number(event, "sid"), new TrafficClass("primary", primary, true))); } } // Cancels sending traffic messages. private void cancelTraffic(ObjectNode event) { selectedIntents = null; sendMessage(trafficMessage(number(event, "sid"))); stopTrafficMonitoring(); } private synchronized long startSummaryMonitoring(ObjectNode event) { stopSummaryMonitoring(); summaryEvent = event; summaryTask = new SummaryMonitor(); timer.schedule(summaryTask, SUMMARY_FREQUENCY, SUMMARY_FREQUENCY); return number(event, "sid"); } private synchronized void stopSummaryMonitoring() { if (summaryEvent != null) { summaryTask.cancel(); summaryTask = null; summaryEvent = null; } } // Subscribes for summary messages. private synchronized void requestSummary(ObjectNode event) { sendMessage(summmaryMessage(number(event, "sid"))); } // Forces mastership role rebalancing. private void equalizeMasters(ObjectNode event) { directory.get(MastershipAdminService.class).balanceRoles(); } // Adds all internal listeners. private void addListeners() { clusterService.addListener(clusterListener); mastershipService.addListener(mastershipListener); deviceService.addListener(deviceListener); linkService.addListener(linkListener); hostService.addListener(hostListener); intentService.addListener(intentListener); flowService.addListener(flowListener); } // Removes all internal listeners. private synchronized void removeListeners() { if (!listenersRemoved) { listenersRemoved = true; clusterService.removeListener(clusterListener); mastershipService.removeListener(mastershipListener); deviceService.removeListener(deviceListener); linkService.removeListener(linkListener); hostService.removeListener(hostListener); intentService.removeListener(intentListener); flowService.removeListener(flowListener); } } // Cluster event listener. private class InternalClusterListener implements ClusterEventListener { @Override public void event(ClusterEvent event) { sendMessage(instanceMessage(event, null)); } } // Mastership change listener private class InternalMastershipListener implements MastershipListener { @Override public void event(MastershipEvent event) { sendAllInstances("updateInstance"); Device device = deviceService.getDevice(event.subject()); sendMessage(deviceMessage(new DeviceEvent(DEVICE_UPDATED, device))); } } // Device event listener. private class InternalDeviceListener implements DeviceListener { @Override public void event(DeviceEvent event) { sendMessage(deviceMessage(event)); eventAccummulator.add(event); } } // Link event listener. private class InternalLinkListener implements LinkListener { @Override public void event(LinkEvent event) { sendMessage(linkMessage(event)); eventAccummulator.add(event); } } // Host event listener. private class InternalHostListener implements HostListener { @Override public void event(HostEvent event) { sendMessage(hostMessage(event)); eventAccummulator.add(event); } } //weiw // Intent event listener. private class InternalIntentListener implements IntentListener { @Override public void event(IntentEvent event) { if (trafficEvent != null) { requestSelectedIntentTraffic(trafficEvent); } eventAccummulator.add(event); } } // Intent event listener. private class InternalFlowListener implements FlowRuleListener { @Override public void event(FlowRuleEvent event) { eventAccummulator.add(event); } } // Periodic update of the traffic information private class TrafficMonitor extends TimerTask { @Override public void run() { try { if (trafficEvent != null) { String type = string(trafficEvent, "event", "unknown"); if (type.equals("requestAllTraffic")) { requestAllTraffic(trafficEvent); } else if (type.equals("requestDeviceLinkFlows")) { requestDeviceLinkFlows(trafficEvent); } else if (type.equals("requestSelectedIntentTraffic")) { requestSelectedIntentTraffic(trafficEvent); } } } catch (Exception e) { log.warn("Unable to handle traffic request due to {}", e.getMessage()); log.debug("Boom!", e); } } } // Periodic update of the summary information private class SummaryMonitor extends TimerTask { @Override public void run() { try { if (summaryEvent != null) { requestSummary(summaryEvent); } } catch (Exception e) { log.warn("Unable to handle summary request due to {}", e.getMessage()); log.debug("Boom!", e); } } } // Accumulates events to drive methodic update of the summary pane. private class InternalEventAccummulator extends AbstractAccumulator<Event> { protected InternalEventAccummulator() { super(new Timer("topo-summary"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS); } @Override public void processItems(List<Event> events) { try { if (summaryEvent != null) { sendMessage(summmaryMessage(0)); } } catch (Exception e) { log.warn("Unable to handle summary request due to {}", e.getMessage()); log.debug("Boom!", e); } } } }