1
28 package demo.view.networkmonitoring;
29
30 import org.w3c.dom.Element;
31 import y.base.DataMap;
32 import y.base.Edge;
33 import y.base.EdgeCursor;
34 import y.base.EdgeList;
35 import y.base.Node;
36 import y.base.NodeCursor;
37 import y.base.NodeMap;
38 import y.base.YList;
39 import y.io.GraphMLIOHandler;
40 import y.io.graphml.KeyScope;
41 import y.io.graphml.KeyType;
42 import y.io.graphml.input.DeserializationEvent;
43 import y.io.graphml.input.DeserializationHandler;
44 import y.io.graphml.input.GraphMLParseException;
45 import y.util.DataProviderAdapter;
46 import y.util.GraphCopier;
47 import y.util.Maps;
48 import y.view.Graph2D;
49
50 import javax.swing.Timer;
51 import java.awt.event.ActionEvent;
52 import java.awt.event.ActionListener;
53 import java.io.IOException;
54 import java.net.URL;
55 import java.util.Iterator;
56 import java.util.Random;
57
58
67 public class NetworkModelImpl implements NetworkModel {
68
69
72 private static final int MAX_WAITING_CYCLES = 10;
73
76 private static final int MAX_DATA_AMOUNT = 15;
77
80 private static final double DATA_GENERATION_PROBABILITY = 0.02;
81
85 private final DataMap statusMap;
86
89 private final DataMap volumeMap;
90
94 private final DataMap loadMap;
95 private final NodeMap nodeKind;
96 private final NodeMap nodeInfo;
97 private boolean canFailure;
98 private final Random random = new Random(666);
99
100 private final YList observerList;
101
102 private final Graph2D graph;
103
104 private final Timer timer;
105
106
107 public NetworkModelImpl(URL resource) {
108 observerList = new YList();
109 graph = new Graph2D();
110 graph.addDataProvider(ELEMENT_ID_DPKEY, new DataProviderAdapter() {
112 public Object get(Object dataHolder) {
113 return dataHolder;
114 }
115 });
116 statusMap = Maps.createHashedDataMap();
117 loadMap = Maps.createHashedDataMap();
118 nodeKind = Maps.createHashedNodeMap();
119 volumeMap = Maps.createHashedDataMap();
120 nodeInfo = Maps.createHashedNodeMap();
121
122 graph.addDataProvider(NetworkModel.NODE_TYPE_DPKEY,nodeKind);
123 graph.addDataProvider(NetworkModel.ELEMENT_CAPACITY_DPKEY,volumeMap);
124 graph.addDataProvider(NetworkModel.NODE_INFO_DPKEY, nodeInfo);
125
126 loadNetworkGraph(resource);
127 for (int i = 0; i < 40; i++) {
129 updateState();
130 }
131 timer = new Timer(1500, new ActionListener() {
135 public void actionPerformed(ActionEvent e) {
136 updateState();
137 notifyObserver(statusMap);
138 }
139 });
140 timer.start();
141 }
142
143
147 private void loadNetworkGraph(URL resource) {
148 final GraphMLIOHandler ioh = new GraphMLIOHandler();
149 ioh.getGraphMLHandler().addInputDataAcceptor("NetworkMonitoring.Volume",volumeMap,KeyScope.ALL,KeyType.INT);
151 ioh.getGraphMLHandler().addInputDataAcceptor("NetworkMonitoring.NodeKind", nodeKind, KeyScope.NODE, KeyType.INT);
152 ioh.getGraphMLHandler().addInputDataAcceptor("NetworkMonitoring.NodeInfo", nodeInfo, KeyScope.NODE,
153 new DeserializationHandler() {
154 public void onHandleDeserialization(DeserializationEvent event) throws GraphMLParseException {
155 final Element element = (Element) event.getXmlNode();
156 event.setResult(new NetworkNodeInfo(element.getAttribute("Name"), element.getAttribute("IP")));
157 }
158 });
159 try {
160 ioh.read(graph, resource);
161 } catch (IOException e1) {
162 e1.printStackTrace();
163 }
164 for (final NodeCursor nodeCursor = graph.nodes();nodeCursor.ok();nodeCursor.next()) {
166 loadMap.set(nodeCursor.node(),new YList());
167 }
168 for (final EdgeCursor edges = graph.edges();edges.ok();edges.next()) {
169 loadMap.set(edges.edge(),new YList());
170 }
171 }
172
173
177 private void updateState() {
178 boolean hasCrashed = false;
180 for (final EdgeCursor edges = graph.edges(); edges.ok(); edges.next()) {
181 final Edge edge = edges.edge();
182 if (!hasCrashed) {
183 hasCrashed = tryCrash(edge);
184 }
185 if (isOK(edge)) {
186 updateEdge(edge);
187 }
188 }
189 for (final NodeCursor nodes = graph.nodes(); nodes.ok(); nodes.next()) {
190 final Node node = nodes.node();
191 if (!hasCrashed) {
192 hasCrashed = tryCrash(node);
193 }
194 if (isOK(node)) {
195 switch (nodeKind.getInt(node)) {
196 case PC:
197 case LAPTOP:
198 case SMARTPHONE:
199 updatePC(node);
200 break;
201 case SWITCH:
202 case WLAN:
203 updateSwitch(node);
204 break;
205 case SERVER:
206 case DATABASE:
207 updateServer(node);
208 break;
209 }
210 }
211 }
212 for (final NodeCursor nodes = graph.nodes(); nodes.ok(); nodes.next()) {
214 final Node node = nodes.node();
215 if (isOK(node)) {
216 final double value = (double) ((YList) loadMap.get(node)).size() / (double) volumeMap.getInt(node);
217 statusMap.setDouble(node, value);
218 }
219 }
220 for (final EdgeCursor edges = graph.edges(); edges.ok(); edges.next()) {
221 final Edge edge = edges.edge();
222 if (isOK(edge)) {
223 final double value = (double) ((YList) loadMap.get(edge)).size() / (double) volumeMap.getInt(edge);
224 statusMap.setDouble(edge, value);
225 }
226 }
227 }
228
229
235 private void updateServer(final Node node) {
236 final YList packetQueue = (YList) loadMap.get(node);
237 dropOldPackets(packetQueue);
238 final YList unsentPackets = new YList();
239 final int serverVolume = volumeMap.getInt(node);
240 for (final Iterator iterator = packetQueue.iterator(); iterator.hasNext(); ) {
241 DataPacket packet = (DataPacket) iterator.next();
242 Edge edge = node.getEdge(packet.source);
244 if ((packet.getWaitingCycles() > 0) && isOK(edge)) {
245 final YList edgeQueue = (YList) loadMap.get(edge);
246 final int edgeVolume = volumeMap.getInt(edge);
247 if (edgeVolume > edgeQueue.size()) {
249 packet.setSource(node);
250 packet.resetWaitingCycles();
251 edgeQueue.add(packet);
252 iterator.remove();
253 final int newPackages = random.nextInt(3);
255 for (int i = 0; i < newPackages; i++) {
256 if (edgeVolume > edgeQueue.size()) {
257 edgeQueue.add(new DataPacket(node));
258 } else if (serverVolume - unsentPackets.size() > packetQueue.size()) {
259 packet = new DataPacket(edge.opposite(node));
260 unsentPackets.add(packet);
261 }
262 }
263 } else {
264 packet.incrementWaitingCycles();
265 }
266 } else {
267 packet.incrementWaitingCycles();
268 }
269 }
270 packetQueue.addAll(unsentPackets);
272 }
273
274
280 private void updateSwitch(final Node node) {
281 final YList switchQueue = (YList) loadMap.get(node);
282 dropOldPackets(switchQueue);
283 for (final Iterator iterator = switchQueue.iterator(); iterator.hasNext(); ) {
285 final DataPacket packet = (DataPacket) iterator.next();
286 if (packet.getWaitingCycles() > 0) {
288 final Edge edge = getBestEdge(node.edges(), packet.getSource());
289 if (edge != null) {
290 final YList edgeLoad = (YList) loadMap.get(edge);
291 packet.setSource(node);
292 packet.resetWaitingCycles();
293 edgeLoad.add(packet);
294 iterator.remove();
295 } else {
296 packet.incrementWaitingCycles();
297 }
298 } else {
299 packet.incrementWaitingCycles();
300 }
301 }
302
303 }
304
305
312 private Edge getBestEdge(final EdgeCursor edges, final Node source) {
313 EdgeList bestEdges = new EdgeList();
314 int bestSpace = 0;
315 for (; edges.ok(); edges.next()) {
316 Edge edge = edges.edge();
317 if (edge.target() != source && edge.source() != source && isOK(edge)) {
318 int edgeSpace = volumeMap.getInt(edge) - ((YList) loadMap.get(edge)).size();
319 if (edgeSpace > bestSpace) {
320 bestEdges = new EdgeList(edge);
321 bestSpace = edgeSpace;
322 } else if (edgeSpace > 0 && edgeSpace == bestSpace) {
323 bestEdges.add(edge);
324 }
325 }
326 }
327 if (bestEdges.isEmpty()) {
328 return null;
329 } else {
330 return (Edge) bestEdges.get(random.nextInt(bestEdges.size()));
332 }
333 }
334
335
340 private void updatePC(final Node node) {
341 final YList load = (YList) loadMap.get(node);
342 dropOldPackets(load);
343 final int volume = volumeMap.getInt(node);
344 final Edge edge = node.edges().edge();
346 if (isOK(edge)) {
347 final YList edgeLoad = (YList) loadMap.get(edge);
348 int availableEdgeSpace = volumeMap.getInt(edge) - edgeLoad.size();
349 for (final Iterator iterator = load.iterator(); iterator.hasNext(); ) {
351 final DataPacket packet = (DataPacket) iterator.next();
352 if (packet.getWaitingCycles() > 0) {
353 if (packet.getSource() != node) {
354 iterator.remove();
355 } else if (availableEdgeSpace > 0) {
356 edgeLoad.add(packet);
357 packet.resetWaitingCycles();
358 availableEdgeSpace--;
359 iterator.remove();
360 } else {
362 packet.incrementWaitingCycles();
363 }
364 } else {
365 packet.incrementWaitingCycles();
366 }
367 }
368 if (random.nextDouble() <= DATA_GENERATION_PROBABILITY) {
370 final int dataAmount = random.nextInt(MAX_DATA_AMOUNT);
371 for (int i = 0; i < dataAmount; i++) {
372 final DataPacket packet = new DataPacket(node);
373 if (availableEdgeSpace > 0) {
374 edgeLoad.add(packet);
375 availableEdgeSpace--;
376 } else if (volume > load.size()) {
377 load.add(packet);
378 } else {
379 break;
381 }
382 }
383 }
384 }
385 }
386
387
391 private void updateEdge(final Edge edge) {
392 final YList edgeLoad = (YList) loadMap.get(edge);
393 dropOldPackets(edgeLoad);
394 final Node source = edge.source();
395 final Node target = edge.target();
396 final YList sourceLoad = (YList) loadMap.get(source);
397 final YList targetLoad = (YList) loadMap.get(target);
398 int availableSpaceSource = volumeMap.getInt(source) - sourceLoad.size();
399 int availableSpaceTarget = volumeMap.getInt(target) - targetLoad.size();
400 for (final Iterator iterator = edgeLoad.iterator(); iterator.hasNext(); ) {
401 DataPacket packet = (DataPacket) iterator.next();
402 if ((packet.getSource() == source) && (availableSpaceTarget > 0)) {
403 targetLoad.add(packet);
405 packet.resetWaitingCycles();
406 availableSpaceTarget--;
407 iterator.remove();
408 } else if ((packet.getSource() == target) && (availableSpaceSource > 0)) {
409 sourceLoad.add(packet);
411 packet.resetWaitingCycles();
412 availableSpaceSource--;
413 iterator.remove();
414 } else {
415 packet.incrementWaitingCycles();
417 }
418 }
419 }
420
421
425 private void dropOldPackets(YList load) {
426 for (final Iterator iterator = load.iterator();iterator.hasNext();) {
427 final DataPacket next = (DataPacket) iterator.next();
428 if (next.getWaitingCycles() > MAX_WAITING_CYCLES) {
429 iterator.remove();
430 }
431 }
432 }
433
434
440 private boolean tryCrash(Object id) {
441 if (canFailure && random.nextInt(3000) == 0) {
442 statusMap.setDouble(id, -2);
443 loadMap.set(id,new YList());
444 if (id instanceof Node) {
445 Node node = (Node) id;
446 for (final EdgeCursor edgeCursor = node.edges();edgeCursor.ok();edgeCursor.next()) {
447 disableConnection(edgeCursor.edge());
448 }
449 }
450 return true;
451 }
452 return false;
453 }
454
455
458 private void notifyObserver(DataMap sendMap) {
459 final Iterator iterator = observerList.iterator();
460 while (iterator.hasNext()) {
461 final NetworkModelObserver observer = (NetworkModelObserver) iterator.next();
462 observer.update(sendMap);
463 }
464 }
465
466 public void addObserver(final NetworkModelObserver observer) {
467 observerList.add(observer);
468 }
469
470 public void removeObserver(final NetworkModelObserver observer) {
471 observerList.remove(observer);
472 }
473
474 public Graph2D getNetworkModel() {
475 final GraphCopier graphCopier = new GraphCopier();
476 graphCopier.setCopyFactory(graph.getGraphCopyFactory());
477 graphCopier.setDataProviderContentCopying(true);
478 return (Graph2D) graphCopier.copy(graph);
479 }
480
481
486 public boolean isOK(final Object id) {
487 return statusMap.getDouble(id) >= 0;
488 }
489
490 public void enableNetworkNode(final Object id) {
491 DataMap sendMap = Maps.createHashedDataMap();
492 statusMap.setDouble(id, 0);
493 final Node node = (Node) id;
494 for (final EdgeCursor edges = node.edges(); edges.ok(); edges.next()) {
495 final Edge edge = edges.edge();
496 if (isOK(edge.opposite(node)) && statusMap.getDouble(edge) != -2) {
497 enableConnection(edge);
498 statusMap.set(edge, new Double(0));
499 sendMap.set(edge,new Double(0));
500 }
501 }
502 sendMap.set(id,new Double(0));
503 notifyObserver(sendMap);
504 }
505
506 public void disableNetworkNode(final Object id) {
507 DataMap sendMap = Maps.createHashedDataMap();
508 statusMap.setDouble(id, -1);
509 loadMap.set(id,new YList());
510 for (final EdgeCursor edges = ((Node) id).edges(); edges.ok(); edges.next()) {
511 final Edge edge = edges.edge();
512 if (isOK(edge)) {
513 sendMap.set(edge,new Double(-1));
514 statusMap.setDouble(edge, -1);
515 loadMap.set(edge, new YList());
516 }
517 }
518 sendMap.set(id,new Double(0));
519 notifyObserver(sendMap);
520 }
521
522 public void enableConnection(final Object id) {
523 DataMap sendMap = Maps.createHashedDataMap();
524 sendMap.setDouble(id,0);
525 statusMap.set(id, new Double(0));
526 notifyObserver(sendMap);
527 }
528
529 public void disableConnection(final Object id) {
530 if (isOK(id)) {
531 DataMap sendMap = Maps.createHashedDataMap();
532 statusMap.setDouble(id, -1);
533 sendMap.set(id, new Double(-1));
534 loadMap.set(id, new YList());
535 notifyObserver(sendMap);
536 }
537 }
538
539 public void repairNetworkNode(final Object id) {
540 enableNetworkNode(id);
541 }
542
543 public void repairEdge(final Object id) {
544 statusMap.setDouble(id, 0);
545 DataMap sendMap = Maps.createHashedDataMap();
546 sendMap.set(id,new Double(0));
547 notifyObserver(sendMap);
548 }
549
550 public void setUpdateCycle(final int duration) {
551 timer.setDelay(duration);
552 }
553
554 public int getUpdateCycle() {
555 return timer.getDelay();
556 }
557
558 public void setNetworkErrorsEnabled(boolean errorsEnabled) {
559 this.canFailure = errorsEnabled;
560 if (!errorsEnabled) {
561 for (final NodeCursor nodes = graph.nodes(); nodes.ok(); nodes.next()) {
563 final Node node = nodes.node();
564 if (statusMap.getDouble(node) == -2) {
565 repairNetworkNode(node);
566 }
567 }
568 for (final EdgeCursor edges = graph.edges(); edges.ok(); edges.next()) {
569 final Edge edge = edges.edge();
570 if (statusMap.getDouble(edge) == -2) {
571 repairEdge(edge);
572 }
573 }
574 }
575 }
576
577 public boolean isNetworkErrorsEnabled() {
578 return canFailure;
579 }
580
581
584 private class DataPacket {
585 private Node source;
586 private int waitingCycles;
587
588 private DataPacket(Node source) {
589 this.source = source;
590 }
591
592 public Node getSource() {
593 return source;
594 }
595
596 public void setSource(final Node source) {
597 this.source = source;
598 }
599
600 public void incrementWaitingCycles() {
601 waitingCycles++;
602 }
603
604 public void resetWaitingCycles() {
605 waitingCycles = 0;
606 }
607
608 public int getWaitingCycles() {
609 return waitingCycles;
610 }
611 }
612 }
613