blob: 8ba8d3aeed43aeb7c9710717844d884703b20fb5 [file] [log] [blame]
Thomas Vachuska329af532015-03-10 02:08:33 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.ui.impl;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ArrayNode;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import com.google.common.collect.ImmutableSet;
22import org.onlab.osgi.ServiceDirectory;
23import org.onlab.util.AbstractAccumulator;
24import org.onlab.util.Accumulator;
25import org.onosproject.cluster.ClusterEvent;
26import org.onosproject.cluster.ClusterEventListener;
27import org.onosproject.cluster.ControllerNode;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
30import org.onosproject.event.Event;
31import org.onosproject.mastership.MastershipAdminService;
32import org.onosproject.mastership.MastershipEvent;
33import org.onosproject.mastership.MastershipListener;
34import org.onosproject.net.ConnectPoint;
35import org.onosproject.net.Device;
36import org.onosproject.net.Host;
37import org.onosproject.net.HostId;
38import org.onosproject.net.HostLocation;
39import org.onosproject.net.Link;
40import org.onosproject.net.device.DeviceEvent;
41import org.onosproject.net.device.DeviceListener;
42import org.onosproject.net.flow.DefaultTrafficSelector;
43import org.onosproject.net.flow.DefaultTrafficTreatment;
44import org.onosproject.net.flow.FlowRuleEvent;
45import org.onosproject.net.flow.FlowRuleListener;
46import org.onosproject.net.flow.TrafficSelector;
47import org.onosproject.net.flow.TrafficTreatment;
48import org.onosproject.net.host.HostEvent;
49import org.onosproject.net.host.HostListener;
50import org.onosproject.net.intent.HostToHostIntent;
51import org.onosproject.net.intent.Intent;
52import org.onosproject.net.intent.IntentEvent;
53import org.onosproject.net.intent.IntentListener;
54import org.onosproject.net.intent.MultiPointToSinglePointIntent;
55import org.onosproject.net.link.LinkEvent;
56import org.onosproject.net.link.LinkListener;
57import org.onosproject.ui.UiConnection;
58
59import java.util.ArrayList;
60import java.util.Collections;
61import java.util.Comparator;
62import java.util.HashSet;
63import java.util.List;
64import java.util.Set;
65import java.util.Timer;
66import java.util.TimerTask;
67
68import static com.google.common.base.Strings.isNullOrEmpty;
69import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED;
70import static org.onosproject.net.DeviceId.deviceId;
71import static org.onosproject.net.HostId.hostId;
72import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
73import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_UPDATED;
74import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
75import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
76
77/**
78 * Web socket capable of interacting with the GUI topology view.
79 */
80public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
81
82 private static final String APP_ID = "org.onosproject.gui";
83
84 private static final long TRAFFIC_FREQUENCY = 5000;
85 private static final long SUMMARY_FREQUENCY = 30000;
86
87 private static final Comparator<? super ControllerNode> NODE_COMPARATOR =
88 new Comparator<ControllerNode>() {
89 @Override
90 public int compare(ControllerNode o1, ControllerNode o2) {
91 return o1.id().toString().compareTo(o2.id().toString());
92 }
93 };
94
95
96 private final Timer timer = new Timer("topology-view");
97
98 private static final int MAX_EVENTS = 1000;
99 private static final int MAX_BATCH_MS = 5000;
100 private static final int MAX_IDLE_MS = 1000;
101
102 private ApplicationId appId;
103
104 private final ClusterEventListener clusterListener = new InternalClusterListener();
105 private final MastershipListener mastershipListener = new InternalMastershipListener();
106 private final DeviceListener deviceListener = new InternalDeviceListener();
107 private final LinkListener linkListener = new InternalLinkListener();
108 private final HostListener hostListener = new InternalHostListener();
109 private final IntentListener intentListener = new InternalIntentListener();
110 private final FlowRuleListener flowListener = new InternalFlowListener();
111
112 private final Accumulator<Event> eventAccummulator = new InternalEventAccummulator();
113
114 private TimerTask trafficTask;
115 private ObjectNode trafficEvent;
116
117 private TimerTask summaryTask;
118 private ObjectNode summaryEvent;
119
120 private boolean listenersRemoved = false;
121
122 private TopologyViewIntentFilter intentFilter;
123
124 // Current selection context
125 private Set<Host> selectedHosts;
126 private Set<Device> selectedDevices;
127 private List<Intent> selectedIntents;
128 private int currentIntentIndex = -1;
129
130 /**
131 * Creates a new web-socket for serving data to GUI topology view.
132 */
133 public TopologyViewMessageHandler() {
Simon Hunt44aa2f82015-04-30 15:01:35 -0700134 super(ImmutableSet.of("topoStart",
135 "topoStop",
Thomas Vachuska329af532015-03-10 02:08:33 -0700136 "requestDetails",
137 "updateMeta",
138 "addHostIntent",
139 "addMultiSourceIntent",
140 "requestRelatedIntents",
141 "requestNextRelatedIntent",
142 "requestPrevRelatedIntent",
143 "requestSelectedIntentTraffic",
144 "requestAllTraffic",
145 "requestDeviceLinkFlows",
146 "cancelTraffic",
147 "requestSummary",
148 "cancelSummary",
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700149 "equalizeMasters",
150 "spriteListRequest",
151 "spriteDataRequest"
Thomas Vachuska329af532015-03-10 02:08:33 -0700152 ));
153 }
154
155 @Override
156 public void init(UiConnection connection, ServiceDirectory directory) {
157 super.init(connection, directory);
158 intentFilter = new TopologyViewIntentFilter(intentService, deviceService,
159 hostService, linkService);
160 appId = directory.get(CoreService.class).registerApplication(APP_ID);
161 }
162
163 @Override
164 public void destroy() {
165 cancelAllRequests();
Thomas Vachuska2bb48632015-04-28 14:40:42 -0700166 removeListeners();
Thomas Vachuska329af532015-03-10 02:08:33 -0700167 super.destroy();
168 }
169
170 // Processes the specified event.
171 @Override
172 public void process(ObjectNode event) {
173 String type = string(event, "event", "unknown");
174 if (type.equals("requestDetails")) {
175 requestDetails(event);
176 } else if (type.equals("updateMeta")) {
177 updateMetaUi(event);
178
179 } else if (type.equals("addHostIntent")) {
180 createHostIntent(event);
181 } else if (type.equals("addMultiSourceIntent")) {
182 createMultiSourceIntent(event);
183
184 } else if (type.equals("requestRelatedIntents")) {
185 stopTrafficMonitoring();
186 requestRelatedIntents(event);
187
188 } else if (type.equals("requestNextRelatedIntent")) {
189 stopTrafficMonitoring();
190 requestAnotherRelatedIntent(event, +1);
191 } else if (type.equals("requestPrevRelatedIntent")) {
192 stopTrafficMonitoring();
193 requestAnotherRelatedIntent(event, -1);
194 } else if (type.equals("requestSelectedIntentTraffic")) {
195 requestSelectedIntentTraffic(event);
196 startTrafficMonitoring(event);
197
198 } else if (type.equals("requestAllTraffic")) {
199 requestAllTraffic(event);
200 startTrafficMonitoring(event);
201
202 } else if (type.equals("requestDeviceLinkFlows")) {
203 requestDeviceLinkFlows(event);
204 startTrafficMonitoring(event);
205
206 } else if (type.equals("cancelTraffic")) {
207 cancelTraffic(event);
208
209 } else if (type.equals("requestSummary")) {
210 requestSummary(event);
211 startSummaryMonitoring(event);
212 } else if (type.equals("cancelSummary")) {
213 stopSummaryMonitoring();
214
215 } else if (type.equals("equalizeMasters")) {
216 equalizeMasters(event);
217
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700218 } else if (type.equals("spriteListRequest")) {
219 sendSpriteList(event);
220 } else if (type.equals("spriteDataRequest")) {
221 sendSpriteData(event);
222
Thomas Vachuska329af532015-03-10 02:08:33 -0700223 } else if (type.equals("topoStart")) {
224 sendAllInitialData();
225 } else if (type.equals("topoStop")) {
226 cancelAllRequests();
227 }
228 }
229
230 // Sends the specified data to the client.
231 protected synchronized void sendMessage(ObjectNode data) {
232 UiConnection connection = connection();
233 if (connection != null) {
234 connection.sendMessage(data);
235 }
236 }
237
238 private void sendAllInitialData() {
239 addListeners();
240 sendAllInstances(null);
241 sendAllDevices();
242 sendAllLinks();
243 sendAllHosts();
244
245 }
246
247 private void cancelAllRequests() {
248 stopSummaryMonitoring();
249 stopTrafficMonitoring();
Thomas Vachuska329af532015-03-10 02:08:33 -0700250 }
251
252 // Sends all controller nodes to the client as node-added messages.
253 private void sendAllInstances(String messageType) {
254 List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes());
255 Collections.sort(nodes, NODE_COMPARATOR);
256 for (ControllerNode node : nodes) {
257 sendMessage(instanceMessage(new ClusterEvent(INSTANCE_ADDED, node),
258 messageType));
259 }
260 }
261
262 // Sends all devices to the client as device-added messages.
263 private void sendAllDevices() {
264 // Send optical first, others later for layered rendering
265 for (Device device : deviceService.getDevices()) {
266 if (device.type() == Device.Type.ROADM) {
267 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
268 }
269 }
270 for (Device device : deviceService.getDevices()) {
271 if (device.type() != Device.Type.ROADM) {
272 sendMessage(deviceMessage(new DeviceEvent(DEVICE_ADDED, device)));
273 }
274 }
275 }
276
277 // Sends all links to the client as link-added messages.
278 private void sendAllLinks() {
279 // Send optical first, others later for layered rendering
280 for (Link link : linkService.getLinks()) {
281 if (link.type() == Link.Type.OPTICAL) {
282 sendMessage(linkMessage(new LinkEvent(LINK_ADDED, link)));
283 }
284 }
285 for (Link link : linkService.getLinks()) {
286 if (link.type() != Link.Type.OPTICAL) {
287 sendMessage(linkMessage(new LinkEvent(LINK_ADDED, link)));
288 }
289 }
290 }
291
292 // Sends all hosts to the client as host-added messages.
293 private void sendAllHosts() {
294 for (Host host : hostService.getHosts()) {
295 sendMessage(hostMessage(new HostEvent(HOST_ADDED, host)));
296 }
297 }
298
299 // Sends back device or host details.
300 private void requestDetails(ObjectNode event) {
301 ObjectNode payload = payload(event);
302 String type = string(payload, "class", "unknown");
303 long sid = number(event, "sid");
304
305 if (type.equals("device")) {
306 sendMessage(deviceDetails(deviceId(string(payload, "id")), sid));
307 } else if (type.equals("host")) {
308 sendMessage(hostDetails(hostId(string(payload, "id")), sid));
309 }
310 }
311
312
313 // Creates host-to-host intent.
314 private void createHostIntent(ObjectNode event) {
315 ObjectNode payload = payload(event);
316 long id = number(event, "sid");
317 // TODO: add protection against device ids and non-existent hosts.
318 HostId one = hostId(string(payload, "one"));
319 HostId two = hostId(string(payload, "two"));
320
321 HostToHostIntent intent =
Ray Milkeyebc5d222015-03-18 15:45:36 -0700322 HostToHostIntent.builder()
323 .appId(appId)
324 .one(one)
325 .two(two)
326 .build();
Thomas Vachuska329af532015-03-10 02:08:33 -0700327
328 intentService.submit(intent);
329 startMonitoringIntent(event, intent);
330 }
331
332 // Creates multi-source-to-single-dest intent.
333 private void createMultiSourceIntent(ObjectNode event) {
334 ObjectNode payload = payload(event);
335 long id = number(event, "sid");
336 // TODO: add protection against device ids and non-existent hosts.
337 Set<HostId> src = getHostIds((ArrayNode) payload.path("src"));
338 HostId dst = hostId(string(payload, "dst"));
339 Host dstHost = hostService.getHost(dst);
340
341 Set<ConnectPoint> ingressPoints = getHostLocations(src);
342
343 // FIXME: clearly, this is not enough
344 TrafficSelector selector = DefaultTrafficSelector.builder()
345 .matchEthDst(dstHost.mac()).build();
Brian O'Connor6b528132015-03-10 16:39:52 -0700346 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
Thomas Vachuska329af532015-03-10 02:08:33 -0700347
348 MultiPointToSinglePointIntent intent =
Ray Milkeyebc5d222015-03-18 15:45:36 -0700349 MultiPointToSinglePointIntent.builder()
350 .appId(appId)
351 .selector(selector)
352 .treatment(treatment)
353 .ingressPoints(ingressPoints)
354 .egressPoint(dstHost.location())
355 .build();
Thomas Vachuska329af532015-03-10 02:08:33 -0700356
357 intentService.submit(intent);
358 startMonitoringIntent(event, intent);
359 }
360
361
362 private synchronized void startMonitoringIntent(ObjectNode event, Intent intent) {
363 selectedHosts = new HashSet<>();
364 selectedDevices = new HashSet<>();
365 selectedIntents = new ArrayList<>();
366 selectedIntents.add(intent);
367 currentIntentIndex = -1;
368 requestAnotherRelatedIntent(event, +1);
369 requestSelectedIntentTraffic(event);
370 }
371
372
373 private Set<ConnectPoint> getHostLocations(Set<HostId> hostIds) {
374 Set<ConnectPoint> points = new HashSet<>();
375 for (HostId hostId : hostIds) {
376 points.add(getHostLocation(hostId));
377 }
378 return points;
379 }
380
381 private HostLocation getHostLocation(HostId hostId) {
382 return hostService.getHost(hostId).location();
383 }
384
385 // Produces a list of host ids from the specified JSON array.
386 private Set<HostId> getHostIds(ArrayNode ids) {
387 Set<HostId> hostIds = new HashSet<>();
388 for (JsonNode id : ids) {
389 hostIds.add(hostId(id.asText()));
390 }
391 return hostIds;
392 }
393
394
395 private synchronized long startTrafficMonitoring(ObjectNode event) {
396 stopTrafficMonitoring();
397 trafficEvent = event;
398 trafficTask = new TrafficMonitor();
399 timer.schedule(trafficTask, TRAFFIC_FREQUENCY, TRAFFIC_FREQUENCY);
400 return number(event, "sid");
401 }
402
403 private synchronized void stopTrafficMonitoring() {
404 if (trafficTask != null) {
405 trafficTask.cancel();
406 trafficTask = null;
407 trafficEvent = null;
408 }
409 }
410
411 // Subscribes for host traffic messages.
412 private synchronized void requestAllTraffic(ObjectNode event) {
413 long sid = startTrafficMonitoring(event);
414 sendMessage(trafficSummaryMessage(sid));
415 }
416
417 private void requestDeviceLinkFlows(ObjectNode event) {
418 ObjectNode payload = payload(event);
419 long sid = startTrafficMonitoring(event);
420
421 // Get the set of selected hosts and their intents.
422 ArrayNode ids = (ArrayNode) payload.path("ids");
423 Set<Host> hosts = new HashSet<>();
424 Set<Device> devices = getDevices(ids);
425
426 // If there is a hover node, include it in the hosts and find intents.
427 String hover = string(payload, "hover");
428 if (!isNullOrEmpty(hover)) {
429 addHover(hosts, devices, hover);
430 }
431 sendMessage(flowSummaryMessage(sid, devices));
432 }
433
434
435 // Requests related intents message.
436 private synchronized void requestRelatedIntents(ObjectNode event) {
437 ObjectNode payload = payload(event);
438 if (!payload.has("ids")) {
439 return;
440 }
441
442 long sid = number(event, "sid");
443
444 // Cancel any other traffic monitoring mode.
445 stopTrafficMonitoring();
446
447 // Get the set of selected hosts and their intents.
448 ArrayNode ids = (ArrayNode) payload.path("ids");
449 selectedHosts = getHosts(ids);
450 selectedDevices = getDevices(ids);
451 selectedIntents = intentFilter.findPathIntents(selectedHosts, selectedDevices,
452 intentService.getIntents());
453 currentIntentIndex = -1;
454
455 if (haveSelectedIntents()) {
456 // Send a message to highlight all links of all monitored intents.
457 sendMessage(trafficMessage(sid, new TrafficClass("primary", selectedIntents)));
458 }
459
460 // FIXME: Re-introduce one the client click vs hover gesture stuff is sorted out.
461// String hover = string(payload, "hover");
462// if (!isNullOrEmpty(hover)) {
463// // If there is a hover node, include it in the selection and find intents.
464// processHoverExtendedSelection(sid, hover);
465// }
466 }
467
468 private boolean haveSelectedIntents() {
469 return selectedIntents != null && !selectedIntents.isEmpty();
470 }
471
472 // Processes the selection extended with hovered item to segregate items
473 // into primary (those including the hover) vs secondary highlights.
474 private void processHoverExtendedSelection(long sid, String hover) {
475 Set<Host> hoverSelHosts = new HashSet<>(selectedHosts);
476 Set<Device> hoverSelDevices = new HashSet<>(selectedDevices);
477 addHover(hoverSelHosts, hoverSelDevices, hover);
478
479 List<Intent> primary = selectedIntents == null ? new ArrayList<>() :
480 intentFilter.findPathIntents(hoverSelHosts, hoverSelDevices,
481 selectedIntents);
482 Set<Intent> secondary = new HashSet<>(selectedIntents);
483 secondary.removeAll(primary);
484
485 // Send a message to highlight all links of all monitored intents.
486 sendMessage(trafficMessage(sid, new TrafficClass("primary", primary),
487 new TrafficClass("secondary", secondary)));
488 }
489
490 // Requests next or previous related intent.
491 private void requestAnotherRelatedIntent(ObjectNode event, int offset) {
492 if (haveSelectedIntents()) {
493 currentIntentIndex = currentIntentIndex + offset;
494 if (currentIntentIndex < 0) {
495 currentIntentIndex = selectedIntents.size() - 1;
496 } else if (currentIntentIndex >= selectedIntents.size()) {
497 currentIntentIndex = 0;
498 }
499 sendSelectedIntent(event);
500 }
501 }
502
503 // Sends traffic information on the related intents with the currently
504 // selected intent highlighted.
505 private void sendSelectedIntent(ObjectNode event) {
506 Intent selectedIntent = selectedIntents.get(currentIntentIndex);
507 log.info("Requested next intent {}", selectedIntent.id());
508
509 Set<Intent> primary = new HashSet<>();
510 primary.add(selectedIntent);
511
512 Set<Intent> secondary = new HashSet<>(selectedIntents);
513 secondary.remove(selectedIntent);
514
515 // Send a message to highlight all links of the selected intent.
516 sendMessage(trafficMessage(number(event, "sid"),
517 new TrafficClass("primary", primary),
518 new TrafficClass("secondary", secondary)));
519 }
520
521 // Requests monitoring of traffic for the selected intent.
522 private void requestSelectedIntentTraffic(ObjectNode event) {
523 if (haveSelectedIntents()) {
524 if (currentIntentIndex < 0) {
525 currentIntentIndex = 0;
526 }
527 Intent selectedIntent = selectedIntents.get(currentIntentIndex);
528 log.info("Requested traffic for selected {}", selectedIntent.id());
529
530 Set<Intent> primary = new HashSet<>();
531 primary.add(selectedIntent);
532
533 // Send a message to highlight all links of the selected intent.
534 sendMessage(trafficMessage(number(event, "sid"),
535 new TrafficClass("primary", primary, true)));
536 }
537 }
538
539 // Cancels sending traffic messages.
540 private void cancelTraffic(ObjectNode event) {
541 selectedIntents = null;
542 sendMessage(trafficMessage(number(event, "sid")));
543 stopTrafficMonitoring();
544 }
545
546
547 private synchronized long startSummaryMonitoring(ObjectNode event) {
548 stopSummaryMonitoring();
549 summaryEvent = event;
550 summaryTask = new SummaryMonitor();
551 timer.schedule(summaryTask, SUMMARY_FREQUENCY, SUMMARY_FREQUENCY);
552 return number(event, "sid");
553 }
554
555 private synchronized void stopSummaryMonitoring() {
556 if (summaryEvent != null) {
557 summaryTask.cancel();
558 summaryTask = null;
559 summaryEvent = null;
560 }
561 }
562
563 // Subscribes for summary messages.
564 private synchronized void requestSummary(ObjectNode event) {
565 sendMessage(summmaryMessage(number(event, "sid")));
566 }
567
568
569 // Forces mastership role rebalancing.
570 private void equalizeMasters(ObjectNode event) {
571 directory.get(MastershipAdminService.class).balanceRoles();
572 }
573
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700574 // Sends a list of sprite names.
575 private void sendSpriteList(ObjectNode event) {
576 ObjectNode root = mapper.createObjectNode();
577 ArrayNode names = mapper.createArrayNode();
578 get(SpriteService.class).getNames().forEach(names::add);
579 root.set("names", names);
580 sendMessage(envelope("spriteListResponse", number(event, "sid"), root));
581 }
582
583 // Sends requested sprite data.
584 private void sendSpriteData(ObjectNode event) {
Simon Huntfd8c7d72015-04-14 17:53:37 -0700585 String name = event.path("payload").path("name").asText();
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700586 ObjectNode root = mapper.createObjectNode();
Simon Huntfd8c7d72015-04-14 17:53:37 -0700587 root.set("data", get(SpriteService.class).get(name));
Thomas Vachuska9ed335b2015-04-14 12:07:47 -0700588 sendMessage(envelope("spriteDataResponse", number(event, "sid"), root));
589 }
590
Thomas Vachuska329af532015-03-10 02:08:33 -0700591
592 // Adds all internal listeners.
Thomas Vachuska35fa3d42015-04-30 10:11:47 -0700593 private synchronized void addListeners() {
Thomas Vachuskae586b792015-03-26 13:59:38 -0700594 listenersRemoved = false;
Thomas Vachuska329af532015-03-10 02:08:33 -0700595 clusterService.addListener(clusterListener);
596 mastershipService.addListener(mastershipListener);
597 deviceService.addListener(deviceListener);
598 linkService.addListener(linkListener);
599 hostService.addListener(hostListener);
600 intentService.addListener(intentListener);
601 flowService.addListener(flowListener);
602 }
603
604 // Removes all internal listeners.
605 private synchronized void removeListeners() {
606 if (!listenersRemoved) {
607 listenersRemoved = true;
608 clusterService.removeListener(clusterListener);
609 mastershipService.removeListener(mastershipListener);
610 deviceService.removeListener(deviceListener);
611 linkService.removeListener(linkListener);
612 hostService.removeListener(hostListener);
613 intentService.removeListener(intentListener);
614 flowService.removeListener(flowListener);
615 }
616 }
617
618 // Cluster event listener.
619 private class InternalClusterListener implements ClusterEventListener {
620 @Override
621 public void event(ClusterEvent event) {
622 sendMessage(instanceMessage(event, null));
623 }
624 }
625
626 // Mastership change listener
627 private class InternalMastershipListener implements MastershipListener {
628 @Override
629 public void event(MastershipEvent event) {
630 sendAllInstances("updateInstance");
631 Device device = deviceService.getDevice(event.subject());
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700632 if (device != null) {
633 sendMessage(deviceMessage(new DeviceEvent(DEVICE_UPDATED, device)));
634 }
Thomas Vachuska329af532015-03-10 02:08:33 -0700635 }
636 }
637
638 // Device event listener.
639 private class InternalDeviceListener implements DeviceListener {
640 @Override
641 public void event(DeviceEvent event) {
642 sendMessage(deviceMessage(event));
643 eventAccummulator.add(event);
644 }
645 }
646
647 // Link event listener.
648 private class InternalLinkListener implements LinkListener {
649 @Override
650 public void event(LinkEvent event) {
651 sendMessage(linkMessage(event));
652 eventAccummulator.add(event);
653 }
654 }
655
656 // Host event listener.
657 private class InternalHostListener implements HostListener {
658 @Override
659 public void event(HostEvent event) {
660 sendMessage(hostMessage(event));
661 eventAccummulator.add(event);
662 }
663 }
664
665 // Intent event listener.
666 private class InternalIntentListener implements IntentListener {
667 @Override
668 public void event(IntentEvent event) {
669 if (trafficEvent != null) {
670 requestSelectedIntentTraffic(trafficEvent);
671 }
672 eventAccummulator.add(event);
673 }
674 }
675
676 // Intent event listener.
677 private class InternalFlowListener implements FlowRuleListener {
678 @Override
679 public void event(FlowRuleEvent event) {
680 eventAccummulator.add(event);
681 }
682 }
683
684 // Periodic update of the traffic information
685 private class TrafficMonitor extends TimerTask {
686 @Override
687 public void run() {
688 try {
689 if (trafficEvent != null) {
690 String type = string(trafficEvent, "event", "unknown");
691 if (type.equals("requestAllTraffic")) {
692 requestAllTraffic(trafficEvent);
693 } else if (type.equals("requestDeviceLinkFlows")) {
694 requestDeviceLinkFlows(trafficEvent);
695 } else if (type.equals("requestSelectedIntentTraffic")) {
696 requestSelectedIntentTraffic(trafficEvent);
697 }
698 }
699 } catch (Exception e) {
700 log.warn("Unable to handle traffic request due to {}", e.getMessage());
701 log.warn("Boom!", e);
702 }
703 }
704 }
705
706 // Periodic update of the summary information
707 private class SummaryMonitor extends TimerTask {
708 @Override
709 public void run() {
710 try {
711 if (summaryEvent != null) {
712 requestSummary(summaryEvent);
713 }
714 } catch (Exception e) {
715 log.warn("Unable to handle summary request due to {}", e.getMessage());
716 log.warn("Boom!", e);
717 }
718 }
719 }
720
721 // Accumulates events to drive methodic update of the summary pane.
722 private class InternalEventAccummulator extends AbstractAccumulator<Event> {
723 protected InternalEventAccummulator() {
724 super(new Timer("topo-summary"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
725 }
726
727 @Override
728 public void processItems(List<Event> items) {
729 try {
730 if (summaryEvent != null) {
731 sendMessage(summmaryMessage(0));
732 }
733 } catch (Exception e) {
734 log.warn("Unable to handle summary request due to {}", e.getMessage());
735 log.debug("Boom!", e);
736 }
737 }
738 }
739}
740