Committed by
Ray Milkey
Fixing various issues and re-tuning.
Change-Id: I8822fcf77cfa507788241c5bda98ef4741b284b4
Showing
6 changed files
with
111 additions
and
64 deletions
... | @@ -23,13 +23,15 @@ import org.onlab.onos.cluster.ControllerNode; | ... | @@ -23,13 +23,15 @@ import org.onlab.onos.cluster.ControllerNode; |
23 | import org.onlab.onos.mastership.MastershipAdminService; | 23 | import org.onlab.onos.mastership.MastershipAdminService; |
24 | import org.onlab.onos.mastership.MastershipService; | 24 | import org.onlab.onos.mastership.MastershipService; |
25 | import org.onlab.onos.net.DeviceId; | 25 | import org.onlab.onos.net.DeviceId; |
26 | -import org.onlab.onos.net.MastershipRole; | 26 | +import org.onlab.onos.net.device.DeviceService; |
27 | 27 | ||
28 | import java.util.Collection; | 28 | import java.util.Collection; |
29 | import java.util.Iterator; | 29 | import java.util.Iterator; |
30 | import java.util.List; | 30 | import java.util.List; |
31 | +import java.util.Set; | ||
31 | 32 | ||
32 | import static com.google.common.collect.Lists.newArrayList; | 33 | import static com.google.common.collect.Lists.newArrayList; |
34 | +import static org.onlab.onos.net.MastershipRole.MASTER; | ||
33 | 35 | ||
34 | /** | 36 | /** |
35 | * Forces device mastership rebalancing. | 37 | * Forces device mastership rebalancing. |
... | @@ -50,56 +52,48 @@ public class BalanceMastersCommand extends AbstractShellCommand { | ... | @@ -50,56 +52,48 @@ public class BalanceMastersCommand extends AbstractShellCommand { |
50 | 52 | ||
51 | // Create buckets reflecting current ownership. | 53 | // Create buckets reflecting current ownership. |
52 | for (ControllerNode node : nodes) { | 54 | for (ControllerNode node : nodes) { |
53 | - controllerDevices.putAll(node, mastershipService.getDevicesOf(node.id())); | 55 | + Set<DeviceId> devicesOf = mastershipService.getDevicesOf(node.id()); |
56 | + controllerDevices.putAll(node, devicesOf); | ||
57 | + print("Node %s has %d devices.", node.id(), devicesOf.size()); | ||
54 | } | 58 | } |
55 | 59 | ||
56 | - int bucketCount = nodes.size(); | 60 | + int rounds = nodes.size(); |
57 | - for (int i = 0; i < bucketCount / 2; i++) { | 61 | + for (int i = 0; i < rounds; i++) { |
58 | // Iterate over the buckets and find the smallest and the largest. | 62 | // Iterate over the buckets and find the smallest and the largest. |
59 | - ControllerNode smallest = findSmallestBucket(controllerDevices); | 63 | + ControllerNode smallest = findBucket(true, nodes, controllerDevices); |
60 | - ControllerNode largest = findLargestBucket(controllerDevices); | 64 | + ControllerNode largest = findBucket(false, nodes, controllerDevices); |
61 | - balanceBuckets(smallest, largest, controllerDevices, | 65 | + balanceBuckets(smallest, largest, controllerDevices, adminService); |
62 | - mastershipService, adminService); | ||
63 | } | 66 | } |
64 | } | 67 | } |
65 | 68 | ||
66 | - private ControllerNode findSmallestBucket(Multimap<ControllerNode, DeviceId> controllerDevices) { | 69 | + private ControllerNode findBucket(boolean min, Collection<ControllerNode> nodes, |
67 | - int minSize = Integer.MAX_VALUE; | 70 | + Multimap<ControllerNode, DeviceId> controllerDevices) { |
68 | - ControllerNode minNode = null; | 71 | + int xSize = min ? Integer.MAX_VALUE : -1; |
69 | - for (ControllerNode node : controllerDevices.keySet()) { | 72 | + ControllerNode xNode = null; |
70 | - int size = controllerDevices.get(node).size(); | 73 | + for (ControllerNode node : nodes) { |
71 | - if (size < minSize) { | ||
72 | - minSize = size; | ||
73 | - minNode = node; | ||
74 | - } | ||
75 | - } | ||
76 | - return minNode; | ||
77 | - } | ||
78 | - | ||
79 | - private ControllerNode findLargestBucket(Multimap<ControllerNode, DeviceId> controllerDevices) { | ||
80 | - int maxSize = -1; | ||
81 | - ControllerNode maxNode = null; | ||
82 | - for (ControllerNode node : controllerDevices.keySet()) { | ||
83 | int size = controllerDevices.get(node).size(); | 74 | int size = controllerDevices.get(node).size(); |
84 | - if (size >= maxSize) { | 75 | + if ((min && size < xSize) || (!min && size > xSize)) { |
85 | - maxSize = size; | 76 | + xSize = size; |
86 | - maxNode = node; | 77 | + xNode = node; |
87 | } | 78 | } |
88 | } | 79 | } |
89 | - return maxNode; | 80 | + return xNode; |
90 | } | 81 | } |
91 | 82 | ||
92 | // FIXME: enhance to better handle cases where smallest cannot take any of the devices from largest | 83 | // FIXME: enhance to better handle cases where smallest cannot take any of the devices from largest |
93 | 84 | ||
94 | private void balanceBuckets(ControllerNode smallest, ControllerNode largest, | 85 | private void balanceBuckets(ControllerNode smallest, ControllerNode largest, |
95 | Multimap<ControllerNode, DeviceId> controllerDevices, | 86 | Multimap<ControllerNode, DeviceId> controllerDevices, |
96 | - MastershipService mastershipService, | ||
97 | MastershipAdminService adminService) { | 87 | MastershipAdminService adminService) { |
98 | Collection<DeviceId> minBucket = controllerDevices.get(smallest); | 88 | Collection<DeviceId> minBucket = controllerDevices.get(smallest); |
99 | Collection<DeviceId> maxBucket = controllerDevices.get(largest); | 89 | Collection<DeviceId> maxBucket = controllerDevices.get(largest); |
90 | + int bucketCount = controllerDevices.keySet().size(); | ||
91 | + int deviceCount = get(DeviceService.class).getDeviceCount(); | ||
100 | 92 | ||
101 | int delta = (maxBucket.size() - minBucket.size()) / 2; | 93 | int delta = (maxBucket.size() - minBucket.size()) / 2; |
94 | + delta = Math.min(deviceCount / bucketCount, delta); | ||
102 | 95 | ||
96 | + if (delta > 0) { | ||
103 | print("Attempting to move %d nodes from %s to %s...", | 97 | print("Attempting to move %d nodes from %s to %s...", |
104 | delta, largest.id(), smallest.id()); | 98 | delta, largest.id(), smallest.id()); |
105 | 99 | ||
... | @@ -107,16 +101,13 @@ public class BalanceMastersCommand extends AbstractShellCommand { | ... | @@ -107,16 +101,13 @@ public class BalanceMastersCommand extends AbstractShellCommand { |
107 | Iterator<DeviceId> it = maxBucket.iterator(); | 101 | Iterator<DeviceId> it = maxBucket.iterator(); |
108 | while (it.hasNext() && i < delta) { | 102 | while (it.hasNext() && i < delta) { |
109 | DeviceId deviceId = it.next(); | 103 | DeviceId deviceId = it.next(); |
110 | - | 104 | + print("Setting %s as the master for %s", smallest.id(), deviceId); |
111 | - // Check that the transfer can happen for the current element. | 105 | + adminService.setRole(smallest.id(), deviceId, MASTER); |
112 | - if (mastershipService.getNodesFor(deviceId).backups().contains(smallest.id())) { | 106 | + controllerDevices.put(smallest, deviceId); |
113 | - print("Setting %s as the new master for %s", smallest.id(), deviceId); | 107 | + it.remove(); |
114 | - adminService.setRole(smallest.id(), deviceId, MastershipRole.MASTER); | ||
115 | i++; | 108 | i++; |
116 | } | 109 | } |
117 | } | 110 | } |
118 | - | ||
119 | - controllerDevices.removeAll(smallest); | ||
120 | } | 111 | } |
121 | 112 | ||
122 | } | 113 | } | ... | ... |
... | @@ -16,6 +16,8 @@ | ... | @@ -16,6 +16,8 @@ |
16 | package org.onlab.onos.event; | 16 | package org.onlab.onos.event; |
17 | 17 | ||
18 | import com.google.common.collect.Lists; | 18 | import com.google.common.collect.Lists; |
19 | +import org.slf4j.Logger; | ||
20 | +import org.slf4j.LoggerFactory; | ||
19 | 21 | ||
20 | import java.util.List; | 22 | import java.util.List; |
21 | import java.util.Timer; | 23 | import java.util.Timer; |
... | @@ -31,6 +33,8 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -31,6 +33,8 @@ import static com.google.common.base.Preconditions.checkNotNull; |
31 | */ | 33 | */ |
32 | public abstract class AbstractEventAccumulator implements EventAccumulator { | 34 | public abstract class AbstractEventAccumulator implements EventAccumulator { |
33 | 35 | ||
36 | + private Logger log = LoggerFactory.getLogger(AbstractEventAccumulator.class); | ||
37 | + | ||
34 | private final Timer timer; | 38 | private final Timer timer; |
35 | private final int maxEvents; | 39 | private final int maxEvents; |
36 | private final int maxBatchMillis; | 40 | private final int maxBatchMillis; |
... | @@ -104,9 +108,13 @@ public abstract class AbstractEventAccumulator implements EventAccumulator { | ... | @@ -104,9 +108,13 @@ public abstract class AbstractEventAccumulator implements EventAccumulator { |
104 | private class ProcessorTask extends TimerTask { | 108 | private class ProcessorTask extends TimerTask { |
105 | @Override | 109 | @Override |
106 | public void run() { | 110 | public void run() { |
111 | + try { | ||
107 | idleTask = cancelIfActive(idleTask); | 112 | idleTask = cancelIfActive(idleTask); |
108 | maxTask = cancelIfActive(maxTask); | 113 | maxTask = cancelIfActive(maxTask); |
109 | processEvents(finalizeCurrentBatch()); | 114 | processEvents(finalizeCurrentBatch()); |
115 | + } catch (Exception e) { | ||
116 | + log.warn("Unable to process batch due to {}", e.getMessage()); | ||
117 | + } | ||
110 | } | 118 | } |
111 | } | 119 | } |
112 | 120 | ... | ... |
... | @@ -66,13 +66,13 @@ public class DefaultTopologyProvider extends AbstractProvider | ... | @@ -66,13 +66,13 @@ public class DefaultTopologyProvider extends AbstractProvider |
66 | implements TopologyProvider { | 66 | implements TopologyProvider { |
67 | 67 | ||
68 | private static final int MAX_THREADS = 8; | 68 | private static final int MAX_THREADS = 8; |
69 | - private static final int DEFAULT_MAX_EVENTS = 100; | 69 | + private static final int DEFAULT_MAX_EVENTS = 200; |
70 | - private static final int DEFAULT_MAX_BATCH_MS = 50; | 70 | + private static final int DEFAULT_MAX_BATCH_MS = 60; |
71 | - private static final int DEFAULT_MAX_IDLE_MS = 5; | 71 | + private static final int DEFAULT_MAX_IDLE_MS = 30; |
72 | 72 | ||
73 | // FIXME: Replace with a system-wide timer instance; | 73 | // FIXME: Replace with a system-wide timer instance; |
74 | // TODO: Convert to use HashedWheelTimer or produce a variant of that; then decide which we want to adopt | 74 | // TODO: Convert to use HashedWheelTimer or produce a variant of that; then decide which we want to adopt |
75 | - private static final Timer TIMER = new Timer(); | 75 | + private static final Timer TIMER = new Timer("topo-event-batching"); |
76 | 76 | ||
77 | @Property(name = "maxEvents", intValue = DEFAULT_MAX_EVENTS, | 77 | @Property(name = "maxEvents", intValue = DEFAULT_MAX_EVENTS, |
78 | label = "Maximum number of events to accumulate") | 78 | label = "Maximum number of events to accumulate") |
... | @@ -122,6 +122,9 @@ public class DefaultTopologyProvider extends AbstractProvider | ... | @@ -122,6 +122,9 @@ public class DefaultTopologyProvider extends AbstractProvider |
122 | deviceService.addListener(deviceListener); | 122 | deviceService.addListener(deviceListener); |
123 | linkService.addListener(linkListener); | 123 | linkService.addListener(linkListener); |
124 | 124 | ||
125 | + log.info("Configured with maxEvents = {}; maxBatchMs = {}; maxIdleMs = {}", | ||
126 | + maxEvents, maxBatchMs, maxIdleMs); | ||
127 | + | ||
125 | isStarted = true; | 128 | isStarted = true; |
126 | triggerRecompute(); | 129 | triggerRecompute(); |
127 | log.info("Started"); | 130 | log.info("Started"); | ... | ... |
tools/test/bin/onos-topo-cfg-all
0 → 100755
1 | +#!/bin/bash | ||
2 | +# ----------------------------------------------------------------------------- | ||
3 | +# ONOS topology configuration uploader. | ||
4 | +# ----------------------------------------------------------------------------- | ||
5 | + | ||
6 | +[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 | ||
7 | +. $ONOS_ROOT/tools/build/envDefaults | ||
8 | + | ||
9 | +nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2) | ||
10 | + | ||
11 | +for node in $nodes; do | ||
12 | + printf "$node..." | ||
13 | + onos-topo-cfg $node $1 | ||
14 | +done | ||
15 | +printf "\n" |
... | @@ -24,6 +24,9 @@ import org.onlab.onos.cluster.ClusterEventListener; | ... | @@ -24,6 +24,9 @@ import org.onlab.onos.cluster.ClusterEventListener; |
24 | import org.onlab.onos.cluster.ControllerNode; | 24 | import org.onlab.onos.cluster.ControllerNode; |
25 | import org.onlab.onos.core.ApplicationId; | 25 | import org.onlab.onos.core.ApplicationId; |
26 | import org.onlab.onos.core.CoreService; | 26 | import org.onlab.onos.core.CoreService; |
27 | +import org.onlab.onos.event.AbstractEventAccumulator; | ||
28 | +import org.onlab.onos.event.Event; | ||
29 | +import org.onlab.onos.event.EventAccumulator; | ||
27 | import org.onlab.onos.mastership.MastershipEvent; | 30 | import org.onlab.onos.mastership.MastershipEvent; |
28 | import org.onlab.onos.mastership.MastershipListener; | 31 | import org.onlab.onos.mastership.MastershipListener; |
29 | import org.onlab.onos.net.ConnectPoint; | 32 | import org.onlab.onos.net.ConnectPoint; |
... | @@ -36,6 +39,8 @@ import org.onlab.onos.net.device.DeviceEvent; | ... | @@ -36,6 +39,8 @@ import org.onlab.onos.net.device.DeviceEvent; |
36 | import org.onlab.onos.net.device.DeviceListener; | 39 | import org.onlab.onos.net.device.DeviceListener; |
37 | import org.onlab.onos.net.flow.DefaultTrafficSelector; | 40 | import org.onlab.onos.net.flow.DefaultTrafficSelector; |
38 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; | 41 | import org.onlab.onos.net.flow.DefaultTrafficTreatment; |
42 | +import org.onlab.onos.net.flow.FlowRuleEvent; | ||
43 | +import org.onlab.onos.net.flow.FlowRuleListener; | ||
39 | import org.onlab.onos.net.flow.TrafficSelector; | 44 | import org.onlab.onos.net.flow.TrafficSelector; |
40 | import org.onlab.onos.net.flow.TrafficTreatment; | 45 | import org.onlab.onos.net.flow.TrafficTreatment; |
41 | import org.onlab.onos.net.host.HostEvent; | 46 | import org.onlab.onos.net.host.HostEvent; |
... | @@ -84,8 +89,7 @@ public class TopologyViewWebSocket | ... | @@ -84,8 +89,7 @@ public class TopologyViewWebSocket |
84 | 89 | ||
85 | private static final String APP_ID = "org.onlab.onos.gui"; | 90 | private static final String APP_ID = "org.onlab.onos.gui"; |
86 | 91 | ||
87 | - private static final long SUMMARY_FREQUENCY_SEC = 3000; | 92 | + private static final long TRAFFIC_FREQUENCY_SEC = 2000; |
88 | - private static final long TRAFFIC_FREQUENCY_SEC = 1500; | ||
89 | 93 | ||
90 | private static final Comparator<? super ControllerNode> NODE_COMPARATOR = | 94 | private static final Comparator<? super ControllerNode> NODE_COMPARATOR = |
91 | new Comparator<ControllerNode>() { | 95 | new Comparator<ControllerNode>() { |
... | @@ -95,6 +99,13 @@ public class TopologyViewWebSocket | ... | @@ -95,6 +99,13 @@ public class TopologyViewWebSocket |
95 | } | 99 | } |
96 | }; | 100 | }; |
97 | 101 | ||
102 | + | ||
103 | + private final Timer timer = new Timer("topology-view"); | ||
104 | + | ||
105 | + private static final int MAX_EVENTS = 500; | ||
106 | + private static final int MAX_BATCH_MS = 1000; | ||
107 | + private static final int MAX_IDLE_MS = 500; | ||
108 | + | ||
98 | private final ApplicationId appId; | 109 | private final ApplicationId appId; |
99 | 110 | ||
100 | private Connection connection; | 111 | private Connection connection; |
... | @@ -106,16 +117,14 @@ public class TopologyViewWebSocket | ... | @@ -106,16 +117,14 @@ public class TopologyViewWebSocket |
106 | private final LinkListener linkListener = new InternalLinkListener(); | 117 | private final LinkListener linkListener = new InternalLinkListener(); |
107 | private final HostListener hostListener = new InternalHostListener(); | 118 | private final HostListener hostListener = new InternalHostListener(); |
108 | private final IntentListener intentListener = new InternalIntentListener(); | 119 | private final IntentListener intentListener = new InternalIntentListener(); |
120 | + private final FlowRuleListener flowListener = new InternalFlowListener(); | ||
109 | 121 | ||
110 | - // Timers and objects being monitored | 122 | + private final EventAccumulator eventAccummulator = new InternalEventAccummulator(); |
111 | - private final Timer timer = new Timer("topology-view"); | ||
112 | 123 | ||
124 | + private boolean summaryEnabled = true; | ||
113 | private TimerTask trafficTask; | 125 | private TimerTask trafficTask; |
114 | private ObjectNode trafficEvent; | 126 | private ObjectNode trafficEvent; |
115 | 127 | ||
116 | - private TimerTask summaryTask; | ||
117 | - private ObjectNode summaryEvent; | ||
118 | - | ||
119 | private long lastActive = System.currentTimeMillis(); | 128 | private long lastActive = System.currentTimeMillis(); |
120 | private boolean listenersRemoved = false; | 129 | private boolean listenersRemoved = false; |
121 | 130 | ||
... | @@ -128,7 +137,6 @@ public class TopologyViewWebSocket | ... | @@ -128,7 +137,6 @@ public class TopologyViewWebSocket |
128 | */ | 137 | */ |
129 | public TopologyViewWebSocket(ServiceDirectory directory) { | 138 | public TopologyViewWebSocket(ServiceDirectory directory) { |
130 | super(directory); | 139 | super(directory); |
131 | - | ||
132 | intentFilter = new TopologyViewIntentFilter(intentService, deviceService, | 140 | intentFilter = new TopologyViewIntentFilter(intentService, deviceService, |
133 | hostService, linkService); | 141 | hostService, linkService); |
134 | appId = directory.get(CoreService.class).registerApplication(APP_ID); | 142 | appId = directory.get(CoreService.class).registerApplication(APP_ID); |
... | @@ -431,21 +439,13 @@ public class TopologyViewWebSocket | ... | @@ -431,21 +439,13 @@ public class TopologyViewWebSocket |
431 | 439 | ||
432 | // Subscribes for summary messages. | 440 | // Subscribes for summary messages. |
433 | private synchronized void requestSummary(ObjectNode event) { | 441 | private synchronized void requestSummary(ObjectNode event) { |
434 | - if (summaryTask == null) { | 442 | + summaryEnabled = true; |
435 | - summaryEvent = event; | ||
436 | - summaryTask = new SummaryMonitor(); | ||
437 | - timer.schedule(summaryTask, SUMMARY_FREQUENCY_SEC, SUMMARY_FREQUENCY_SEC); | ||
438 | - } | ||
439 | sendMessage(summmaryMessage(number(event, "sid"))); | 443 | sendMessage(summmaryMessage(number(event, "sid"))); |
440 | } | 444 | } |
441 | 445 | ||
442 | // Cancels sending summary messages. | 446 | // Cancels sending summary messages. |
443 | private synchronized void cancelSummary(ObjectNode event) { | 447 | private synchronized void cancelSummary(ObjectNode event) { |
444 | - if (summaryTask != null) { | 448 | + summaryEnabled = false; |
445 | - summaryTask.cancel(); | ||
446 | - summaryTask = null; | ||
447 | - summaryEvent = null; | ||
448 | - } | ||
449 | } | 449 | } |
450 | 450 | ||
451 | 451 | ||
... | @@ -457,6 +457,7 @@ public class TopologyViewWebSocket | ... | @@ -457,6 +457,7 @@ public class TopologyViewWebSocket |
457 | linkService.addListener(linkListener); | 457 | linkService.addListener(linkListener); |
458 | hostService.addListener(hostListener); | 458 | hostService.addListener(hostListener); |
459 | intentService.addListener(intentListener); | 459 | intentService.addListener(intentListener); |
460 | + flowService.addListener(flowListener); | ||
460 | } | 461 | } |
461 | 462 | ||
462 | // Removes all internal listeners. | 463 | // Removes all internal listeners. |
... | @@ -469,6 +470,7 @@ public class TopologyViewWebSocket | ... | @@ -469,6 +470,7 @@ public class TopologyViewWebSocket |
469 | linkService.removeListener(linkListener); | 470 | linkService.removeListener(linkListener); |
470 | hostService.removeListener(hostListener); | 471 | hostService.removeListener(hostListener); |
471 | intentService.removeListener(intentListener); | 472 | intentService.removeListener(intentListener); |
473 | + flowService.removeListener(flowListener); | ||
472 | } | 474 | } |
473 | } | 475 | } |
474 | 476 | ||
... | @@ -495,6 +497,7 @@ public class TopologyViewWebSocket | ... | @@ -495,6 +497,7 @@ public class TopologyViewWebSocket |
495 | @Override | 497 | @Override |
496 | public void event(DeviceEvent event) { | 498 | public void event(DeviceEvent event) { |
497 | sendMessage(deviceMessage(event)); | 499 | sendMessage(deviceMessage(event)); |
500 | + eventAccummulator.add(event); | ||
498 | } | 501 | } |
499 | } | 502 | } |
500 | 503 | ||
... | @@ -503,6 +506,7 @@ public class TopologyViewWebSocket | ... | @@ -503,6 +506,7 @@ public class TopologyViewWebSocket |
503 | @Override | 506 | @Override |
504 | public void event(LinkEvent event) { | 507 | public void event(LinkEvent event) { |
505 | sendMessage(linkMessage(event)); | 508 | sendMessage(linkMessage(event)); |
509 | + eventAccummulator.add(event); | ||
506 | } | 510 | } |
507 | } | 511 | } |
508 | 512 | ||
... | @@ -511,6 +515,7 @@ public class TopologyViewWebSocket | ... | @@ -511,6 +515,7 @@ public class TopologyViewWebSocket |
511 | @Override | 515 | @Override |
512 | public void event(HostEvent event) { | 516 | public void event(HostEvent event) { |
513 | sendMessage(hostMessage(event)); | 517 | sendMessage(hostMessage(event)); |
518 | + eventAccummulator.add(event); | ||
514 | } | 519 | } |
515 | } | 520 | } |
516 | 521 | ||
... | @@ -521,12 +526,22 @@ public class TopologyViewWebSocket | ... | @@ -521,12 +526,22 @@ public class TopologyViewWebSocket |
521 | if (trafficEvent != null) { | 526 | if (trafficEvent != null) { |
522 | requestTraffic(trafficEvent); | 527 | requestTraffic(trafficEvent); |
523 | } | 528 | } |
529 | + eventAccummulator.add(event); | ||
530 | + } | ||
531 | + } | ||
532 | + | ||
533 | + // Intent event listener. | ||
534 | + private class InternalFlowListener implements FlowRuleListener { | ||
535 | + @Override | ||
536 | + public void event(FlowRuleEvent event) { | ||
537 | + eventAccummulator.add(event); | ||
524 | } | 538 | } |
525 | } | 539 | } |
526 | 540 | ||
527 | private class TrafficMonitor extends TimerTask { | 541 | private class TrafficMonitor extends TimerTask { |
528 | @Override | 542 | @Override |
529 | public void run() { | 543 | public void run() { |
544 | + try { | ||
530 | if (trafficEvent != null) { | 545 | if (trafficEvent != null) { |
531 | String type = string(trafficEvent, "event", "unknown"); | 546 | String type = string(trafficEvent, "event", "unknown"); |
532 | if (type.equals("requestAllTraffic")) { | 547 | if (type.equals("requestAllTraffic")) { |
... | @@ -537,17 +552,29 @@ public class TopologyViewWebSocket | ... | @@ -537,17 +552,29 @@ public class TopologyViewWebSocket |
537 | requestTraffic(trafficEvent); | 552 | requestTraffic(trafficEvent); |
538 | } | 553 | } |
539 | } | 554 | } |
555 | + } catch (Exception e) { | ||
556 | + log.warn("Unable to handle traffic request due to {}", e.getMessage()); | ||
557 | + } | ||
540 | } | 558 | } |
541 | } | 559 | } |
542 | 560 | ||
543 | - private class SummaryMonitor extends TimerTask { | 561 | + // Accummulates events to drive methodic update of the summary pane. |
544 | - @Override | 562 | + private class InternalEventAccummulator extends AbstractEventAccumulator { |
545 | - public void run() { | 563 | + protected InternalEventAccummulator() { |
546 | - if (summaryEvent != null) { | 564 | + super(new Timer("topo-summary"), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS); |
547 | - requestSummary(summaryEvent); | ||
548 | } | 565 | } |
566 | + | ||
567 | + @Override | ||
568 | + public void processEvents(List<Event> events) { | ||
569 | + try { | ||
570 | + if (summaryEnabled) { | ||
571 | + sendMessage(summmaryMessage(0)); | ||
549 | } | 572 | } |
573 | + } catch (Exception e) { | ||
574 | + log.warn("Unable to handle summary request due to {}", e.getMessage()); | ||
550 | } | 575 | } |
551 | 576 | ||
577 | + } | ||
578 | + } | ||
552 | } | 579 | } |
553 | 580 | ... | ... |
... | @@ -356,6 +356,9 @@ | ... | @@ -356,6 +356,9 @@ |
356 | hideInstances(); | 356 | hideInstances(); |
357 | } else if (summaryPane.isVisible()) { | 357 | } else if (summaryPane.isVisible()) { |
358 | cancelSummary(); | 358 | cancelSummary(); |
359 | + stopAntTimer(); | ||
360 | + } else { | ||
361 | + hoverMode = hoverModeFlows; | ||
359 | } | 362 | } |
360 | } | 363 | } |
361 | 364 | ... | ... |
-
Please register or login to post a comment