Committed by
Gerrit Code Review
ONOS-2328 GUI -- Started work on seeing multiple links between devices on the to…
…pology view. Device links are now grouped based on what device they are between. Also minor bug fixes and investigations into other bugs. WIP. Change-Id: I444f016268efc5c489ba6ad0282d0f7827fff462
Showing
4 changed files
with
94 additions
and
16 deletions
... | @@ -367,6 +367,7 @@ | ... | @@ -367,6 +367,7 @@ |
367 | .classed('linkLabel', true) | 367 | .classed('linkLabel', true) |
368 | .attr('id', function (d) { return d.id; }); | 368 | .attr('id', function (d) { return d.id; }); |
369 | 369 | ||
370 | + // FIXME: x and y position calculated here, use link.position obj | ||
370 | entering.each(function (d) { | 371 | entering.each(function (d) { |
371 | var el = d3.select(this), | 372 | var el = d3.select(this), |
372 | rect, | 373 | rect, |
... | @@ -410,6 +411,7 @@ | ... | @@ -410,6 +411,7 @@ |
410 | return box; | 411 | return box; |
411 | } | 412 | } |
412 | 413 | ||
414 | + // FIXME: x and y position calculated here | ||
413 | function transformLabel(p) { | 415 | function transformLabel(p) { |
414 | var dx = p.x2 - p.x1, | 416 | var dx = p.x2 - p.x1, |
415 | dy = p.y2 - p.y1, | 417 | dy = p.y2 - p.y1, | ... | ... |
... | @@ -24,8 +24,7 @@ | ... | @@ -24,8 +24,7 @@ |
24 | 24 | ||
25 | // injected refs | 25 | // injected refs |
26 | var $log, $timeout, fs, sus, is, ts, flash, wss, | 26 | var $log, $timeout, fs, sus, is, ts, flash, wss, |
27 | - tis, tms, td3, tss, tts, tos, fltr, tls, | 27 | + tis, tms, td3, tss, tts, tos, fltr, tls, uplink, svg; |
28 | - icfg, uplink, svg; | ||
29 | 28 | ||
30 | // configuration | 29 | // configuration |
31 | var linkConfig = { | 30 | var linkConfig = { |
... | @@ -50,6 +49,7 @@ | ... | @@ -50,6 +49,7 @@ |
50 | network = { | 49 | network = { |
51 | nodes: [], | 50 | nodes: [], |
52 | links: [], | 51 | links: [], |
52 | + linksByDevice: {}, | ||
53 | lookup: {}, | 53 | lookup: {}, |
54 | revLinkToKey: {} | 54 | revLinkToKey: {} |
55 | }, | 55 | }, |
... | @@ -215,6 +215,7 @@ | ... | @@ -215,6 +215,7 @@ |
215 | d = tms.createLink(data); | 215 | d = tms.createLink(data); |
216 | if (d) { | 216 | if (d) { |
217 | network.links.push(d); | 217 | network.links.push(d); |
218 | + aggregateLink(d, data); | ||
218 | lu[d.key] = d; | 219 | lu[d.key] = d; |
219 | updateLinks(); | 220 | updateLinks(); |
220 | fStart(); | 221 | fStart(); |
... | @@ -241,10 +242,40 @@ | ... | @@ -241,10 +242,40 @@ |
241 | 242 | ||
242 | // ======================== | 243 | // ======================== |
243 | 244 | ||
245 | + function makeNodeKey(node1, node2) { | ||
246 | + return node1 + '-' + node2; | ||
247 | + } | ||
248 | + | ||
249 | + function findNodePair(key, keyRev) { | ||
250 | + if (network.linksByDevice[key]) { | ||
251 | + return key; | ||
252 | + } else if (network.linksByDevice[keyRev]) { | ||
253 | + return keyRev; | ||
254 | + } else { | ||
255 | + return false; | ||
256 | + } | ||
257 | + } | ||
258 | + | ||
259 | + function aggregateLink(ldata, link) { | ||
260 | + var key = makeNodeKey(link.src, link.dst), | ||
261 | + keyRev = makeNodeKey(link.dst, link.src), | ||
262 | + found = findNodePair(key, keyRev); | ||
263 | + | ||
264 | + if (found) { | ||
265 | + network.linksByDevice[found].push(ldata); | ||
266 | + ldata.devicePair = found; | ||
267 | + } else { | ||
268 | + network.linksByDevice[key] = [ ldata ]; | ||
269 | + ldata.devicePair = key; | ||
270 | + } | ||
271 | + } | ||
272 | + | ||
244 | function addLinkUpdate(ldata, link) { | 273 | function addLinkUpdate(ldata, link) { |
245 | // add link event, but we already have the reverse link installed | 274 | // add link event, but we already have the reverse link installed |
246 | ldata.fromTarget = link; | 275 | ldata.fromTarget = link; |
247 | rlk[link.id] = ldata.key; | 276 | rlk[link.id] = ldata.key; |
277 | + // possible solution to el being undefined in restyleLinkElement: | ||
278 | + //_updateLinks(); | ||
248 | restyleLinkElement(ldata); | 279 | restyleLinkElement(ldata); |
249 | } | 280 | } |
250 | 281 | ||
... | @@ -267,7 +298,12 @@ | ... | @@ -267,7 +298,12 @@ |
267 | delay = immediate ? 0 : 1000; | 298 | delay = immediate ? 0 : 1000; |
268 | 299 | ||
269 | // FIXME: understand why el is sometimes undefined on addLink events... | 300 | // FIXME: understand why el is sometimes undefined on addLink events... |
270 | - if (el) { | 301 | + // Investigated: |
302 | + // el is undefined when it's a reverse link that is being added. | ||
303 | + // updateLinks (which sets ldata.el) isn't called before this is called. | ||
304 | + // Calling _updateLinks in addLinkUpdate fixes it, but there might be | ||
305 | + // a more efficient way to fix it. | ||
306 | + if (el && !el.empty()) { | ||
271 | el.classed('link', true); | 307 | el.classed('link', true); |
272 | el.classed('inactive', !online); | 308 | el.classed('inactive', !online); |
273 | el.classed(allLinkTypes, false); | 309 | el.classed(allLinkTypes, false); |
... | @@ -383,7 +419,7 @@ | ... | @@ -383,7 +419,7 @@ |
383 | d.metaUi = metaUi; | 419 | d.metaUi = metaUi; |
384 | wss.sendEvent('updateMeta', { | 420 | wss.sendEvent('updateMeta', { |
385 | id: d.id, | 421 | id: d.id, |
386 | - 'class': d.class, | 422 | + class: d.class, |
387 | memento: metaUi | 423 | memento: metaUi |
388 | }); | 424 | }); |
389 | } | 425 | } |
... | @@ -503,7 +539,11 @@ | ... | @@ -503,7 +539,11 @@ |
503 | .attr({ | 539 | .attr({ |
504 | id: function (d) { return sus.safeId(d.id); }, | 540 | id: function (d) { return sus.safeId(d.id); }, |
505 | class: mkSvgClass, | 541 | class: mkSvgClass, |
506 | - transform: function (d) { return sus.translate(d.x, d.y); }, | 542 | + transform: function (d) { |
543 | + // sometimes says d.x and d.y are NaN? | ||
544 | + // I have a feeling it's a timing issue | ||
545 | + return sus.translate(d.x, d.y); | ||
546 | + }, | ||
507 | opacity: 0 | 547 | opacity: 0 |
508 | }) | 548 | }) |
509 | .call(drag) | 549 | .call(drag) |
... | @@ -548,6 +588,9 @@ | ... | @@ -548,6 +588,9 @@ |
548 | link = linkG.selectAll('.link') | 588 | link = linkG.selectAll('.link') |
549 | .data(network.links, function (d) { return d.key; }); | 589 | .data(network.links, function (d) { return d.key; }); |
550 | 590 | ||
591 | + // This seems to do nothing? I've only triggered it on timeout errors | ||
592 | + // when adding links, link var is empty because there aren't any links | ||
593 | + // when removing links, link var is empty already | ||
551 | // operate on existing links: | 594 | // operate on existing links: |
552 | link.each(function (d) { | 595 | link.each(function (d) { |
553 | // this is supposed to be an existing link, but we have observed | 596 | // this is supposed to be an existing link, but we have observed |
... | @@ -559,6 +602,7 @@ | ... | @@ -559,6 +602,7 @@ |
559 | }); | 602 | }); |
560 | 603 | ||
561 | // operate on entering links: | 604 | // operate on entering links: |
605 | + // FIXME: x and y position calculated here - calculate position and add it to the link | ||
562 | var entering = link.enter() | 606 | var entering = link.enter() |
563 | .append('line') | 607 | .append('line') |
564 | .attr({ | 608 | .attr({ |
... | @@ -620,6 +664,7 @@ | ... | @@ -620,6 +664,7 @@ |
620 | nodeAttr: { | 664 | nodeAttr: { |
621 | transform: function (d) { return sus.translate(d.x, d.y); } | 665 | transform: function (d) { return sus.translate(d.x, d.y); } |
622 | }, | 666 | }, |
667 | + // FIXME: x and y position calculated here, will be deleted | ||
623 | linkAttr: { | 668 | linkAttr: { |
624 | x1: function (d) { return d.source.x; }, | 669 | x1: function (d) { return d.source.x; }, |
625 | y1: function (d) { return d.source.y; }, | 670 | y1: function (d) { return d.source.y; }, |
... | @@ -630,6 +675,7 @@ | ... | @@ -630,6 +675,7 @@ |
630 | transform: function (d) { | 675 | transform: function (d) { |
631 | var lnk = tms.findLinkById(d.key); | 676 | var lnk = tms.findLinkById(d.key); |
632 | if (lnk) { | 677 | if (lnk) { |
678 | + // FIXME: x and y position calculated here, use link.position object | ||
633 | return td3.transformLabel({ | 679 | return td3.transformLabel({ |
634 | x1: lnk.source.x, | 680 | x1: lnk.source.x, |
635 | y1: lnk.source.y, | 681 | y1: lnk.source.y, |
... | @@ -643,9 +689,16 @@ | ... | @@ -643,9 +689,16 @@ |
643 | 689 | ||
644 | function tick() { | 690 | function tick() { |
645 | // guard against null (which can happen when our view pages out)... | 691 | // guard against null (which can happen when our view pages out)... |
646 | - if (node) node.attr(tickStuff.nodeAttr); | 692 | + if (node) { |
647 | - if (link) link.attr(tickStuff.linkAttr); | 693 | + node.attr(tickStuff.nodeAttr); |
648 | - if (linkLabel) linkLabel.attr(tickStuff.linkLabelAttr); | 694 | + } |
695 | + if (link) { | ||
696 | + // FIXME: instead of tickStuff here, use link.position object | ||
697 | + link.attr(tickStuff.linkAttr); | ||
698 | + } | ||
699 | + if (linkLabel) { | ||
700 | + linkLabel.attr(tickStuff.linkLabelAttr); | ||
701 | + } | ||
649 | } | 702 | } |
650 | 703 | ||
651 | 704 | ||
... | @@ -734,7 +787,7 @@ | ... | @@ -734,7 +787,7 @@ |
734 | showHosts: function () { return showHosts; }, | 787 | showHosts: function () { return showHosts; }, |
735 | restyleLinkElement: restyleLinkElement, | 788 | restyleLinkElement: restyleLinkElement, |
736 | updateLinkLabelModel: updateLinkLabelModel | 789 | updateLinkLabelModel: updateLinkLabelModel |
737 | - } | 790 | + }; |
738 | } | 791 | } |
739 | 792 | ||
740 | function mkSelectApi(uplink) { | 793 | function mkSelectApi(uplink) { |
... | @@ -755,7 +808,7 @@ | ... | @@ -755,7 +808,7 @@ |
755 | hovered: tss.hovered, | 808 | hovered: tss.hovered, |
756 | validateSelectionContext: tss.validateSelectionContext, | 809 | validateSelectionContext: tss.validateSelectionContext, |
757 | selectOrder: tss.selectOrder | 810 | selectOrder: tss.selectOrder |
758 | - } | 811 | + }; |
759 | } | 812 | } |
760 | 813 | ||
761 | function mkObliqueApi(uplink, fltr) { | 814 | function mkObliqueApi(uplink, fltr) { |
... | @@ -797,19 +850,18 @@ | ... | @@ -797,19 +850,18 @@ |
797 | 850 | ||
798 | angular.module('ovTopo') | 851 | angular.module('ovTopo') |
799 | .factory('TopoForceService', | 852 | .factory('TopoForceService', |
800 | - ['$log', '$timeout', 'FnService', 'SvgUtilService', 'IconService', | 853 | + ['$log', '$timeout', 'FnService', 'SvgUtilService', |
801 | 'ThemeService', 'FlashService', 'WebSocketService', | 854 | 'ThemeService', 'FlashService', 'WebSocketService', |
802 | 'TopoInstService', 'TopoModelService', | 855 | 'TopoInstService', 'TopoModelService', |
803 | 'TopoD3Service', 'TopoSelectService', 'TopoTrafficService', | 856 | 'TopoD3Service', 'TopoSelectService', 'TopoTrafficService', |
804 | 'TopoObliqueService', 'TopoFilterService', 'TopoLinkService', | 857 | 'TopoObliqueService', 'TopoFilterService', 'TopoLinkService', |
805 | 858 | ||
806 | - function (_$log_, _$timeout_, _fs_, _sus_, _is_, _ts_, _flash_, _wss_, | 859 | + function (_$log_, _$timeout_, _fs_, _sus_, _ts_, _flash_, _wss_, |
807 | _tis_, _tms_, _td3_, _tss_, _tts_, _tos_, _fltr_, _tls_) { | 860 | _tis_, _tms_, _td3_, _tss_, _tts_, _tos_, _fltr_, _tls_) { |
808 | $log = _$log_; | 861 | $log = _$log_; |
809 | $timeout = _$timeout_; | 862 | $timeout = _$timeout_; |
810 | fs = _fs_; | 863 | fs = _fs_; |
811 | sus = _sus_; | 864 | sus = _sus_; |
812 | - is = _is_; | ||
813 | ts = _ts_; | 865 | ts = _ts_; |
814 | flash = _flash_; | 866 | flash = _flash_; |
815 | wss = _wss_; | 867 | wss = _wss_; |
... | @@ -822,8 +874,6 @@ | ... | @@ -822,8 +874,6 @@ |
822 | fltr = _fltr_; | 874 | fltr = _fltr_; |
823 | tls = _tls_; | 875 | tls = _tls_; |
824 | 876 | ||
825 | - icfg = is.iconConfig(); | ||
826 | - | ||
827 | var themeListener = ts.addListener(function () { | 877 | var themeListener = ts.addListener(function () { |
828 | updateLinks(); | 878 | updateLinks(); |
829 | updateNodes(); | 879 | updateNodes(); |
... | @@ -902,12 +952,24 @@ | ... | @@ -902,12 +952,24 @@ |
902 | // clean up internal state | 952 | // clean up internal state |
903 | network.nodes = []; | 953 | network.nodes = []; |
904 | network.links = []; | 954 | network.links = []; |
955 | + network.linksByDevice = {}; | ||
905 | network.lookup = {}; | 956 | network.lookup = {}; |
906 | network.revLinkToKey = {}; | 957 | network.revLinkToKey = {}; |
907 | 958 | ||
908 | linkG = linkLabelG = nodeG = portLabelG = null; | 959 | linkG = linkLabelG = nodeG = portLabelG = null; |
909 | link = linkLabel = node = null; | 960 | link = linkLabel = node = null; |
910 | force = drag = null; | 961 | force = drag = null; |
962 | + | ||
963 | + // clean up $timeout promises | ||
964 | + if (fTimer) { | ||
965 | + $timeout.cancel(fTimer); | ||
966 | + } | ||
967 | + if (fNodesTimer) { | ||
968 | + $timeout.cancel(fNodesTimer); | ||
969 | + } | ||
970 | + if (fLinksTimer) { | ||
971 | + $timeout.cancel(fLinksTimer); | ||
972 | + } | ||
911 | } | 973 | } |
912 | 974 | ||
913 | return { | 975 | return { | ... | ... |
... | @@ -104,6 +104,7 @@ | ... | @@ -104,6 +104,7 @@ |
104 | return {x:x4, y:y4}; | 104 | return {x:x4, y:y4}; |
105 | } | 105 | } |
106 | 106 | ||
107 | + // FIXME: x and y position calculated here, use link.position | ||
107 | function lineSeg(d) { | 108 | function lineSeg(d) { |
108 | return { | 109 | return { |
109 | x1: d.source.x, | 110 | x1: d.source.x, |
... | @@ -200,6 +201,7 @@ | ... | @@ -200,6 +201,7 @@ |
200 | td3.applyPortLabels(data, api.portLabelG()); | 201 | td3.applyPortLabels(data, api.portLabelG()); |
201 | } | 202 | } |
202 | 203 | ||
204 | + // FIXME: x and y position calculated here somewhere | ||
203 | function locatePortLabel(link, src) { | 205 | function locatePortLabel(link, src) { |
204 | var near = src ? 'source' : 'target', | 206 | var near = src ? 'source' : 'target', |
205 | far = src ? 'target' : 'source', | 207 | far = src ? 'target' : 'source', | ... | ... |
... | @@ -36,7 +36,7 @@ | ... | @@ -36,7 +36,7 @@ |
36 | */ | 36 | */ |
37 | 37 | ||
38 | // shorthand | 38 | // shorthand |
39 | - var lu, rlk, nodes, links; | 39 | + var lu, rlk, nodes, links, linksByDevice; |
40 | 40 | ||
41 | var dim; // dimensions of layout [w,h] | 41 | var dim; // dimensions of layout [w,h] |
42 | 42 | ||
... | @@ -185,6 +185,12 @@ | ... | @@ -185,6 +185,12 @@ |
185 | fromSource: link, | 185 | fromSource: link, |
186 | srcPort: link.srcPort, | 186 | srcPort: link.srcPort, |
187 | tgtPort: link.dstPort, | 187 | tgtPort: link.dstPort, |
188 | + position: { | ||
189 | + x1: 0, | ||
190 | + y1: 0, | ||
191 | + x2: 0, | ||
192 | + y2: 0 | ||
193 | + }, | ||
188 | 194 | ||
189 | // functions to aggregate dual link state | 195 | // functions to aggregate dual link state |
190 | type: function () { | 196 | type: function () { |
... | @@ -292,6 +298,11 @@ | ... | @@ -292,6 +298,11 @@ |
292 | 298 | ||
293 | } else { | 299 | } else { |
294 | result.removeRawLink = function () { | 300 | result.removeRawLink = function () { |
301 | + // remove link out of aggregate linksByDevice list | ||
302 | + var linksForDevPair = linksByDevice[ldata.devicePair], | ||
303 | + rmvIdx = fs.find(ldata.key, linksForDevPair, 'key'); | ||
304 | + linksForDevPair.splice(rmvIdx, 1); | ||
305 | + | ||
295 | if (link) { | 306 | if (link) { |
296 | // remove fromSource | 307 | // remove fromSource |
297 | ldata.fromSource = null; | 308 | ldata.fromSource = null; |
... | @@ -393,6 +404,7 @@ | ... | @@ -393,6 +404,7 @@ |
393 | rlk = api.network.revLinkToKey; | 404 | rlk = api.network.revLinkToKey; |
394 | nodes = api.network.nodes; | 405 | nodes = api.network.nodes; |
395 | links = api.network.links; | 406 | links = api.network.links; |
407 | + linksByDevice = api.network.linksByDevice; | ||
396 | } | 408 | } |
397 | 409 | ||
398 | function newDim(_dim_) { | 410 | function newDim(_dim_) { | ... | ... |
-
Please register or login to post a comment