From 23da67335f942457b0d8b1f10e9849eba0eee9f7 Mon Sep 17 00:00:00 2001 From: Martin Quinson Date: Tue, 23 Feb 2016 09:22:01 +0100 Subject: [PATCH] Remove PSG from SimGrid git This was not more visible or better maintained here. It was just useless code dupplication. See also https://github.com/mquinson/simgrid/issues/64 --- contrib/psg/Makefile | 22 - contrib/psg/README.txt | 48 - contrib/psg/configs/bittorrent.txt | 46 - contrib/psg/configs/bittorrentPSG.txt | 48 - contrib/psg/configs/chord.txt | 51 - contrib/psg/configs/chordPSG.txt | 54 - contrib/psg/configs/edaggregation.txt | 57 - contrib/psg/configs/edaggregationPSG.txt | 57 - contrib/psg/configs/symphony.txt | 154 -- contrib/psg/configs/symphonyPSG.txt | 155 -- contrib/psg/lib.jar | Bin 716138 -> 0 bytes contrib/psg/platforms/psg.xml | 20 - contrib/psg/run.sh | 15 - .../src/example/bittorrent/BTObserver.java | 132 -- .../src/example/bittorrent/BitTorrent.java | 1989 ----------------- .../src/example/bittorrent/BitfieldMsg.java | 87 - .../psg/src/example/bittorrent/IntMsg.java | 72 - .../example/bittorrent/NetworkDynamics.java | 289 --- .../bittorrent/NetworkInitializer.java | 105 - .../example/bittorrent/NodeInitializer.java | 170 -- .../src/example/bittorrent/PeerSetMsg.java | 58 - .../src/example/bittorrent/SimpleEvent.java | 79 - .../psg/src/example/bittorrent/SimpleMsg.java | 60 - .../src/example/chord/ChordInitializer.java | 72 - .../psg/src/example/chord/ChordMessage.java | 12 - .../psg/src/example/chord/ChordProtocol.java | 358 --- contrib/psg/src/example/chord/CreateNw.java | 148 -- .../psg/src/example/chord/FinalMessage.java | 14 - .../psg/src/example/chord/LookUpMessage.java | 44 - .../example/chord/MessageCounterObserver.java | 108 - .../psg/src/example/chord/NodeComparator.java | 21 - contrib/psg/src/example/chord/Parameters.java | 7 - .../src/example/chord/TrafficGenerator.java | 54 - .../src/example/edaggregation/AverageED.java | 116 - .../symphony/AdapterIterableNetwork.java | 31 - .../AdapterSymphonyNodeComparator.java | 28 - contrib/psg/src/example/symphony/Handler.java | 19 - .../psg/src/example/symphony/LeaveTest.java | 77 - contrib/psg/src/example/symphony/Message.java | 90 - ...NetworkSizeEstimatorProtocolInterface.java | 13 - .../src/example/symphony/RandomRouteTest.java | 48 - .../src/example/symphony/RingRouteTest.java | 150 -- .../example/symphony/RoutingException.java | 15 - .../SimpleNetworkSizeEstimatorProtocol.java | 23 - .../symphony/SymphonyEstimationProtocol.java | 106 - .../symphony/SymphonyNetworkBuilder.java | 157 -- .../symphony/SymphonyNetworkChecker.java | 123 - .../symphony/SymphonyNetworkManager.java | 864 ------- .../symphony/SymphonyNodeComparator.java | 51 - .../symphony/SymphonyNodeInizializer.java | 59 - .../example/symphony/SymphonyProtocol.java | 530 ----- .../example/symphony/SymphonyStatistics.java | 77 - contrib/psg/src/example/symphony/Tuple.java | 45 - .../symphony/test/NetworkEstimationTest.java | 52 - contrib/psg/src/peersim/Simulator.java | 270 --- contrib/psg/src/peersim/cdsim/CDProtocol.java | 44 - .../psg/src/peersim/cdsim/CDSimulator.java | 221 -- contrib/psg/src/peersim/cdsim/CDState.java | 136 -- .../psg/src/peersim/cdsim/DaemonProtocol.java | 102 - .../psg/src/peersim/cdsim/FullNextCycle.java | 137 -- contrib/psg/src/peersim/cdsim/NextCycle.java | 111 - contrib/psg/src/peersim/cdsim/Shuffle.java | 59 - .../psg/src/peersim/config/CheckConfig.java | 186 -- .../psg/src/peersim/config/ClassFinder.java | 258 --- .../src/peersim/config/ConfigContainer.java | 1011 --------- .../src/peersim/config/ConfigProperties.java | 190 -- .../psg/src/peersim/config/Configuration.java | 668 ------ .../psg/src/peersim/config/FastConfig.java | 191 -- .../config/IllegalParameterException.java | 80 - .../config/MissingParameterException.java | 77 - .../src/peersim/config/NullPrintStream.java | 62 - contrib/psg/src/peersim/config/Operators.java | 163 -- .../src/peersim/config/ParsedProperties.java | 254 --- contrib/psg/src/peersim/core/Cleanable.java | 48 - contrib/psg/src/peersim/core/CommonState.java | 301 --- contrib/psg/src/peersim/core/Control.java | 36 - contrib/psg/src/peersim/core/Fallible.java | 69 - contrib/psg/src/peersim/core/GeneralNode.java | 192 -- .../psg/src/peersim/core/IdleProtocol.java | 160 -- contrib/psg/src/peersim/core/Linkable.java | 80 - .../src/peersim/core/MaliciousProtocol.java | 31 - .../psg/src/peersim/core/ModifiableNode.java | 51 - contrib/psg/src/peersim/core/Network.java | 327 --- contrib/psg/src/peersim/core/Node.java | 83 - .../src/peersim/core/OracleIdleProtocol.java | 103 - .../psg/src/peersim/core/OverlayGraph.java | 221 -- contrib/psg/src/peersim/core/Protocol.java | 39 - contrib/psg/src/peersim/core/Scheduler.java | 186 -- .../src/peersim/dynamics/DynamicNetwork.java | 229 -- .../src/peersim/dynamics/MethodInvoker.java | 204 -- .../src/peersim/dynamics/NodeInitializer.java | 39 - .../peersim/dynamics/OscillatingNetwork.java | 200 -- contrib/psg/src/peersim/dynamics/RandNI.java | 114 - contrib/psg/src/peersim/dynamics/StarNI.java | 104 - .../src/peersim/dynamics/WireByMethod.java | 223 -- .../src/peersim/dynamics/WireFromFile.java | 136 -- .../psg/src/peersim/dynamics/WireGraph.java | 158 -- .../psg/src/peersim/dynamics/WireKOut.java | 82 - .../peersim/dynamics/WireRegRootedTree.java | 77 - .../src/peersim/dynamics/WireRingLattice.java | 80 - .../src/peersim/dynamics/WireScaleFreeBA.java | 84 - .../src/peersim/dynamics/WireScaleFreeDM.java | 126 -- .../psg/src/peersim/dynamics/WireStar.java | 54 - contrib/psg/src/peersim/dynamics/WireWS.java | 92 - .../psg/src/peersim/edsim/CDScheduler.java | 213 -- .../psg/src/peersim/edsim/ControlEvent.java | 89 - contrib/psg/src/peersim/edsim/EDProtocol.java | 47 - .../psg/src/peersim/edsim/EDSimulator.java | 400 ---- contrib/psg/src/peersim/edsim/Heap.java | 391 ---- .../psg/src/peersim/edsim/NextCycleEvent.java | 103 - contrib/psg/src/peersim/edsim/PriorityQ.java | 102 - .../psg/src/peersim/edsim/RandNextCycle.java | 68 - .../src/peersim/edsim/RegRandNextCycle.java | 98 - contrib/psg/src/peersim/edsim/edsim_jsp.xmi | 2 - contrib/psg/src/peersim/edsim/edsim_kdm.xmi | 16 - .../psg/src/peersim/graph/BitMatrixGraph.java | 160 -- .../src/peersim/graph/ConstUndirGraph.java | 185 -- .../psg/src/peersim/graph/FastUndirGraph.java | 95 - contrib/psg/src/peersim/graph/Graph.java | 89 - .../src/peersim/graph/GraphAlgorithms.java | 379 ---- .../psg/src/peersim/graph/GraphFactory.java | 300 --- contrib/psg/src/peersim/graph/GraphIO.java | 295 --- .../src/peersim/graph/NeighbourListGraph.java | 173 -- .../psg/src/peersim/graph/PrefixSubGraph.java | 158 -- .../psg/src/peersim/graph/SubGraphEdges.java | 177 -- .../src/peersim/graph/UndirectedGraph.java | 152 -- .../src/peersim/rangesim/ProcessHandler.java | 37 - .../src/peersim/rangesim/ProcessManager.java | 53 - .../src/peersim/rangesim/RangeSimulator.java | 461 ---- .../peersim/rangesim/TaggedOutputStream.java | 179 -- .../src/peersim/reports/BallExpansion.java | 159 -- .../psg/src/peersim/reports/Clustering.java | 80 - .../peersim/reports/ConnectivityObserver.java | 125 -- .../psg/src/peersim/reports/DegreeStats.java | 187 -- .../src/peersim/reports/GraphObserver.java | 170 -- .../psg/src/peersim/reports/GraphPrinter.java | 142 -- .../psg/src/peersim/reports/GraphStats.java | 150 -- .../src/peersim/reports/MemoryObserver.java | 55 - .../psg/src/peersim/reports/RandRemoval.java | 122 - .../psg/src/peersim/transport/E2ENetwork.java | 144 -- .../src/peersim/transport/E2ETransport.java | 156 -- .../psg/src/peersim/transport/KingParser.java | 166 -- .../psg/src/peersim/transport/RouterInfo.java | 49 - .../psg/src/peersim/transport/Transport.java | 59 - .../transport/TriangularMatrixParser.java | 140 -- .../transport/UniformRandomTransport.java | 123 - .../transport/UniformRouterAssignment.java | 91 - .../transport/UnreliableTransport.java | 129 -- .../psg/src/peersim/util/ExtendedRandom.java | 123 - .../src/peersim/util/FileNameGenerator.java | 87 - .../psg/src/peersim/util/IncrementalFreq.java | 312 --- .../src/peersim/util/IncrementalStats.java | 187 -- .../psg/src/peersim/util/IndexIterator.java | 42 - .../psg/src/peersim/util/LinearIterator.java | 108 - contrib/psg/src/peersim/util/MedianStats.java | 91 - contrib/psg/src/peersim/util/MomentStats.java | 82 - .../psg/src/peersim/util/RandPermutation.java | 178 -- .../src/peersim/util/StringListParser.java | 164 -- .../src/peersim/util/WeightedRandPerm.java | 194 -- contrib/psg/src/peersim/vector/Getter.java | 237 -- .../peersim/vector/GetterSetterFinder.java | 174 -- .../src/peersim/vector/InitVectFromFile.java | 128 -- .../peersim/vector/LinearDistribution.java | 123 - .../psg/src/peersim/vector/Normalizer.java | 114 - .../src/peersim/vector/PeakDistribution.java | 139 -- contrib/psg/src/peersim/vector/Setter.java | 222 -- .../psg/src/peersim/vector/SingleValue.java | 40 - .../peersim/vector/SingleValueComparator.java | 58 - .../src/peersim/vector/SingleValueHolder.java | 95 - .../peersim/vector/SingleValueObserver.java | 124 - .../psg/src/peersim/vector/TestVectors.java | 104 - .../peersim/vector/UniformDistribution.java | 141 -- .../psg/src/peersim/vector/ValueDumper.java | 134 -- contrib/psg/src/peersim/vector/VectAngle.java | 141 -- .../psg/src/peersim/vector/VectControl.java | 90 - contrib/psg/src/peersim/vector/VectCopy.java | 113 - .../src/peersim/vector/VectorComparator.java | 97 - .../src/peersim/vector/VectorObserver.java | 80 - contrib/psg/src/psgsim/NodeHost.java | 74 - contrib/psg/src/psgsim/PSGDynamicNetwork.java | 45 - contrib/psg/src/psgsim/PSGPlatform.java | 329 --- .../psg/src/psgsim/PSGProcessController.java | 68 - contrib/psg/src/psgsim/PSGProcessCycle.java | 59 - contrib/psg/src/psgsim/PSGProcessEvent.java | 62 - .../psg/src/psgsim/PSGProcessLauncher.java | 74 - contrib/psg/src/psgsim/PSGSimulator.java | 99 - contrib/psg/src/psgsim/PSGTask.java | 85 - contrib/psg/src/psgsim/PSGTransport.java | 115 - contrib/psg/src/psgsim/Sizable.java | 18 - contrib/psg/test.sh | 45 - contrib/psg/tutorial.odt | Bin 63343 -> 0 bytes contrib/psg/tutorial.pdf | Bin 115095 -> 0 bytes 192 files changed, 27093 deletions(-) delete mode 100644 contrib/psg/Makefile delete mode 100644 contrib/psg/README.txt delete mode 100644 contrib/psg/configs/bittorrent.txt delete mode 100644 contrib/psg/configs/bittorrentPSG.txt delete mode 100644 contrib/psg/configs/chord.txt delete mode 100644 contrib/psg/configs/chordPSG.txt delete mode 100644 contrib/psg/configs/edaggregation.txt delete mode 100644 contrib/psg/configs/edaggregationPSG.txt delete mode 100644 contrib/psg/configs/symphony.txt delete mode 100644 contrib/psg/configs/symphonyPSG.txt delete mode 100644 contrib/psg/lib.jar delete mode 100644 contrib/psg/platforms/psg.xml delete mode 100755 contrib/psg/run.sh delete mode 100644 contrib/psg/src/example/bittorrent/BTObserver.java delete mode 100644 contrib/psg/src/example/bittorrent/BitTorrent.java delete mode 100644 contrib/psg/src/example/bittorrent/BitfieldMsg.java delete mode 100644 contrib/psg/src/example/bittorrent/IntMsg.java delete mode 100644 contrib/psg/src/example/bittorrent/NetworkDynamics.java delete mode 100644 contrib/psg/src/example/bittorrent/NetworkInitializer.java delete mode 100644 contrib/psg/src/example/bittorrent/NodeInitializer.java delete mode 100644 contrib/psg/src/example/bittorrent/PeerSetMsg.java delete mode 100644 contrib/psg/src/example/bittorrent/SimpleEvent.java delete mode 100644 contrib/psg/src/example/bittorrent/SimpleMsg.java delete mode 100644 contrib/psg/src/example/chord/ChordInitializer.java delete mode 100644 contrib/psg/src/example/chord/ChordMessage.java delete mode 100644 contrib/psg/src/example/chord/ChordProtocol.java delete mode 100644 contrib/psg/src/example/chord/CreateNw.java delete mode 100644 contrib/psg/src/example/chord/FinalMessage.java delete mode 100644 contrib/psg/src/example/chord/LookUpMessage.java delete mode 100644 contrib/psg/src/example/chord/MessageCounterObserver.java delete mode 100644 contrib/psg/src/example/chord/NodeComparator.java delete mode 100644 contrib/psg/src/example/chord/Parameters.java delete mode 100644 contrib/psg/src/example/chord/TrafficGenerator.java delete mode 100644 contrib/psg/src/example/edaggregation/AverageED.java delete mode 100644 contrib/psg/src/example/symphony/AdapterIterableNetwork.java delete mode 100644 contrib/psg/src/example/symphony/AdapterSymphonyNodeComparator.java delete mode 100644 contrib/psg/src/example/symphony/Handler.java delete mode 100644 contrib/psg/src/example/symphony/LeaveTest.java delete mode 100644 contrib/psg/src/example/symphony/Message.java delete mode 100644 contrib/psg/src/example/symphony/NetworkSizeEstimatorProtocolInterface.java delete mode 100644 contrib/psg/src/example/symphony/RandomRouteTest.java delete mode 100644 contrib/psg/src/example/symphony/RingRouteTest.java delete mode 100644 contrib/psg/src/example/symphony/RoutingException.java delete mode 100644 contrib/psg/src/example/symphony/SimpleNetworkSizeEstimatorProtocol.java delete mode 100644 contrib/psg/src/example/symphony/SymphonyEstimationProtocol.java delete mode 100644 contrib/psg/src/example/symphony/SymphonyNetworkBuilder.java delete mode 100644 contrib/psg/src/example/symphony/SymphonyNetworkChecker.java delete mode 100644 contrib/psg/src/example/symphony/SymphonyNetworkManager.java delete mode 100644 contrib/psg/src/example/symphony/SymphonyNodeComparator.java delete mode 100644 contrib/psg/src/example/symphony/SymphonyNodeInizializer.java delete mode 100644 contrib/psg/src/example/symphony/SymphonyProtocol.java delete mode 100644 contrib/psg/src/example/symphony/SymphonyStatistics.java delete mode 100644 contrib/psg/src/example/symphony/Tuple.java delete mode 100644 contrib/psg/src/example/symphony/test/NetworkEstimationTest.java delete mode 100644 contrib/psg/src/peersim/Simulator.java delete mode 100644 contrib/psg/src/peersim/cdsim/CDProtocol.java delete mode 100644 contrib/psg/src/peersim/cdsim/CDSimulator.java delete mode 100644 contrib/psg/src/peersim/cdsim/CDState.java delete mode 100644 contrib/psg/src/peersim/cdsim/DaemonProtocol.java delete mode 100644 contrib/psg/src/peersim/cdsim/FullNextCycle.java delete mode 100644 contrib/psg/src/peersim/cdsim/NextCycle.java delete mode 100644 contrib/psg/src/peersim/cdsim/Shuffle.java delete mode 100644 contrib/psg/src/peersim/config/CheckConfig.java delete mode 100644 contrib/psg/src/peersim/config/ClassFinder.java delete mode 100644 contrib/psg/src/peersim/config/ConfigContainer.java delete mode 100644 contrib/psg/src/peersim/config/ConfigProperties.java delete mode 100644 contrib/psg/src/peersim/config/Configuration.java delete mode 100644 contrib/psg/src/peersim/config/FastConfig.java delete mode 100644 contrib/psg/src/peersim/config/IllegalParameterException.java delete mode 100644 contrib/psg/src/peersim/config/MissingParameterException.java delete mode 100644 contrib/psg/src/peersim/config/NullPrintStream.java delete mode 100644 contrib/psg/src/peersim/config/Operators.java delete mode 100644 contrib/psg/src/peersim/config/ParsedProperties.java delete mode 100644 contrib/psg/src/peersim/core/Cleanable.java delete mode 100644 contrib/psg/src/peersim/core/CommonState.java delete mode 100644 contrib/psg/src/peersim/core/Control.java delete mode 100644 contrib/psg/src/peersim/core/Fallible.java delete mode 100644 contrib/psg/src/peersim/core/GeneralNode.java delete mode 100644 contrib/psg/src/peersim/core/IdleProtocol.java delete mode 100644 contrib/psg/src/peersim/core/Linkable.java delete mode 100644 contrib/psg/src/peersim/core/MaliciousProtocol.java delete mode 100644 contrib/psg/src/peersim/core/ModifiableNode.java delete mode 100644 contrib/psg/src/peersim/core/Network.java delete mode 100644 contrib/psg/src/peersim/core/Node.java delete mode 100644 contrib/psg/src/peersim/core/OracleIdleProtocol.java delete mode 100644 contrib/psg/src/peersim/core/OverlayGraph.java delete mode 100644 contrib/psg/src/peersim/core/Protocol.java delete mode 100644 contrib/psg/src/peersim/core/Scheduler.java delete mode 100644 contrib/psg/src/peersim/dynamics/DynamicNetwork.java delete mode 100644 contrib/psg/src/peersim/dynamics/MethodInvoker.java delete mode 100644 contrib/psg/src/peersim/dynamics/NodeInitializer.java delete mode 100644 contrib/psg/src/peersim/dynamics/OscillatingNetwork.java delete mode 100644 contrib/psg/src/peersim/dynamics/RandNI.java delete mode 100644 contrib/psg/src/peersim/dynamics/StarNI.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireByMethod.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireFromFile.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireGraph.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireKOut.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireRegRootedTree.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireRingLattice.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireScaleFreeBA.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireScaleFreeDM.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireStar.java delete mode 100644 contrib/psg/src/peersim/dynamics/WireWS.java delete mode 100644 contrib/psg/src/peersim/edsim/CDScheduler.java delete mode 100644 contrib/psg/src/peersim/edsim/ControlEvent.java delete mode 100644 contrib/psg/src/peersim/edsim/EDProtocol.java delete mode 100644 contrib/psg/src/peersim/edsim/EDSimulator.java delete mode 100644 contrib/psg/src/peersim/edsim/Heap.java delete mode 100644 contrib/psg/src/peersim/edsim/NextCycleEvent.java delete mode 100644 contrib/psg/src/peersim/edsim/PriorityQ.java delete mode 100644 contrib/psg/src/peersim/edsim/RandNextCycle.java delete mode 100644 contrib/psg/src/peersim/edsim/RegRandNextCycle.java delete mode 100644 contrib/psg/src/peersim/edsim/edsim_jsp.xmi delete mode 100644 contrib/psg/src/peersim/edsim/edsim_kdm.xmi delete mode 100644 contrib/psg/src/peersim/graph/BitMatrixGraph.java delete mode 100644 contrib/psg/src/peersim/graph/ConstUndirGraph.java delete mode 100644 contrib/psg/src/peersim/graph/FastUndirGraph.java delete mode 100644 contrib/psg/src/peersim/graph/Graph.java delete mode 100644 contrib/psg/src/peersim/graph/GraphAlgorithms.java delete mode 100644 contrib/psg/src/peersim/graph/GraphFactory.java delete mode 100644 contrib/psg/src/peersim/graph/GraphIO.java delete mode 100644 contrib/psg/src/peersim/graph/NeighbourListGraph.java delete mode 100644 contrib/psg/src/peersim/graph/PrefixSubGraph.java delete mode 100644 contrib/psg/src/peersim/graph/SubGraphEdges.java delete mode 100644 contrib/psg/src/peersim/graph/UndirectedGraph.java delete mode 100644 contrib/psg/src/peersim/rangesim/ProcessHandler.java delete mode 100644 contrib/psg/src/peersim/rangesim/ProcessManager.java delete mode 100644 contrib/psg/src/peersim/rangesim/RangeSimulator.java delete mode 100644 contrib/psg/src/peersim/rangesim/TaggedOutputStream.java delete mode 100644 contrib/psg/src/peersim/reports/BallExpansion.java delete mode 100644 contrib/psg/src/peersim/reports/Clustering.java delete mode 100644 contrib/psg/src/peersim/reports/ConnectivityObserver.java delete mode 100644 contrib/psg/src/peersim/reports/DegreeStats.java delete mode 100644 contrib/psg/src/peersim/reports/GraphObserver.java delete mode 100644 contrib/psg/src/peersim/reports/GraphPrinter.java delete mode 100644 contrib/psg/src/peersim/reports/GraphStats.java delete mode 100644 contrib/psg/src/peersim/reports/MemoryObserver.java delete mode 100644 contrib/psg/src/peersim/reports/RandRemoval.java delete mode 100644 contrib/psg/src/peersim/transport/E2ENetwork.java delete mode 100644 contrib/psg/src/peersim/transport/E2ETransport.java delete mode 100644 contrib/psg/src/peersim/transport/KingParser.java delete mode 100644 contrib/psg/src/peersim/transport/RouterInfo.java delete mode 100644 contrib/psg/src/peersim/transport/Transport.java delete mode 100644 contrib/psg/src/peersim/transport/TriangularMatrixParser.java delete mode 100644 contrib/psg/src/peersim/transport/UniformRandomTransport.java delete mode 100644 contrib/psg/src/peersim/transport/UniformRouterAssignment.java delete mode 100644 contrib/psg/src/peersim/transport/UnreliableTransport.java delete mode 100644 contrib/psg/src/peersim/util/ExtendedRandom.java delete mode 100644 contrib/psg/src/peersim/util/FileNameGenerator.java delete mode 100644 contrib/psg/src/peersim/util/IncrementalFreq.java delete mode 100644 contrib/psg/src/peersim/util/IncrementalStats.java delete mode 100644 contrib/psg/src/peersim/util/IndexIterator.java delete mode 100644 contrib/psg/src/peersim/util/LinearIterator.java delete mode 100644 contrib/psg/src/peersim/util/MedianStats.java delete mode 100644 contrib/psg/src/peersim/util/MomentStats.java delete mode 100644 contrib/psg/src/peersim/util/RandPermutation.java delete mode 100644 contrib/psg/src/peersim/util/StringListParser.java delete mode 100644 contrib/psg/src/peersim/util/WeightedRandPerm.java delete mode 100644 contrib/psg/src/peersim/vector/Getter.java delete mode 100644 contrib/psg/src/peersim/vector/GetterSetterFinder.java delete mode 100644 contrib/psg/src/peersim/vector/InitVectFromFile.java delete mode 100644 contrib/psg/src/peersim/vector/LinearDistribution.java delete mode 100644 contrib/psg/src/peersim/vector/Normalizer.java delete mode 100644 contrib/psg/src/peersim/vector/PeakDistribution.java delete mode 100644 contrib/psg/src/peersim/vector/Setter.java delete mode 100644 contrib/psg/src/peersim/vector/SingleValue.java delete mode 100644 contrib/psg/src/peersim/vector/SingleValueComparator.java delete mode 100644 contrib/psg/src/peersim/vector/SingleValueHolder.java delete mode 100644 contrib/psg/src/peersim/vector/SingleValueObserver.java delete mode 100644 contrib/psg/src/peersim/vector/TestVectors.java delete mode 100644 contrib/psg/src/peersim/vector/UniformDistribution.java delete mode 100644 contrib/psg/src/peersim/vector/ValueDumper.java delete mode 100644 contrib/psg/src/peersim/vector/VectAngle.java delete mode 100644 contrib/psg/src/peersim/vector/VectControl.java delete mode 100644 contrib/psg/src/peersim/vector/VectCopy.java delete mode 100644 contrib/psg/src/peersim/vector/VectorComparator.java delete mode 100644 contrib/psg/src/peersim/vector/VectorObserver.java delete mode 100644 contrib/psg/src/psgsim/NodeHost.java delete mode 100644 contrib/psg/src/psgsim/PSGDynamicNetwork.java delete mode 100644 contrib/psg/src/psgsim/PSGPlatform.java delete mode 100644 contrib/psg/src/psgsim/PSGProcessController.java delete mode 100644 contrib/psg/src/psgsim/PSGProcessCycle.java delete mode 100644 contrib/psg/src/psgsim/PSGProcessEvent.java delete mode 100644 contrib/psg/src/psgsim/PSGProcessLauncher.java delete mode 100644 contrib/psg/src/psgsim/PSGSimulator.java delete mode 100644 contrib/psg/src/psgsim/PSGTask.java delete mode 100644 contrib/psg/src/psgsim/PSGTransport.java delete mode 100644 contrib/psg/src/psgsim/Sizable.java delete mode 100755 contrib/psg/test.sh delete mode 100644 contrib/psg/tutorial.odt delete mode 100644 contrib/psg/tutorial.pdf diff --git a/contrib/psg/Makefile b/contrib/psg/Makefile deleted file mode 100644 index 93470aec1c..0000000000 --- a/contrib/psg/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -LIB_JARS= lib.jar - -all: compile doc - -compile: - mkdir -p classes - javac -sourcepath src -classpath $(LIB_JARS):../../simgrid.jar -d classes `find -L -name "*.java"` -doc: - mkdir -p doc - javadoc -sourcepath src -classpath $(LIB_JARS):../../simgrid.jar -d doc psgsim -test: - ./test.sh -clean: - rm -rf classes doc outputs -help: - @echo "The following are a valid targets for this Makefile:" - @echo "................ all (the default if no target is provided)" - @echo "................ compile" - @echo "................ doc" - @echo "................ test" - @echo "................ clean" - diff --git a/contrib/psg/README.txt b/contrib/psg/README.txt deleted file mode 100644 index 44359907fa..0000000000 --- a/contrib/psg/README.txt +++ /dev/null @@ -1,48 +0,0 @@ -Mon Jan 26 16:00 CEST 2015 -This is version 1.0 of PeerSimGrid - -1) An overview -2) Preliminaries -3) Compile & Run - --------------------------------------------------------------------------------------------- -1) An overview: -PeerSimGrid (PSG) is an interface developed in Java and allows users to simulate -and execute their code under PeerSim or Simgrid simulator, using PeerSim implementation policy. - -This archive is composed of: -* the src/ directory containing the simulator source and examples -* the configs/ directory containing example of configuration files -* psg.jar, a java archive containing all libraries - - -2) Preliminaries: - Before using psg simulator, you need to make some changes in your configuration file: - * Replace the "UniformRandomTransport" transport protocol by "psgsim.PSGTransport". - * Replace the "simulation.endtime" by "simulation.duration" - * you can define your platform on the configuration file as: - platform path/to/your/file.xml - - -3) Compile & Run: - In short, the way to compile and execute your code is: - Compile it: - $> make compile - - Test it (optional): - $> make test - This test execute two examples, (chord and edaggregation found in the example folder), under the two simulators - and compare their outputs. - - Run it: - $> ./run.sh path/to/your/configuration_file - For example: - $>./run.sh configs/chordPSG.txt - - For the documentation - $> make doc - - For the help command - $> make help - -Note: For more informations please contact khaled.baati@gmail.com \ No newline at end of file diff --git a/contrib/psg/configs/bittorrent.txt b/contrib/psg/configs/bittorrent.txt deleted file mode 100644 index 356b3028df..0000000000 --- a/contrib/psg/configs/bittorrent.txt +++ /dev/null @@ -1,46 +0,0 @@ -#Config file for BitTorrent extension - -random.seed 1234567890 -simulation.endtime 1800000#6^8 -simulation.logtime 10^3 -OutputName bittorrent -simulation.experiments 1 - -network.size 30 -network.node peersim.core.GeneralNode - -protocol.urt UniformRandomTransport -protocol.urt.mindelay 10 -protocol.urt.maxdelay 400 - -#BE AWARE: the value "max_swarm_size" must be greater than -#the value "peerset_size", since I have to be sure -#that the space for the neighbor nodes is enough. - -protocol.bittorrent example.bittorrent.BitTorrent -protocol.bittorrent.file_size 100 -protocol.bittorrent.max_swarm_size 80 -protocol.bittorrent.peerset_size 50 -protocol.bittorrent.duplicated_requests 1 -protocol.bittorrent.transport urt -protocol.bittorrent.max_growth 20 - -init.net example.bittorrent.NetworkInitializer -init.net.protocol bittorrent -init.net.transport urt -init.net.newer_distr 80 -init.net.seeder_distr 15 - -control.observer example.bittorrent.BTObserver -control.observer.protocol bittorrent -control.observer.step 10000 - -control.dynamics example.bittorrent.NetworkDynamics -control.dynamics.protocol bittorrent -control.dynamics.newer_distr 60 -control.dynamics.minsize 20 -control.dynamics.tracker_can_die 1 -control.dynamics.step 100000 -control.dynamics.transport urt -control.dynamics.add 0#5 -control.dynamics.remove 0#5 \ No newline at end of file diff --git a/contrib/psg/configs/bittorrentPSG.txt b/contrib/psg/configs/bittorrentPSG.txt deleted file mode 100644 index 647ccb4333..0000000000 --- a/contrib/psg/configs/bittorrentPSG.txt +++ /dev/null @@ -1,48 +0,0 @@ -#Config file for BitTorrent extension -OutputName bittorrent -platform platforms/psg.xml -unit ms -random.seed 1234567890 -simulation.duration 1800000 -simulation.logtime 10^3 - -simulation.experiments 1 - -network.size 40 -network.node peersim.core.GeneralNode - -protocol.urt psgsim.PSGTransport -protocol.urt.mindelay 0#10 -protocol.urt.maxdelay 0#400 - -#BE AWARE: the value "max_swarm_size" must be greater than -#the value "peerset_size", since I have to be sure -#that the space for the neighbor nodes is enough. - -protocol.bittorrent example.bittorrent.BitTorrent -protocol.bittorrent.file_size 100 -protocol.bittorrent.max_swarm_size 80 -protocol.bittorrent.peerset_size 50 -protocol.bittorrent.duplicated_requests 1 -protocol.bittorrent.transport urt -protocol.bittorrent.max_growth 20 - -init.net example.bittorrent.NetworkInitializer -init.net.protocol bittorrent -init.net.transport urt -init.net.newer_distr 80 -init.net.seeder_distr 15 - -control.observer example.bittorrent.BTObserver -control.observer.protocol bittorrent -control.observer.step 10000 - -control.dynamics example.bittorrent.NetworkDynamics -control.dynamics.protocol bittorrent -control.dynamics.newer_distr 60 -control.dynamics.minsize 20 -control.dynamics.tracker_can_die 1 -control.dynamics.step 100000 -control.dynamics.transport urt -control.dynamics.add 0#5 -control.dynamics.remove 0#5 \ No newline at end of file diff --git a/contrib/psg/configs/chord.txt b/contrib/psg/configs/chord.txt deleted file mode 100644 index deeee8f4d5..0000000000 --- a/contrib/psg/configs/chord.txt +++ /dev/null @@ -1,51 +0,0 @@ -# PEERSIM CHORD - -random.seed 1234567890 -simulation.endtime 10^4 -simulation.logtime 10^6 -OutputName chord -simulation.experiments 1 - -network.size 40 -protocol.tr UniformRandomTransport -{ - mindelay 0 - maxdelay 0 -} - -protocol.chord example.chord.ChordProtocol -{ - transport tr -} - -control.traffic example.chord.TrafficGenerator -{ - protocol chord - step 100 -} - -init.create example.chord.CreateNw -{ - protocol chord - idLength 128 - succListSize 12 -} - -control.observer example.chord.MessageCounterObserver -{ - protocol chord - step 90000 -} - -#control.dnet DynamicNetwork -#{ -# #add 2 -# add -2 -# minsize 18#3000 -# maxsize 60#7000 -# step 100000 -# init.0 example.chord.ChordInitializer -# { -# protocol chord -# } -#} \ No newline at end of file diff --git a/contrib/psg/configs/chordPSG.txt b/contrib/psg/configs/chordPSG.txt deleted file mode 100644 index 7e670474b5..0000000000 --- a/contrib/psg/configs/chordPSG.txt +++ /dev/null @@ -1,54 +0,0 @@ -# PEERSIM CHORD - -random.seed 1234567890 -simulation.duration 10^4 -simulation.logtime 10^6 -unit sec -OutputName chord -platform platforms/psg.xml -simulation.experiments 1 - -network.size 40 -protocol.tr psgsim.PSGTransport -{ - mindelay 0 - maxdelay 0 -} - -protocol.chord example.chord.ChordProtocol -{ - transport tr -} - -control.traffic example.chord.TrafficGenerator -{ - protocol chord - step 100 -} - -init.create example.chord.CreateNw -{ - protocol chord - idLength 128 - succListSize 12 -} - -control.observer example.chord.MessageCounterObserver -{ - protocol chord - step 90000 -} - - -#control.dnet DynamicNetwork -#{ -# #add 2 -# add -2 -# minsize 18#3000 -# maxsize 60#7000 -# step 100000 -# init.0 example.chord.ChordInitializer -# { -# protocol chord -# } -#} diff --git a/contrib/psg/configs/edaggregation.txt b/contrib/psg/configs/edaggregation.txt deleted file mode 100644 index d3aec1237b..0000000000 --- a/contrib/psg/configs/edaggregation.txt +++ /dev/null @@ -1,57 +0,0 @@ -# network size -SIZE 50 -OutputName edaggregation - -# parameters of periodic execution -CYCLES 100 -CYCLE SIZE*100 - -# parameters of message transfer -# delay values here are relative to cycle length, in percentage, -# eg 50 means half the cycle length, 200 twice the cycle length, etc. -MINDELAY 0 -MAXDELAY 0 -# drop is a probability, 0<=DROP<=1 -DROP 0 - -random.seed 1234567890 -network.size SIZE -simulation.endtime CYCLE*CYCLES -simulation.logtime CYCLE - -################### protocols =========================== - -protocol.link peersim.core.IdleProtocol - -protocol.avg example.edaggregation.AverageED -protocol.avg.linkable link -protocol.avg.step CYCLE -protocol.avg.transport tr - -protocol.tr UnreliableTransport -protocol.tr.transport urt -protocol.tr.drop DROP - -protocol.urt UniformRandomTransport -protocol.urt.mindelay (CYCLE*MINDELAY)/100 -protocol.urt.maxdelay (CYCLE*MAXDELAY)/100 -################### initialization ====================== - -init.rndlink WireKOut -init.rndlink.k 20 -init.rndlink.protocol link - -init.vals LinearDistribution -init.vals.protocol avg -init.vals.max SIZE -init.vals.min 1 - -init.sch CDScheduler -init.sch.protocol avg -init.sch.randstart - -################ control ============================== - -control.0 SingleValueObserver -control.0.protocol avg -control.0.step CYCLE diff --git a/contrib/psg/configs/edaggregationPSG.txt b/contrib/psg/configs/edaggregationPSG.txt deleted file mode 100644 index 8510e90544..0000000000 --- a/contrib/psg/configs/edaggregationPSG.txt +++ /dev/null @@ -1,57 +0,0 @@ -# network size -SIZE 50 -OutputName edaggregation -platform platforms/psg.xml -unit sec -# parameters of periodic execution -CYCLES 100 -CYCLE SIZE*100 -# parameters of message transfer -# delay values here are relative to cycle length, in percentage, -# eg 50 means half the cycle length, 200 twice the cycle length, etc. -MINDELAY 0 -MAXDELAY 0 -# drop is a probability, 0<=DROP<=1 -DROP 0 - -random.seed 1234567890 -network.size SIZE -simulation.duration CYCLE*CYCLES -simulation.logtime CYCLE - -################### protocols =========================== - -protocol.link peersim.core.IdleProtocol - -protocol.avg example.edaggregation.AverageED -protocol.avg.linkable link -protocol.avg.step CYCLE -protocol.avg.transport tr - -protocol.tr UnreliableTransport -protocol.tr.transport urt -protocol.tr.drop DROP - -protocol.urt psgsim.PSGTransport -protocol.urt.mindelay (CYCLE*MINDELAY)/100 -protocol.urt.maxdelay (CYCLE*MAXDELAY)/100 -################### initialization ====================== - -init.rndlink WireKOut -init.rndlink.k 20 -init.rndlink.protocol link - -init.vals LinearDistribution -init.vals.protocol avg -init.vals.max SIZE -init.vals.min 1 - -init.sch CDScheduler -init.sch.protocol avg -init.sch.randstart - -################ control ============================== - -control.0 SingleValueObserver -control.0.protocol avg -control.0.step CYCLE diff --git a/contrib/psg/configs/symphony.txt b/contrib/psg/configs/symphony.txt deleted file mode 100644 index fb5c778f0a..0000000000 --- a/contrib/psg/configs/symphony.txt +++ /dev/null @@ -1,154 +0,0 @@ -# :::::::::::::::::::::::::::::::::::::::::::::::::::::: -# :: Symphony Default Configuration -# :::::::::::::::::::::::::::::::::::::::::::::::::::::: - -# network size -SIZE 50 - -# parameters of periodic execution -CYCLES 100 -CYCLE SIZE/2 -OutputName symphony - -# parameters of message transfer -# delay values here are relative to cycle length, in percentage, -# eg 50 means half the cycle length, 200 twice the cycle length, etc. -MINDELAY 0 -MAXDELAY 0 - -random.seed 1234567890 -network.size SIZE -simulation.experiments 1 -simulation.endtime 2000#CYCLE*CYCLES -simulation.logtime CYCLE - -################### transports =========================== - -protocol.tr UniformRandomTransport -{ - mindelay (CYCLE*MINDELAY)/100 - maxdelay (CYCLE*MAXDELAY)/100 -} - -################### protocols =========================== - -order.protocol link networkestimator symphony symphonynetworkmanager - -protocol.link peersim.core.IdleProtocol - -protocol.symphony example.symphony.SymphonyProtocol -{ - linkable link - transport tr - shortlink 4 - # if commented means: longlink log(n) - #longlink 4 - routing unidirectional - lookahead off -} - -#protocol.networkestimator example.symphony.SimpleNetworkSizeEstimatorProtocol - -protocol.networkestimator example.symphony.SymphonyEstimationProtocol -{ - symphony symphony - # if commented means: s log(n) - #s 3 -} - -protocol.symphonynetworkmanager example.symphony.SymphonyNetworkManager -{ - symphony symphony - transport tr - networkestimator networkestimator - attempts 3 - nTimeout 5 - relinking on - relinkingLowerBound 0.5 - relinkingUpperBound 2.0 - step 4*CYCLE #useless -} - -################### initialization ====================== - -order.init netbuild checknet - -init.netbuild example.symphony.SymphonyNetworkBuilder -{ - symphony symphony - createLongLinks true - attempts 5 -} - -init.checknet example.symphony.SymphonyNetworkChecker -{ - symphony symphony - networkestimator networkestimator -} - -################ control ============================== - -order.control sch checknet randomroutetest ringroutetest leavetest dnet estimationtest statistics - -control.randomroutetest example.symphony.RandomRouteTest -{ - symphony symphony - step CYCLE -} - -control.ringroutetest example.symphony.RingRouteTest -{ - symphony symphony - startnode 0 - step CYCLE -} - -control.sch CDScheduler -{ - protocol symphonynetworkmanager - step CYCLE*2 - randstart -} - -control.checknet example.symphony.SymphonyNetworkChecker -{ - symphony symphony - networkestimator networkestimator - step CYCLE -} - -control.dnet peersim.dynamics.DynamicNetwork -{ - add 0 - maxsize 50 - minsize SIZE/2 - step CYCLE*2 - init.0 example.symphony.SymphonyNodeInizializer - { - symphonynetworkmanager symphonynetworkmanager - symphony symphony - bootstrapnode 0 - } -} - -control.leavetest example.symphony.LeaveTest -{ - symphonynetworkmanager symphonynetworkmanager - n 1 - minsizeOnline SIZE-1 - waitTargetSizeToStart 2*SIZE - step CYCLE*2 -} - -control.statistics example.symphony.SymphonyStatistics -{ - symphony symphony - step (CYCLE*CYCLES)-1 -} - -control.estimationtest example.symphony.test.NetworkEstimationTest -{ - symphony symphony - symphonynetworkmanager symphonynetworkmanager - step CYCLE*4 -} \ No newline at end of file diff --git a/contrib/psg/configs/symphonyPSG.txt b/contrib/psg/configs/symphonyPSG.txt deleted file mode 100644 index 20b7dcecd1..0000000000 --- a/contrib/psg/configs/symphonyPSG.txt +++ /dev/null @@ -1,155 +0,0 @@ -# :::::::::::::::::::::::::::::::::::::::::::::::::::::: -# :: Symphony Default Configuration -# :::::::::::::::::::::::::::::::::::::::::::::::::::::: - -# network size -SIZE 50 -unit sec -# parameters of periodic execution -CYCLES 100 -CYCLE SIZE/2 -OutputName symphony -platform platforms/psg.xml - -# parameters of message transfer -# delay values here are relative to cycle length, in percentage, -# eg 50 means half the cycle length, 200 twice the cycle length, etc. -MINDELAY 0 -MAXDELAY 0 - -random.seed 1234567890 -network.size SIZE -simulation.experiments 1 -simulation.duration 2000#CYCLE*CYCLES -simulation.logtime CYCLE - -################### transports =========================== - -protocol.tr psgsim.PSGTransport -{ - mindelay (CYCLE*MINDELAY)/100 - maxdelay (CYCLE*MAXDELAY)/100 -} - -################### protocols =========================== - -order.protocol link networkestimator symphony symphonynetworkmanager - -protocol.link peersim.core.IdleProtocol - -protocol.symphony example.symphony.SymphonyProtocol -{ - linkable link - transport tr - shortlink 4 - # if commented means: longlink log(n) - #longlink 4 - routing unidirectional - lookahead off -} - -#protocol.networkestimator example.symphony.SimpleNetworkSizeEstimatorProtocol - -protocol.networkestimator example.symphony.SymphonyEstimationProtocol -{ - symphony symphony - # if commented means: s log(n) - #s 3 -} - -protocol.symphonynetworkmanager example.symphony.SymphonyNetworkManager -{ - symphony symphony - transport tr - networkestimator networkestimator - attempts 3 - nTimeout 5 - relinking on - relinkingLowerBound 0.5 - relinkingUpperBound 2.0 - step 4*CYCLE #useless -} - -################### initialization ====================== - -order.init netbuild checknet - -init.netbuild example.symphony.SymphonyNetworkBuilder -{ - symphony symphony - createLongLinks true - attempts 5 -} - -init.checknet example.symphony.SymphonyNetworkChecker -{ - symphony symphony - networkestimator networkestimator -} - -################ control ============================== - -order.control sch checknet randomroutetest ringroutetest leavetest dnet estimationtest statistics - -control.randomroutetest example.symphony.RandomRouteTest -{ - symphony symphony - step CYCLE -} - -control.ringroutetest example.symphony.RingRouteTest -{ - symphony symphony - startnode 0 - step CYCLE -} - -control.sch CDScheduler -{ - protocol symphonynetworkmanager - step CYCLE*2 - randstart -} - -control.checknet example.symphony.SymphonyNetworkChecker -{ - symphony symphony - networkestimator networkestimator - step CYCLE -} - -control.dnet peersim.dynamics.DynamicNetwork -{ - add 0 - maxsize 50 - minsize SIZE/2 - step CYCLE*2 - init.0 example.symphony.SymphonyNodeInizializer - { - symphonynetworkmanager symphonynetworkmanager - symphony symphony - bootstrapnode 0 - } -} - -control.leavetest example.symphony.LeaveTest -{ - symphonynetworkmanager symphonynetworkmanager - n 1 - minsizeOnline SIZE-1 - waitTargetSizeToStart 2*SIZE - step CYCLE*2 -} - -control.statistics example.symphony.SymphonyStatistics -{ - symphony symphony - step (CYCLE*CYCLES)-1 -} - -control.estimationtest example.symphony.test.NetworkEstimationTest -{ - symphony symphony - symphonynetworkmanager symphonynetworkmanager - step CYCLE*4 -} diff --git a/contrib/psg/lib.jar b/contrib/psg/lib.jar deleted file mode 100644 index 8fd65fa45f6041f79c1a9714ae213d8952c01c8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 716138 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

=o<)SUG^0<=c-geSDC*Sj2P)X<#S!++)) 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

-qs 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%0Ar3^I*kAHG9S7_RaV+)_P3mLwg_eW2CNwC;f(U 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�$^BfRu6C zfNiZ@C~y@kJ%VOK_u^SE2-myrMTWq${c8CPl({qd1G-CZ=^Yu&Io7W?)D&ZM{8$a(U}HC z1VIsKg43jpcM3cTM!t&e z0MnpabMD+r`Nkb>8|Fu-bL-SugBn5D7n3-JtrZaB+KfQtF6_)Ztv{AR$8b^Q?6#jo zd7$CGwJ1Vyi;mVD>b`vwW^~hVofft2SM_PtR9Vh^%67%juo7p$$)iQKRdw>*w-S0DpFU zRw(+D5G3@HEjeeKAo-ot9-5wWgwrI#J(Xvs;1Yp7jlL2%zGrGzj9lnr9+?CAl&3kZm0Hka|F=)r9-y%ozR)~S2 zXcx9QWHwCJ)NmFEH><%nl*vMqUM@FfBsA$4tN?Nh*anPhxM%GH-eg1(WI;B1R=^U* zW-@`p!dbrE5jQ^4JAP!s9_)^#p^ltRZ!IsBanF@fMBVPn8=aOdFqA7mmqs-@yPb!C zJ=E^&6^Y10WZTnyft(BhA8KBszVJov`JN*YdTjZn+FZz;Fqd+=(2Ku$piM%;2|Gh! z!}&3JFq?WjhjTr@NMtDYh5{rP1;4mMt+D{$ux1`-SI8R28;qSoA)W$Wj;o4E1NA{oO48_+)_Z1UTAulGAv@|9!rVsO_$K9Dh~<`VfQc zi3+ZpQ79cVd7#Oa!MJ?ydUV)5^}05PK$_HDES~Y78m> zE#n@gi#)I{kYa)D0p7$T^0B}t#sL6!1oeX0xF`Pxzu@j|y@XM>`?-Q5C@@aqXuWt!UNko=933kTcrobGz2;PW_n|0z5>;#LIJP}i+kEeaKPa*=LkA2l1mcaLQRB@ zeF2REnt(7K_lQW4z_?X>6Z=Zm59kxk;C@iUdO3y!M_SKMB1I9v(6Hr!f zgJaou&Q*qR_MbRxGp;@u61qAW!9fZ0X3;~~Qv<>{5&H(E+rq(I$}!Nk98N>9T|gcc z1U@3(ePJ!lM;+VUN9gKyd%n*)0RBh_3=d7=?^NcXv7;HZFn<~iu00LwmWpg<0An@o zVQUWSUSY&1&B@*b1I0c2INt0{YLmSUMuU5iJ}c~)MS diff --git a/contrib/psg/platforms/psg.xml b/contrib/psg/platforms/psg.xml deleted file mode 100644 index ad5e2a27a1..0000000000 --- a/contrib/psg/platforms/psg.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - diff --git a/contrib/psg/run.sh b/contrib/psg/run.sh deleted file mode 100755 index baac2eed8f..0000000000 --- a/contrib/psg/run.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -if [ $(uname -m) = "i686" ]; then - eval ulimit -s 64 -else - eval ulimit -s 128 -fi -echo '------------- Start execution..'; -java -Xmx1024m -cp lib.jar:classes:../../simgrid.jar peersim.Simulator $1 -echo '------------- done -------------'; -exit 0 - - - - diff --git a/contrib/psg/src/example/bittorrent/BTObserver.java b/contrib/psg/src/example/bittorrent/BTObserver.java deleted file mode 100644 index ddd38dab2b..0000000000 --- a/contrib/psg/src/example/bittorrent/BTObserver.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2007-2008 Fabrizio Frioli, Michele Pedrolli - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -- - * - * Please send your questions/suggestions to: - * {fabrizio.frioli, michele.pedrolli} at studenti dot unitn dot it - * - */ - -package example.bittorrent; - -import peersim.config.*; -import peersim.core.*; -import peersim.util.*; - -/** - * This {@link Control} provides a way to keep track of some - * parameters of the BitTorrent network. - */ - public class BTObserver implements Control { - - /** - * The protocol to operate on. - * @config - */ - private static final String PAR_PROT="protocol"; - - /** - * Protocol identifier, obtained from config property - */ - private final int pid; - - /** - * The basic constructor that reads the configuration file. - * @param prefix the configuration prefix for this class - */ - public BTObserver(String prefix) { - pid = Configuration.getPid(prefix + "." + PAR_PROT); - } - - /** - * Prints information about the BitTorrent network - * and the number of leechers and seeders. - * Please refer to the code comments for more details. - * @return always false - */ - public boolean execute() { - IncrementalFreq nodeStatusStats = new IncrementalFreq(); - IncrementalStats neighborStats = new IncrementalStats(); - - int numberOfNodes = Network.size(); - int numberOfCompletedPieces = 0; - - // cycles from 1, since the node 0 is the tracker - for (int i=1; iTRACKER message. - * @config - */ - private static final String PAR_PEERSET_SIZE="peerset_size"; - /** - * Defines how much the network can grow with respect to the network.size - * when {@link NetworkDynamics} is used. - * @config - */ - private static final String PAR_MAX_GROWTH="max_growth"; - /** - * Is the number of requests of the same block sent to different peers. - * @config - */ - private static final String PAR_DUP_REQ = "duplicated_requests"; - - /** - * KEEP_ALIVE message. - * @see SimpleEvent#type "Event types" - */ - private static final int KEEP_ALIVE = 1; - - /** - * CHOKE message. - * @see SimpleEvent#type "Event types" - */ - private static final int CHOKE = 2; - - /** - * UNCHOKE message. - * @see SimpleEvent#type "Event types" - */ - private static final int UNCHOKE = 3; - - /** - * INTERESTED message. - * @see SimpleEvent#type "Event types" - */ - private static final int INTERESTED = 4; - - /** - * NOT_INTERESTED message. - * @see SimpleEvent#type "Event types" - */ - private static final int NOT_INTERESTED = 5; - - /** - * HAVE message. - * @see SimpleEvent#type "Event types" - */ - private static final int HAVE = 6; - - /** - * BITFIELD message. - * @see SimpleEvent#type "Event types" - */ - private static final int BITFIELD = 7; - - /** - * REQUEST message. - * @see SimpleEvent#type "Event types" - */ - private static final int REQUEST = 8; - - /** - * PIECE message. - * @see SimpleEvent#type "Event types" - */ - private static final int PIECE = 9; - - /** - * CANCEL message. - * @see SimpleEvent#type "Event types" - */ - private static final int CANCEL = 10; - - /** - * TRACKER message. - * @see SimpleEvent#type "Event types" - */ - private static final int TRACKER = 11; - - /** - * PEERSET message. - * @see SimpleEvent#type "Event types" - */ - private static final int PEERSET = 12; - - /** - * CHOKE_TIME event. - * @see SimpleEvent#type "Event types" - */ - private static final int CHOKE_TIME = 13; - - /** - * OPTUNCHK_TIME event. - * @see SimpleEvent#type "Event types" - */ - private static final int OPTUNCHK_TIME = 14; - - /** - * ANTISNUB_TIME event. - * @see SimpleEvent#type "Event types" - */ - private static final int ANTISNUB_TIME = 15; - - /** - * CHECKALIVE_TIME event. - * @see SimpleEvent#type "Event types" - */ - private static final int CHECKALIVE_TIME = 16; - - /** - * TRACKERALIVE_TIME event. - * @see SimpleEvent#type "Event types" - */ - private static final int TRACKERALIVE_TIME = 17; - - /** - * DOWNLOAD_COMPLETED event. - * @see SimpleEvent#type "Event types" - */ - private static final int DOWNLOAD_COMPLETED = 18; - - /** - * The maxium connection speed of the local node. - */ - int maxBandwidth; - - /** - * Stores the neighbors ordered by ID. - * @see Element - */ - private example.bittorrent.Element byPeer[]; - - /** - * Contains the neighbors ordered by bandwidth as needed by the unchocking - * algorithm. - */ - private example.bittorrent.Element byBandwidth[]; - - /** - * The Neighbors list. - */ - private Neighbor cache[]; - - /** - * Reference to the neighbors that unchocked the local node. - */ - private boolean unchokedBy[]; - - /** - * Number of neighbors in the cache. When it decreases under 20, a new peerset - * is requested to the tracker. - */ - private int nNodes = 0; - - /** - * Maximum number of nodes in the network. - */ - private int nMaxNodes; - - /** - * The status of the local peer. 0 means that the current peer is a leecher, 1 a seeder. - */ - private int peerStatus; - - /** - * Defines how much the network can grow with respect to the network.size - * when {@link NetworkDynamics} is used. - */ - public int maxGrowth; - - /** - * File status of the local node. Contains the blocks owned by the local node. - */ - private int status[]; - - /** - * Current number of Bitfield request sent. It must be taken into account - * before sending another one. - */ - private int nBitfieldSent = 0; - - /** - * Current number of pieces in upload from the local peer. - */ - public int nPiecesUp = 0; - /** - * Current number of pieces in download to the local peer. - */ - public int nPiecesDown = 0; - - /** - * Current number of piece completed. - */ - private int nPieceCompleted = 0; - - /** - * Current downloading piece ID, the previous lastInterested piece. - */ - int currentPiece = -1; - - /** - * Used to compute the average download rates in choking algorithm. Stores the - * number of CHOKE events. - */ - int n_choke_time = 0; - - /** - * Used to send the TRACKER message when the local node has 20 neighbors - * for the first time. - */ - boolean lock = false; - - /** - * Number of peers interested to my pieces. - */ - int numInterestedPeers = 0; - - /** - * Last piece for which the local node sent an INTERESTED message. - */ - int lastInterested = -1; - - /** - * The status of the current piece in download. Length 16, every time the local node - * receives a PIECE message, it updates the corrisponding block's cell. The cell - * contains the ID for that block of that piece. If an already owned - * block is received this is discarded. - */ - private int pieceStatus[]; - - /** - * Length of the file. Stored as number of pieces (256KB each one). - */ - int nPieces; - - /** - * Contains the neighbors's status of the file. Every row represents a - * node and every a cell has value O if the neighbor doesn't - * have the piece, 1 otherwise. It has {@link #swarmSize} rows and {@link #nPieces} - * columns. - */ - int [][]swarm; - - /** - * The summation of the swarm's rows. Calculated every time a {@link #BITFIELD} message - * is received and updated every time HAVE message is received. - */ - int rarestPieceSet[]; - - /** - * The five pending block requests. - */ - int pendingRequest[]; - - /** - * The maximum swarm size (default is 80) - */ - int swarmSize; - - /** - * The size of the peerset. This is the number of "friends" nodes - * sent from the tracker to each new node (default: 50) - */ - int peersetSize; - - /** - * The ID of the current node - */ - private long thisNodeID; - - /** - * Number of duplicated requests as specified in the configuration file. - * @see BitTorrent#PAR_DUP_REQ - */ - private int numberOfDuplicatedRequests; - - /** - * The queue where the requests to serve are stored. - * The default dimension of the queue is 20. - */ - Queue requestToServe = null; - - /** - * The queue where the out of sequence incoming pieces are stored - * waiting for the right moment to be processed. - * The default dimension of the queue is 100. - */ - Queue incomingPieces = null; - - /** - * The Transport ID. - * @see BitTorrent#PAR_TRANSPORT - */ - int tid; - - /** - * The reference to the tracker node. If equals to null, the local - * node is the tracker. - */ - private Node tracker = null; - - /** - * The default constructor. Reads the configuration file and initializes the - * configuration parameters. - * @param prefix the component prefix declared in the configuration file - */ - public BitTorrent(String prefix){ // Used for the tracker's protocol - tid = Configuration.getPid(prefix+"."+PAR_TRANSPORT); - nPieces = (int)((Configuration.getInt(prefix+"."+PAR_SIZE))*1000000/256000); - swarmSize = (int)Configuration.getInt(prefix+"."+PAR_SWARM); - peersetSize = (int)Configuration.getInt(prefix+"."+PAR_PEERSET_SIZE); - numberOfDuplicatedRequests = (int)Configuration.getInt(prefix+"."+PAR_DUP_REQ); - maxGrowth = (int)Configuration.getInt(prefix+"."+PAR_MAX_GROWTH); - nMaxNodes = Network.getCapacity()-1; - } - - /** - * Gets the reference to the tracker node. - * @return the reference to the tracker - */ - public Node getTracker(){ - return tracker; - } - - /** - * Gets the number of neighbors currently stored in the cache of the local node. - * @return the number of neighbors in the cache - */ - public int getNNodes(){ - return this.nNodes; - } - - /** - * Sets the reference to the tracker node. - * @param t the tracker node - */ - public void setTracker(Node t){ - tracker = t; - } - - /** - * Sets the ID of the local node. - * @param id the ID of the node - */ - public void setThisNodeID(long id) { - this.thisNodeID = id; - } - - /** - * Gets the ID of the local node. - * @return the ID of the local node - */ - public long getThisNodeID(){ - return this.thisNodeID; - } - - /** - * Gets the file status of the local node. - * @return the file status of the local node - */ - public int[] getFileStatus(){ - return this.status; - } - - /** - * Initializes the tracker node. This method - * only performs the initialization of the tracker's cache. - */ - public void initializeTracker() { - cache = new Neighbor[nMaxNodes+maxGrowth]; - for(int i=0; iChecks the number of neighbors and if it is equal to 20 - * sends a TRACKER messages to the tracker, asking for a new - * peer set.

- * - *

This method *must* be called after every call of {@link #removeNeighbor} - * in {@link #processEvent}. - *

- */ - private void processNeighborListSize(Node node, int pid) { - if (nNodes==20) { - Object ev; - long latency; - ev = new SimpleMsg(TRACKER, node); - Node tracker = ((BitTorrent)node.getProtocol(pid)).tracker; - if(tracker != null){ -// latency = ((Transport)node.getProtocol(tid)).getLatency(node, tracker); -// EDSimulator.add(latency,ev,tracker,pid); - ((Transport) node.getProtocol(tid)).send(node, tracker, ev, pid); - } - } - } - - /** - * The standard method that processes incoming events. - * @param node reference to the local node for which the event is going to be processed - * @param pid BitTorrent's protocol id - * @param event the event to process - */ - public void processEvent(Node node, int pid, Object event){ - - Object ev; - long latency; - switch(((SimpleEvent)event).getType()){ - - case KEEP_ALIVE: // 1 - { - Node sender = ((IntMsg)event).getSender(); - int isResponse = ((IntMsg)event).getInt(); - //System.out.println("process, keep_alive: sender is "+sender.getID()+", local is "+node.getID()); - Element e = search(sender.getID()); - if(e!= null){ //if I know the sender - cache[e.peer].isAlive(); - if(isResponse==0 && alive(sender)){ - Object msg = new IntMsg(KEEP_ALIVE,node,1,0); -// latency = ((Transport)node.getProtocol(tid)).getLatency(node, sender); -// EDSimulator.add(latency,msg,sender,pid); - ((Transport) node.getProtocol(tid)).send(node, sender, msg, pid); - cache[e.peer].justSent(); - } - } - else{ - System.err.println("despite it should never happen, it happened"); - ev = new BitfieldMsg(BITFIELD, true, false, node, status, nPieces); -// latency = ((Transport)node.getProtocol(tid)).getLatency(node,sender); -// EDSimulator.add(latency,ev,sender,pid); - ((Transport) node.getProtocol(tid)).send(node, sender, ev, pid); - nBitfieldSent++; - } - - };break; - - case CHOKE: // 2, CHOKE message. - { - Node sender = ((SimpleMsg)event).getSender(); - //System.out.println("process, choke: sender is "+sender.getID()+", local is "+node.getID()); - Element e = search(sender.getID()); - if(e!= null){ //if I know the sender - cache[e.peer].isAlive(); - unchokedBy[e.peer]= false; // I'm choked by it - } - else{ - System.err.println("despite it should never happen, it happened"); - ev = new BitfieldMsg(BITFIELD, true, false, node, status, nPieces); -// latency = ((Transport)node.getProtocol(tid)).getLatency(node,sender); -// EDSimulator.add(latency,ev,sender,pid); - ((Transport) node.getProtocol(tid)).send(node, sender, ev, pid); - nBitfieldSent++; - } - };break; - - case UNCHOKE: // 3, UNCHOKE message. - { - Node sender = ((SimpleMsg)event).getSender(); - //System.out.println("process, unchoke: sender is "+sender.getID()+", local is "+node.getID()); - Element e = search(sender.getID()); - if(e != null){ // If I know the sender - int senderIndex = e.peer; - cache[senderIndex].isAlive(); - /* I send to it some of the pending requests not yet satisfied. */ - int t = numberOfDuplicatedRequests; - for(int i=4;i>=0 && t>0;i--){ - if(pendingRequest[i]==-1) - break; - if(alive(cache[senderIndex].node) && swarm[senderIndex][decode(pendingRequest[i],0)]==1){ //If the sender has that piece - ev = new IntMsg(REQUEST, node,pendingRequest[i],0); -// latency = ((Transport)node.getProtocol(tid)).getLatency(node,sender); -// EDSimulator.add(latency,ev, sender,pid); - ((Transport) node.getProtocol(tid)).send(node, sender, ev, pid); - cache[senderIndex].justSent(); - } - if(!alive(cache[senderIndex].node)){ - System.out.println("unchoke1 rm neigh "+ cache[i].node.getID() ); - removeNeighbor(cache[senderIndex].node); - processNeighborListSize(node,pid); - return; - } - t--; - } - // I request missing blocks to fill the queue - int block = getBlock(); - int piece; - while(block != -2){ //while still available request to send - if(block < 0){ // No more block to request for the current piece - piece = getPiece(); - if(piece == -1){ // no more piece to request - break; - } - for(int j=0; j swarmSize) - ev = new BitfieldMsg(BITFIELD, false, false, node, status, nPieces); //response with nack -// latency = ((Transport)node.getProtocol(tid)).getLatency(node,sender); -// EDSimulator.add(latency,ev,sender,pid); - ((Transport) node.getProtocol(tid)).send(node, sender, ev, pid); - } - } - - } - else - System.out.println("Sender "+sender.getID()+" not alive"); - } - };break; - - case REQUEST: // 8, REQUEST message. - { - Object evnt; - Node sender = ((IntMsg)event).getSender(); - int value = ((IntMsg)event).getInt(); - Element e; - BitTorrent senderP; - int remoteRate; - int localRate; - int bandwidth; - int downloadTime; - - e = search(sender.getID()); - if (e==null) - return; - cache[e.peer].isAlive(); - - requestToServe.enqueue(value, sender); - - /*I serve the enqueued requests until 10 uploding pieces or an empty queue*/ - while(!requestToServe.empty() && nPiecesUp <10){ - Request req = requestToServe.dequeue(); - e = search(req.sender.getID()); - if(e!=null && alive(req.sender)){ -// ev = new IntMsg(PIECE, node, req.id); - nPiecesUp++; - e.valueUP++; - senderP = ((BitTorrent)req.sender.getProtocol(pid)); - senderP.nPiecesDown++; - remoteRate = senderP.maxBandwidth/(senderP.nPiecesUp + senderP.nPiecesDown); - localRate = maxBandwidth/(nPiecesUp + nPiecesDown); - bandwidth = Math.min(remoteRate, localRate); - downloadTime = ((16*8)/(bandwidth))*1000; // in milliseconds - - ev = new IntMsg(PIECE, node, req.id, 16*8 * 1024); - ((Transport) node.getProtocol(tid)).send(node, req.sender, ev, pid); - -// latency = ((Transport)node.getProtocol(tid)).getLatency(node,req.sender); -// EDSimulator.add(latency+downloadTime,ev,req.sender,pid); - cache[e.peer].justSent(); - - /*I send to me an event to indicate that the download is completed. - This prevent that, when the receiver death occurres, my value nPiecesUp - doesn't decrease.*/ - evnt = new SimpleMsg(DOWNLOAD_COMPLETED, req.sender); -// EDSimulator.add(latency+downloadTime,evnt,node,pid); - ((Transport) node.getProtocol(tid)).send(node, node, evnt, pid); - } - } - }; break; - - case PIECE: // 9, PIECE message. - { - Node sender = ((IntMsg)event).getSender(); - /* Set the correct value for the local uploading and remote - downloading number of pieces */ - nPiecesDown--; - - if(peerStatus == 1)// To save CPU cycles - return; - //System.out.println("process, piece: sender is "+sender.getID()+", local is "+node.getID()); - Element e = search(sender.getID()); - - if(e==null){ //I can't accept a piece not wait - return; - } - e.valueDOWN++; - - cache[e.peer].isAlive(); - - int value = ((IntMsg)event).getInt(); - int piece = decode(value,0); - int block = decode(value,1); - /* If the block has not been already downloaded and it belongs to - the current downloading piece.*/ - if(piece == currentPiece && decode(pieceStatus[block],0)!= piece){ - pieceStatus[block] = value; - status[piece]++; - removeRequest(value); - requestNextBlocks(node, pid, e.peer); - - }else{ // Either a future piece or an owned piece - if(piece!=currentPiece && status[piece]!=16){ // Piece not owned, will be considered later - incomingPieces.enqueue(value, sender); - } - - } - ev = new IntMsg(CANCEL, node, value,0); - /* I send a CANCEL to all nodes to which I previously requested the block*/ - for(int i=0; i 0){ // I process the queue - m--; - Request temp = incomingPieces.dequeue(); - int p = decode(temp.id,0); // piece id - int b = decode(temp.id,1); // block id - Element s = search(temp.sender.getID()); - if(s==null) // if the node that sent the block in the queue is dead - continue; - if(p==currentPiece && decode(pieceStatus[b],0)!= p){ - pieceStatus[b] = temp.id; - status[p]++; - removeRequest(temp.id); - requestNextBlocks(node, pid, s.peer); - } - else{ // The piece not currently desired will be moved to the tail - if(p!= currentPiece) // If not a duplicate block but belongs to another piece - incomingPieces.enqueue(temp.id,temp.sender); - else // duplicate block - requestNextBlocks(node, pid, s.peer); - } - } - } - }; break; - - case CANCEL: - { - Node sender = ((IntMsg)event).getSender(); - int value = ((IntMsg)event).getInt(); - requestToServe.remove(sender, value); - };break; - - case PEERSET: // PEERSET message - { - Node sender = ((PeerSetMsg)event).getSender(); - //System.out.println("process, peerset: sender is "+sender.getID()+", local is "+node.getID()); - Neighbor n[] = ((PeerSetMsg)event).getPeerSet(); - - for(int i=0; i 0){ - byBandwidth[j]=byPeer[i]; //shallow copy - j++; - } - } - - /*It ensures that in the next 20sec, if there are less nodes interested - than now, those in surplus will not be ordered. */ - for(;j0;z--){ - int lucky = CommonState.r.nextInt(nNodes); - while(cache[byPeer[lucky].peer].status ==1 && alive(cache[byPeer[lucky].peer].node) && - cache[byPeer[lucky].peer].interested == 0)// until the lucky peer is already unchoked or not interested - lucky = CommonState.r.nextInt(nNodes); - luckies[3-z]= byPeer[lucky].peer; - } - } - for(int i=0; i0 && (byPeer[i].valueDOWN - byPeer[i].head60)==0){// No blocks downloaded in 1 min - cache[byPeer[i].peer].status = 2; // I'm snubbed by it - } - byPeer[i].head60 = byPeer[i].valueDOWN; - } - ev = new SimpleEvent(ANTISNUB_TIME); - EDSimulator.add(60000,ev,node,pid); - long time = CommonState.getTime(); - }; break; - - case CHECKALIVE_TIME: - { - - //System.out.println("process, checkalive_time"); - - long now = CommonState.getTime(); - for(int i=0; ivalue depending - * on part: 0 means the piece value, 1 the block value. - * @param value the ID of the block to decode. - * @param part the information to extract from value. 0 means the piece index, 1 the block index. - * @return the piece or the block index depending about the value of part - */ - private int decode(int value, int part){ - if (value==-1) // Not a true value to decode - return -1; - if(part == 0) // I'm interested to the piece - return value/100; - else // I'm interested to the block - return value%100; - } - - /** - * Used by {@link NodeInitializer#choosePieces(int, BitTorrent) NodeInitializer} to set - * the number of piece completed from the beginning in according with - * the distribution in the configuration file. - * @param number the number of piece completed - */ - public void setCompleted(int number){ - this.nPieceCompleted = number; - } - - /** - * Sets the status (the set of blocks) of the file for the current node. - * Note that a piece is considered completed if the number - * of downloaded blocks is 16. - * @param index The index of the piece - * @param value Number of blocks downloaded for the piece index. - */ - public void setStatus(int index, int value){ - status[index]=value; - } - - /** - * Sets the status of the local node. - * @param status The status of the node: 1 means seeder, 0 leecher - */ - public void setPeerStatus(int status){ - this.peerStatus = status; - } - - /** - * Gets the status of the local node. - * @return The status of the local node: 1 means seeder, 0 leecher - */ - public int getPeerStatus(){ - return peerStatus; - } - - /** - * Gets the number of blocks for a given piece owned by the local node. - * @param index The index of the piece - * @return Number of blocks downloaded for the piece index - */ - public int getStatus(int index){ - return status[index]; - } - - /** - * Sets the maximum bandwdith for the local node. - * @param value The value of bandwidth in Kbps - */ - public void setBandwidth(int value){ - maxBandwidth = value; - } - - /** - * Checks if a node is still alive in the simulated network. - * @param node The node to check - * @return true if the node node is up, false otherwise - * @see peersim.core.GeneralNode#isUp - */ - public boolean alive(Node node){ - if(node == null) - return false; - else - return node.isUp(); - } - - /** - * Adds a neighbor to the cache of the local node. - * The new neighbor is put in the first null position. - * @param neighbor The neighbor node to add - * @return false if the neighbor is already present in the cache (this can happen when the peer requests a - * new peer set to the tracker an there is still this neighbor within) or no place is available. - * Otherwise, returns true if the node is correctly added to the cache. - */ - public boolean addNeighbor(Node neighbor){ - if(search(neighbor.getID()) !=null){// if already exists - // System.err.println("Node "+neighbor.getID() + " not added, already exist."); - return false; - } - if(this.tracker == null){ // I'm in the tracker's BitTorrent protocol - for(int i=0; i< nMaxNodes+maxGrowth; i++){ - if(cache[i].node == null){ - cache[i].node = neighbor; - cache[i].status = 0; //chocked - cache[i].interested = -1; //not interested - this.nNodes++; - - //System.err.println("i: " + i +" nMaxNodes: " + nMaxNodes); - return true; - } - } - } - else{ - if((nNodes+nBitfieldSent) < swarmSize){ - //System.out.println("I'm the node " + this.thisNodeID + ", trying to add node "+neighbor.getID()); - for(int i=0; i=0 && pendingRequest[i]!=-1){ - i--; - } - if(i>=0){ - pendingRequest[i] = block; - return true; - } - else { // It should never happen - //System.err.println("pendingRequest queue full"); - return false; - } - } - - /** - * Removes the block with the given id from the {@link #pendingRequest} queue - * and sorts the queue leaving the empty cell at the left. - * @param id the id of the requested block - */ - private void removeRequest(int id){ - int i = 4; - for(; i>=0; i--){ - if(pendingRequest[i]==id) - break; - } - for(; i>=0; i--){ - if(i==0) - pendingRequest[i] = -1; - else - pendingRequest[i] = pendingRequest[i-1]; - } - } - - /** - * Requests new block until the {@link #pendingRequest} is full to the sender of the just received piece. - * It calls {@link #getNewBlock(Node, int)} to implement the strict priority strategy. - * @param node the local node - * @param pid the BitTorrent protocol id - * @param sender the sender of the just received received piece. - */ - private void requestNextBlocks(Node node, int pid, int sender){ - int block = getNewBlock(node, pid); - while(block != -2){ - if(unchokedBy[sender]==true && alive(cache[sender].node) && addRequest(block)){ - Object ev = new IntMsg(REQUEST, node, block,0); - -// long latency = ((Transport)node.getProtocol(tid)).getLatency(node,cache[sender].node); -// EDSimulator.add(latency,ev,cache[sender].node,pid); - - ((Transport) node.getProtocol(tid)).send(node,cache[sender].node, ev, pid); - cache[sender].justSent(); - } - else{ // I cannot send request - if(!alive(cache[sender].node) && cache[sender].node!=null){ - System.out.println("piece2 rm neigh "+ cache[sender].node.getID() ); - removeNeighbor(cache[sender].node); - processNeighborListSize(node,pid); - } - return; - } - block = getNewBlock(node, pid); - } - } - - /** - * It returns the id of the next block to request. Sends INTERESTED if the new - * block belongs to a new piece. - * It uses {@link #getBlock()} to get the next block of a piece and calls {@link #getPiece()} - * when all the blocks for the {@link #currentPiece} have been requested. - * @param node the local node - * @param pid the BitTorrent protocol id - * @return -2 if no more places available in the pendingRequest queue;
- * the value of the next block to request otherwise

- */ - private int getNewBlock(Node node, int pid){ - int block = getBlock(); - if(block < 0){ // No more block to request for the current piece - - if(block ==-2) // Pending request queue full - return -2; - - int newPiece = getPiece(); - if(newPiece == -1){ // no more piece to request - return -2; - } - - lastInterested = newPiece; - Object ev = new IntMsg(INTERESTED, node, lastInterested,0); - - for(int j=0; jcurrentPiece if there are still - * available places in the {@link #pendingRequest} queue;
- * -2 if the pendingRequest queue is full;
- * -1 if no more blocks to request for the current piece. - */ - private int getBlock(){ - int i=4; - while(i>=0 && pendingRequest[i]!=-1){ // i is the first empty position from the head - i--; - } - if(i==-1){// No places in the pendingRequest available - //System.out.println("Pendig request queue full!"); - return -2; - } - int j; - //The queue is not empty & last requested block belongs to lastInterested piece - if(i!=4 && decode(pendingRequest[i+1],0)==lastInterested) - j=decode(pendingRequest[i+1],1)+1; // the block following the last requested - else // I don't know which is the next block, so I search it. - j=0; - /* I search another block until the current has been already received. - * If in pieceStatus at position j there is a block that belongs to - * lastInterested piece, means that the block j has been already - * received, otherwise I can request it. - */ - while(j<16 && decode(pieceStatus[j],0)==lastInterested){ - j++; - } - if(j==16) // No more block to request for lastInterested piece - return -1; - return encode(lastInterested,j); - } - - /** - * Returns the next correct piece to download. It choose the piece by using the - * random first and rarest first policy. For the beginning 4 pieces - * of a file the first one is used then the pieces are chosen using rarest first. - * @see "Documentation about the BitTorrent module" - * @return the next piece to download. If the whole file has been requested - * -1 is returned. - */ - private int getPiece(){ - int piece = -1; - if(nPieceCompleted < 4){ //Uses random first piece - piece = CommonState.r.nextInt(nPieces); - while(status[piece]==16 || piece == currentPiece) // until the piece is owned - piece = CommonState.r.nextInt(nPieces); - return piece; - } - else{ //Uses rarest piece first - int j=0; - for(; jInsertionSort
- * algorithm. - */ - public void sortByPeer(){ - int i; - - for(int j=1; j=0 && (byPeer[i].ID > key.ID)) // until one is smaller, - { - byPeer[i].copyTo(byPeer[i+1]); // shift item right, - i--; // go left one position - } - key.copyTo(byPeer[i+1]); // insert marked item - } - - } - - /** - * Sorts the array {@link #byBandwidth} using QuickSort algorithm. - * null elements and seeders are moved to the end of the array. - */ - public void sortByBandwidth() { - quicksort(0, swarmSize-1); - } - - /** - * Used by {@link #sortByBandwidth()}. It's the implementation of the - * QuickSort algorithm. - * @param left the leftmost index of the array to sort. - * @param right the rightmost index of the array to sort. - */ - private void quicksort(int left, int right) { - if (right <= left) return; - int i = partition(left, right); - quicksort(left, i-1); - quicksort(i+1, right); - } - - /** - * Used by {@link #quicksort(int, int)}, partitions the subarray to sort returning - * the splitting point as stated by the QuickSort algorithm. - * @see "The QuickSort algorithm". - */ - private int partition(int left, int right) { - int i = left - 1; - int j = right; - while (true) { - while (greater(byBandwidth[++i], byBandwidth[right])) // find item on left to swap - ; // a[right] acts as sentinel - while (greater(byBandwidth[right], byBandwidth[--j])) { // find item on right to swap - if (j == left) break; // don't go out-of-bounds - } - if (i >= j) break; // check if pointers cross - swap(i, j); // swap two elements into place - } - swap(i, right); // swap with partition element - return i; - } - - /** - * Aswers to the question "is x > y?". Compares the {@link Element}s given as - * parameters. Element x is greater than y if isn't null - * and in the last 20 seconds the local node has downloaded ("uploaded" if the local node is a - * seeder) more blocks than from y. - * @param x the first Element to compare. - * @param y the second Element to compare - * @return true if x > y;
- * false otherwise. - */ - private boolean greater(Element x, Element y) { - /* - * Null elements and seeders are shifted at the end - * of the array - */ - if (x==null) return false; - if (y==null) return true; - if (x.isSeeder) return false; - if (y.isSeeder) return true; - - // if the local node is a leecher - if (peerStatus==0) { - if ((x.valueDOWN - x.head20) > - (y.valueDOWN -y.head20)) - return true; - else return false; - } - - // if peerStatus==1 (the local node is a seeder) - else { - if ((x.valueUP - x.head20) > - (y.valueUP -y.head20)) - return true; - else return false; - } - } - - /** - * Swaps {@link Element} i with j in the {@link #byBandwidth}.
- * Used by {@link #partition(int, int)} - * @param i index of the first element to swap - * @param j index of the second element to swap - */ - private void swap(int i, int j) { - Element swap = byBandwidth[i]; - byBandwidth[i] = byBandwidth[j]; - byBandwidth[j] = swap; - } - - /** Searches the node with the given ID. It does a dychotomic - * search. - * @param ID ID of the node to search. - * @return the {@link Element} in {@link #byPeer} which represents the node with the - * given ID. - */ - public Element search(long ID){ - int low = 0; - int high = swarmSize-1; - int p = low+((high-low)/2); //Initial probe position - while ( low <= high) { - if ( byPeer[p] == null || byPeer[p].ID > ID) - high = p - 1; - else { - if( byPeer[p].ID < ID ) //Wasteful second comparison forced by syntax limitations. - low = p + 1; - else - return byPeer[p]; - } - p = low+((high-low)/2); //Next probe position. - } - return null; - } -} - -/** - * This class is used to store the main informations about a neighbors regarding - * the calculation of the Downloading/Uploading rates. Is the class of items in - * {@link example.bittorrent.BitTorrent#byPeer} and {@link example.bittorrent.BitTorrent#byBandwidth}. - */ -class Element{ - /** - * ID of the represented node. - */ - public long ID = Integer.MAX_VALUE; - /** - * Index position of the node in the {@link example.bittorrent.BitTorrent#cache} array. - */ - public int peer = -1; - /** - * Number of blocks uploaded to anyone since the beginning. - */ - public int valueUP = 0; - /** - * Number of blocks downloaded from anyone since the beginning. - */ - public int valueDOWN = 0; - /** - * Value of either {@link #valueUP} or {@link #valueDOWN} (depending by - * {@link example.bittorrent.BitTorrent#peerStatus}) 20 seconds before. - */ - public int head20 = 0; - /** - * Value of either {@link #valueUP} or {@link #valueDOWN} (depending by - * {@link example.bittorrent.BitTorrent#peerStatus}) 60 seconds before. - */ - public int head60 = 0; - /** - * true if the node is a seeder, false otherwise. - */ - public boolean isSeeder = false; - /** - * Makes a deep copy of the Element to destination - * @param destination Element instance where to make the copy - */ - public void copyTo(Element destination){ - destination.ID = this.ID; - destination.peer = this.peer; - destination.valueUP = this.valueUP; - destination.valueDOWN = this.valueDOWN; - destination.head20 = this.head20; - destination.head60 = this.head60; - } -} - -/** - * This class stores information about the neighbors regarding their status. It is - * the type of the items in the {@link example.bittorrent.BitTorrent#cache}. - */ -class Neighbor{ - /** - * Reference to the node in the {@link peersim.core.Network}. - */ - public Node node = null; - /** - * -1 means not interested
- * Other values means the last piece number for which the node is interested. - */ - public int interested; - /** - * 0 means CHOKED
- * 1 means UNCHOKED
- * 2 means SNUBBED_BY. If this value is set and the node is to be unchocked, - * value 2 has the priority. - */ - public int status; - /** - * Last time a message from the node represented has been received. - */ - public long lastSeen = 0; - /** - * Last time a message to the node represented has been sent. - */ - public long lastSent = 0; - - /** - * Sets the last time the neighbor was seen. - */ - public void isAlive(){ - long now = CommonState.getTime(); - this.lastSeen = now; - } - - /* - * Sets the last time the local peer sent something to the neighbor. - */ - public void justSent(){ - long now = CommonState.getTime(); - this.lastSent = now; - } - -} - -/** - * Class type of the queues's items in {@link example.bittorrent.BitTorrent#incomingPieces} - * and {@link example.bittorrent.BitTorrent#requestToServe}. - */ -class Queue{ - int maxSize; - int head = 0; - int tail = 0; - int dim = 0; - Request queue[]; - - /** - * Public constructor. Creates a queue of size size. - */ - public Queue(int size){ - maxSize = size; - queue = new Request[size]; - for(int i=0; i< size; i++) - queue[i]= new Request(); - } - - /** - * Enqueues the request of the block id and its sender - * @param id the id of the block in the request - * @param sender a reference to the sender of the request - * @return true if the request has been correctly added, false - * otherwise. - */ - public boolean enqueue(int id, Node sender){ - if(dim < maxSize){ - queue[tail%maxSize].id = id; - queue[tail%maxSize].sender = sender; - tail++; - dim++; - return true; - } - else return false; - } - - /** - * Returns the {@link Request} in the head of the queue. - * @return the element in the head.
- * null if the queue is empty. - */ - public Request dequeue(){ - Request value; - if(dim > 0){ - value = queue[head%maxSize]; - head++; - dim--; - return value; - } - else return null; //empty queue - } - - /** - * Returns the status of the queue. - * @return true if the queue is empty, false - * otherwise. - */ - public boolean empty(){ - return (dim == 0); - } - - /** - * Returns true if block given as parameter is in. - * @param value the id of the block to search. - * @return true if the block value is in the queue, false - * otherwise. - */ - public boolean contains(int value){ - if(empty()) - return false; - for(int i=head; itrue if the request has been correctly removed, false - * otherwise. - */ - public boolean remove(Node sender, int value){ - if(empty()) - return false; - for(int i=head; ihead; j--){ // Shifts the elements for the removal - queue[j%maxSize]= queue[(j-1)%maxSize]; - } - head++; - dim--; - return true; - } - } - return false; - } -} - -/** - * This class represent an enqueued request of a block. - */ -class Request{ - /** - * The id of the block. - */ - public int id; - /** - * The sender of the request. - */ - public Node sender; -} \ No newline at end of file diff --git a/contrib/psg/src/example/bittorrent/BitfieldMsg.java b/contrib/psg/src/example/bittorrent/BitfieldMsg.java deleted file mode 100644 index d459482de0..0000000000 --- a/contrib/psg/src/example/bittorrent/BitfieldMsg.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2007-2008 Fabrizio Frioli, Michele Pedrolli - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -- - * - * Please send your questions/suggestions to: - * {fabrizio.frioli, michele.pedrolli} at studenti dot unitn dot it - * - */ - -package example.bittorrent; - -import peersim.core.*; - -/** - * This class is a {@link SimpleMsg} and represents the bitfield - * message. - */ -public class BitfieldMsg extends SimpleMsg{ - /** - * The status of the file to transmit to neighbors nodes - */ - int[] array; - - /** - * Defines the type of the Bitfield message. If isRequest is true, then - * the message is a request of subscription; otherwise the message is a response. - */ - boolean isRequest; - - /** - *

The ACK value used to implement ack and nack messages.

- *

It has value true if the message is a reponse and the sender has inserted - * the receiver in its own cache of neighbors.
- * If for some reason (for instance the cache had already 80 peer inside at the moment of the - * request) it was not possible to insert the peer, the value is false.
- * It has value false also if the message is a request and is sent when occours - * an unespected message. - *

- * @see "The documentation to understand the 4 different types of Bitfield messages" - */ - boolean ack; - - /** - * The basic constructor of the Bitfield message. - * @param type The type of the message, according to {@link SimpleMsg} - * @param isRequest Defines if the message is a request or not - * @param ack Defines if the message type is an ack or a nack - * @param sender The sender node - * @param source The array containing the status of the file - * @param size The size of the array - */ - public BitfieldMsg(int type, boolean isRequest, boolean ack, Node sender, int source[], int size){ - super.type = type; - super.sender = sender; - this.isRequest = isRequest; - this.ack = ack; - this.array = new int[size]; - for(int i=0; i maxSize) { - System.err.println("DYN: " + (maxSize - Network.size()) - + " nodes will be added."); - add(maxSize - Network.size()); - } else { - System.err - .println("DYN: " + this.add + " nodes will be added."); - add(this.add); - } - } - // removing existing nodes - else { - if (Network.size() - this.remove < minsize) { - System.err.println("DYN: " + (Network.size() - minsize) - + " nodes will be removed."); - remove(Network.size() - minsize); - } else { - System.err.println("DYN: " + this.remove - + " nodes will be removed."); - remove(this.remove); - } - } - return false; - } -} \ No newline at end of file diff --git a/contrib/psg/src/example/bittorrent/NetworkInitializer.java b/contrib/psg/src/example/bittorrent/NetworkInitializer.java deleted file mode 100644 index 4b5ba72e5f..0000000000 --- a/contrib/psg/src/example/bittorrent/NetworkInitializer.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2007-2008 Fabrizio Frioli, Michele Pedrolli - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -- - * - * Please send your questions/suggestions to: - * {fabrizio.frioli, michele.pedrolli} at studenti dot unitn dot it - * - */ - -package example.bittorrent; - -import peersim.core.*; -import peersim.config.Configuration; -import peersim.edsim.EDSimulator; -import peersim.transport.Transport; -import java.util.Random; - -/** - * This {@link Control} ... - */ -public class NetworkInitializer implements Control { - /** - * The protocol to operate on. - * - * @config - */ - private static final String PAR_PROT="protocol"; - - private static final String PAR_TRANSPORT="transport"; - - private static final int TRACKER = 11; - - private static final int CHOKE_TIME = 13; - - private static final int OPTUNCHK_TIME = 14; - - private static final int ANTISNUB_TIME = 15; - - private static final int CHECKALIVE_TIME = 16; - - private static final int TRACKERALIVE_TIME = 17; - - /** Protocol identifier, obtained from config property */ - private final int pid; - private final int tid; - private NodeInitializer init; - - private Random rnd; - - public NetworkInitializer(String prefix) { - pid = Configuration.getPid(prefix+"."+PAR_PROT); - tid = Configuration.getPid(prefix+"."+PAR_TRANSPORT); - init = new NodeInitializer(prefix); - } - - public boolean execute() { - int completed; - Node tracker = Network.get(0); - - // manca l'inizializzazione del tracker; - - ((BitTorrent)Network.get(0).getProtocol(pid)).initializeTracker(); - - for(int i=1; in associating it - * with the BitTorrent protocol and setting the reference to the tracker, - * the status of the file and the bandwidth. - * @param n The node to initialize - */ - public void initialize(Node n){ - Node tracker = Network.get(0); - BitTorrent p; - p = (BitTorrent)n.getProtocol(pid); - p.setTracker(tracker); - p.setThisNodeID(n.getID()); - setFileStatus(p); - setBandwidth(p); - } - - /** - * Sets the status of the shared file according to the - * probability value given by {@link #getProbability()}. - * @param p The BitTorrent protocol - */ - private void setFileStatus(BitTorrent p){ - int percentage = getProbability(); - choosePieces(percentage, p); - } - - /** - * Set the maximum bandwidth for the node, choosing - * uniformly at random among 4 values. - *

- * The allowed bandwidth speed are 640 Kbps, 1 Mbps, 2 Mbps and 4 Mbps. - *

- * @param p The BitTorrent protocol - */ - private void setBandwidth(BitTorrent p){ - int value = CommonState.r.nextInt(4); - switch(value){ - case 0: p.setBandwidth(640);break; //640Kbps - case 1: p.setBandwidth(1024);break;// 1Mbps - case 2: p.setBandwidth(2048);break;// 2Mbps - case 3: p.setBandwidth(4096);break; //4Mbps - } - } - - /** - * Sets the completed pieces for the given protocol p. - * @parm percentage The percentage of the downloaded pieces, according to {@link #getProbability()} - * @param p the BitTorrent protocol - */ - private void choosePieces(int percentage, BitTorrent p){ - double temp = ((double)p.nPieces/100.0)*percentage; // We use a double to avoid the loss of precision - // during the division operation - int completed = (int)temp; //integer number of piece to set as completed - //0 if the peer is a newer - p.setCompleted(completed); - if(percentage == 100) - p.setPeerStatus(1); - int tmp; - while(completed!=0){ - tmp = CommonState.r.nextInt(p.nPieces); - if(p.getStatus(tmp)!=16){ - p.setStatus(tmp, 16); - completed--; - } - } - } - - /** - * Gets a probability according with the parameter newer_distr - * defined in the configuration file. - * @return the probabilty value, where 0 means that the peer is new and no pieces has been downloaded, - * 100 means that the peer is a seeder; other values defines a random probability. - * @see #PAR_NEWER_DISTR - */ - private int getProbability(){ - int value = CommonState.r.nextInt(100); - if((value+1)<=seederDistr) - return 100; - value = CommonState.r.nextInt(100); - if((value+1)<=newerDistr){ - return 0; // A newer peer, with probability newer_distr - } - else{ - value = CommonState.r.nextInt(9); - return (value+1)*10; - } - } -} \ No newline at end of file diff --git a/contrib/psg/src/example/bittorrent/PeerSetMsg.java b/contrib/psg/src/example/bittorrent/PeerSetMsg.java deleted file mode 100644 index d0e92d56ff..0000000000 --- a/contrib/psg/src/example/bittorrent/PeerSetMsg.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2007-2008 Fabrizio Frioli, Michele Pedrolli - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -- - * - * Please send your questions/suggestions to: - * {fabrizio.frioli, michele.pedrolli} at studenti dot unitn dot it - * - */ -package example.bittorrent; - -import peersim.core.*; - -/** - * This class is a {@link SimpleMsg} and represents the peerset - * message used by the tracker to send to the peers a list of neighbors. - */ -public class PeerSetMsg extends SimpleMsg{ - - /** - * The set of "friends" peers sent by the tracker to each node. - */ - private Neighbor[] peerSet; - - /** - * Initializes a new peerset message. - * @param type is the type of the message (it should be 12) - * @param array is the array containing the references to the neighbor nodes - * @param sender the sender node - * @see SimpleEvent - */ - public PeerSetMsg(int type, Neighbor []array, Node sender){ - super.type = type; - peerSet = array; // references to the effective nodes - super.sender = sender; - } - - /** - * Gets the peer set. - * @return the peer set, namely the set of neighbor nodes. - */ - public Neighbor[] getPeerSet(){ - return this.peerSet; - } -} diff --git a/contrib/psg/src/example/bittorrent/SimpleEvent.java b/contrib/psg/src/example/bittorrent/SimpleEvent.java deleted file mode 100644 index 1da537ac00..0000000000 --- a/contrib/psg/src/example/bittorrent/SimpleEvent.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2007-2008 Fabrizio Frioli, Michele Pedrolli - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -- - * - * Please send your questions/suggestions to: - * {fabrizio.frioli, michele.pedrolli} at studenti dot unitn dot it - * - */ - -package example.bittorrent; - -/** - * This class defines a simple event. A simple event is characterized only - * by its type. - */ -public class SimpleEvent { - - /** - * The identifier of the type of the event. - *

- * The available identifiers for event type are:
- *

    - *
  • 1 is KEEP_ALIVE message
  • - *
  • 2 is CHOKE message
  • - *
  • 3 is UNCHOKE message
  • - *
  • 4 is INTERESTED message
  • - *
  • 5 is NOT_INTERESTED message
  • - *
  • 6 is HAVE message
  • - *
  • 7 is BITFIELD message
  • - *
  • 8 is REQUEST message
  • - *
  • 9 is PIECE message
  • - *
  • 10 is CANCEL message
  • - *
  • 11 is TRACKER message
  • - *
  • 12 is PEERSET message
  • - *
  • 13 is CHOKE_TIME event
  • - *
  • 14 is OPTUNCHK_TIME event
  • - *
  • 15 is ANTISNUB_TIME event
  • - *
  • 16 is CHECKALIVE_TIME event
  • - *
  • 17 is TRACKERALIVE_TIME event
  • - *
  • 18 is DOWNLOAD_COMPLETED event
  • - *

- */ - protected int type; - - public SimpleEvent(){ - } - - /** - * Initializes the type of the event. - * @param type The identifier of the type of the event - */ - public SimpleEvent(int type){ - this.type = type; - } - - /** - * Gets the type of the event. - * @return The type of the current event. - */ - public int getType(){ - return this.type; - } -} - - diff --git a/contrib/psg/src/example/bittorrent/SimpleMsg.java b/contrib/psg/src/example/bittorrent/SimpleMsg.java deleted file mode 100644 index cf9436ec67..0000000000 --- a/contrib/psg/src/example/bittorrent/SimpleMsg.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2007-2008 Fabrizio Frioli, Michele Pedrolli - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * -- - * - * Please send your questions/suggestions to: - * {fabrizio.frioli, michele.pedrolli} at studenti dot unitn dot it - * - */ - -package example.bittorrent; - -import peersim.core.*; - -/** - * This class defines a simple message. - * A simple message has its type and the reference of the sender node. - * @see SimpleEvent - */ -public class SimpleMsg extends SimpleEvent { - - /** - * The sender of the message. - */ - protected Node sender; - - public SimpleMsg(){ - } - - /** - * Initializes the simple message with its type and sender. - * @param type The identifier of the type of the message - * @param sender The sender of the message - */ - public SimpleMsg(int type, Node sender){ - super.type = type; - this.sender = sender; - } - - /** - * Gets the sender of the message. - * @return The sender of the message. - */ - public Node getSender(){ - return this.sender; - } -} diff --git a/contrib/psg/src/example/chord/ChordInitializer.java b/contrib/psg/src/example/chord/ChordInitializer.java deleted file mode 100644 index 799b0d707b..0000000000 --- a/contrib/psg/src/example/chord/ChordInitializer.java +++ /dev/null @@ -1,72 +0,0 @@ -package example.chord; - -import java.math.BigInteger; -import java.util.Random; -import peersim.config.Configuration; -import peersim.core.CommonState; -import peersim.core.Network; -import peersim.core.Node; -import peersim.dynamics.NodeInitializer; - -public class ChordInitializer implements NodeInitializer { - - private static final String PAR_PROT = "protocol"; - - private int pid = 0; - - private ChordProtocol cp; - - public ChordInitializer(String prefix) { - pid = Configuration.getPid(prefix + "." + PAR_PROT); - } - - public void initialize(Node n) { - cp = (ChordProtocol) n.getProtocol(pid); - join(n); - } - - public void join(Node myNode) { - Random generator = new Random(); - //Random generator = new Random(1234567890); - cp.predecessor = null; - // search a node to join - Node n; - do { - n = Network.get(generator.nextInt(Network.size())); - } while (n == null || n.isUp() == false); - cp.m = ((ChordProtocol) n.getProtocol(pid)).m; - cp.chordId = new BigInteger(cp.m, CommonState.r); - ChordProtocol cpRemote = (ChordProtocol) n.getProtocol(pid); - - Node successor = cpRemote.find_successor(cp.chordId); - cp.fails = 0; - cp.stabilizations = 0; - cp.varSuccList = cpRemote.varSuccList; - cp.varSuccList = 0; - cp.succLSize = cpRemote.succLSize; - cp.successorList = new Node[cp.succLSize]; - cp.successorList[0] = successor; - cp.fingerTable = new Node[cp.m]; - long succId = 0; - BigInteger lastId = ((ChordProtocol) Network.get(Network.size() - 1) - .getProtocol(pid)).chordId; - do { - cp.stabilizations++; - succId = cp.successorList[0].getID(); - cp.stabilize(myNode); - if (((ChordProtocol) cp.successorList[0].getProtocol(pid)).chordId - .compareTo(cp.chordId) < 0) { - cp.successorList[0] = ((ChordProtocol) cp.successorList[0] - .getProtocol(pid)).find_successor(cp.chordId); - } - // controllo di non essere l'ultimo elemento della rete - if (cp.chordId.compareTo(lastId) > 0) { - cp.successorList[0] = Network.get(0); - break; - } - } while (cp.successorList[0].getID() != succId - || ((ChordProtocol) cp.successorList[0].getProtocol(pid)).chordId - .compareTo(cp.chordId) < 0); - cp.fixFingers(); - } -} diff --git a/contrib/psg/src/example/chord/ChordMessage.java b/contrib/psg/src/example/chord/ChordMessage.java deleted file mode 100644 index f87fafbb72..0000000000 --- a/contrib/psg/src/example/chord/ChordMessage.java +++ /dev/null @@ -1,12 +0,0 @@ -/** - * - */ -package example.chord; - -/** - * @author Andrea - * - */ -public interface ChordMessage { - -} diff --git a/contrib/psg/src/example/chord/ChordProtocol.java b/contrib/psg/src/example/chord/ChordProtocol.java deleted file mode 100644 index 485c3ba214..0000000000 --- a/contrib/psg/src/example/chord/ChordProtocol.java +++ /dev/null @@ -1,358 +0,0 @@ -/** - * - */ -package example.chord; - -import peersim.config.Configuration; -import peersim.core.CommonState; -import peersim.core.Network; -import peersim.core.Node; -import peersim.edsim.EDProtocol; -import peersim.transport.Transport; - -import java.math.*; - -import org.simgrid.msg.Host; -import org.simgrid.msg.Msg; - -/** - * @author Andrea - * - */ -public class ChordProtocol implements EDProtocol { - - private static final String PAR_TRANSPORT = "transport"; - - private Parameters p; - - private int[] lookupMessage; - - public int index = 0; - - public Node predecessor; - - public Node[] fingerTable; - - public Node[] successorList; - - public BigInteger chordId; - - public int m; - - public int succLSize; - - public String prefix; - - private int next = 0; - - // campo x debug - private int currentNode = 0; - - public int varSuccList = 0; - - public int stabilizations = 0; - - public int fails = 0; - - /** - * - */ - public ChordProtocol(String prefix) { - this.prefix = prefix; - lookupMessage = new int[1]; - lookupMessage[0] = 0; - p = new Parameters(); - p.tid = Configuration.getPid(prefix + "." + PAR_TRANSPORT); - } - - /* - * (non-Javadoc) - * - * @see peersim.edsim.EDProtocol#processEvent(peersim.core.Node, int, - * java.lang.Object) - */ - public void processEvent(Node node, int pid, Object event) { - // processare le richieste a seconda della routing table del nodo - p.pid = pid; - // currentNode = node.getIndex(); - currentNode = (int) node.getID(); - if (event.getClass() == LookUpMessage.class) { - LookUpMessage message = (LookUpMessage) event; - message.increaseHopCounter(); - BigInteger target = message.getTarget(); - Transport t = (Transport) node.getProtocol(p.tid); - Node n = message.getSender(); - System.out.println("R process " + "at time=" - + CommonState.getTime() + " to dest:" + currentNode - + " from src:" + n.getID() + " message: (" - + message.getSender().getID() + ";" + message.getTarget() - + ")"); - if (target == ((ChordProtocol) node.getProtocol(pid)).chordId) { - // mandare mess di tipo final - Object msg = new FinalMessage(message.getHopCounter()); - System.out.println("S Final Message " + "at time=" - + CommonState.getTime() + " from src:" + node.getID() - + " to dest:" + n.getID() + " message: " - + message.getHopCounter() + " HopCounter"); - t.send(node, n, msg, pid); - - } - if (target != ((ChordProtocol) node.getProtocol(pid)).chordId) { - // funzione lookup sulla fingertabable - Node dest = find_successor(target); - if (dest.isUp() == false) { - do { - varSuccList = 0; - stabilize(node); - stabilizations++; - fixFingers(); - dest = find_successor(target); - } while (dest.isUp() == false); - } - if (dest.getID() == successorList[0].getID() - && (target.compareTo(((ChordProtocol) dest - .getProtocol(p.pid)).chordId) < 0)) { - fails++; - } else { - System.out.println("S process " + "at time=" - + CommonState.getTime() + " from src:" - + node.getID() + " to dest:" + dest.getID() - + " message: (" + message.getSender().getID() + ";" - + message.getTarget() + ")"); - // t.send(message.getSender(), dest, message, pid); - t.send(node, dest, message, pid); - - } - } - } - if (event.getClass() == FinalMessage.class) { - FinalMessage message = (FinalMessage) event; - System.out.println("R Final Message " + "at time=" - + CommonState.getTime() + " to dest:" + node.getID()+"\n"); - lookupMessage = new int[index + 1]; - lookupMessage[index] = message.getHopCounter(); - index++; - } - } - - public Object clone() { - ChordProtocol cp = new ChordProtocol(prefix); - String val = BigInteger.ZERO.toString(); - cp.chordId = new BigInteger(val); - cp.fingerTable = new Node[m]; - cp.successorList = new Node[succLSize]; - cp.currentNode = 0; - return cp; - } - - public int[] getLookupMessage() { - return lookupMessage; - } - - public void stabilize(Node myNode) { - try { - Node node = ((ChordProtocol) successorList[0].getProtocol(p.pid)).predecessor; - if (node != null) { - if (this.chordId == ((ChordProtocol) node.getProtocol(p.pid)).chordId) - return; - BigInteger remoteID = ((ChordProtocol) node.getProtocol(p.pid)).chordId; - if (idInab( - remoteID, - chordId, - ((ChordProtocol) successorList[0].getProtocol(p.pid)).chordId)) - successorList[0] = node; - ((ChordProtocol) successorList[0].getProtocol(p.pid)) - .notify(myNode); - } - updateSuccessorList(); - } catch (Exception e1) { - e1.printStackTrace(); - updateSuccessor(); - } - } - - private void updateSuccessorList() throws Exception { - try { - while (successorList[0] == null || successorList[0].isUp() == false) { - updateSuccessor(); - } - System.arraycopy( - ((ChordProtocol) successorList[0].getProtocol(p.pid)).successorList, - 0, successorList, 1, succLSize - 2); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void notify(Node node) throws Exception { - BigInteger nodeId = ((ChordProtocol) node.getProtocol(p.pid)).chordId; - if ((predecessor == null) - || (idInab( - nodeId, - ((ChordProtocol) predecessor.getProtocol(p.pid)).chordId, - this.chordId))) { - predecessor = node; - } - } - - private void updateSuccessor() { - boolean searching = true; - while (searching) { - try { - Node node = successorList[varSuccList]; - varSuccList++; - successorList[0] = node; - if (successorList[0] == null - || successorList[0].isUp() == false) { - if (varSuccList >= succLSize - 1) { - searching = false; - varSuccList = 0; - } else - updateSuccessor(); - } - updateSuccessorList(); - searching = false; - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - private boolean idInab(BigInteger id, BigInteger a, BigInteger b) { - if ((a.compareTo(id) == -1) && (id.compareTo(b) == -1)) { - return true; - } - return false; - } - - public Node find_successor(BigInteger id) { - try { - if (successorList[0] == null || successorList[0].isUp() == false) { - updateSuccessor(); - } - if (idInab( - id, - this.chordId, - ((ChordProtocol) successorList[0].getProtocol(p.pid)).chordId)) { - return successorList[0]; - } else { - Node tmp = closest_preceding_node(id); - return tmp; - } - } catch (Exception e) { - e.printStackTrace(); - } - return successorList[0]; - } - - private Node closest_preceding_node(BigInteger id) { - for (int i = m; i > 0; i--) { - try { - if (fingerTable[i - 1] == null - || fingerTable[i - 1].isUp() == false) { - continue; - } - BigInteger fingerId = ((ChordProtocol) (fingerTable[i - 1] - .getProtocol(p.pid))).chordId; - if ((idInab(fingerId, this.chordId, id)) - || (id.compareTo(fingerId) == 0)) { - return fingerTable[i - 1]; - } - if (fingerId.compareTo(this.chordId) == -1) { - // sono nel caso in cui ho fatto un giro della rete - // circolare - if (idInab(id, fingerId, this.chordId)) { - return fingerTable[i - 1]; - } - } - if ((id.compareTo(fingerId) == -1) - && (id.compareTo(this.chordId) == -1)) { - if (i == 1) - return successorList[0]; - BigInteger lowId = ((ChordProtocol) fingerTable[i - 2] - .getProtocol(p.pid)).chordId; - if (idInab(id, lowId, fingerId)) - return fingerTable[i - 2]; - else if (fingerId.compareTo(this.chordId) == -1) - continue; - else if (fingerId.compareTo(this.chordId) == 1) - return fingerTable[i - 1]; - } - } catch (Exception e) { - e.printStackTrace(); - } - } - if (fingerTable[m - 1] == null) - return successorList[0]; - return successorList[0]; - } - - // debug function - private void printFingers() { - for (int i = fingerTable.length - 1; i > 0; i--) { - if (fingerTable[i] == null) { - System.out.println("Finger " + i + " is null"); - continue; - } - if ((((ChordProtocol) fingerTable[i].getProtocol(p.pid)).chordId) - .compareTo(this.chordId) == 0) - break; - System.out - .println("Finger[" - + i - + "] = " - + fingerTable[i].getIndex() - + " chordId " - + ((ChordProtocol) fingerTable[i] - .getProtocol(p.pid)).chordId); - } - } - - public void fixFingers() { - if (next >= m - 1) - next = 0; - if (fingerTable[next] != null && fingerTable[next].isUp()) { - next++; - return; - } - BigInteger base; - if (next == 0) - base = BigInteger.ONE; - else { - base = BigInteger.valueOf(2); - for (int exp = 1; exp < next; exp++) { - base = base.multiply(BigInteger.valueOf(2)); - } - } - BigInteger pot = this.chordId.add(base); - BigInteger idFirst = ((ChordProtocol) Network.get(0).getProtocol(p.pid)).chordId; - BigInteger idLast = ((ChordProtocol) Network.get(Network.size() - 1) - .getProtocol(p.pid)).chordId; - if (pot.compareTo(idLast) == 1) { - pot = (pot.mod(idLast)); - if (pot.compareTo(this.chordId) != -1) { - next++; - return; - } - if (pot.compareTo(idFirst) == -1) { - this.fingerTable[next] = Network.get(Network.size() - 1); - next++; - return; - } - } - do { - fingerTable[next] = ((ChordProtocol) successorList[0] - .getProtocol(p.pid)).find_successor(pot); - pot = pot.subtract(BigInteger.ONE); - ((ChordProtocol) successorList[0].getProtocol(p.pid)).fixFingers(); - } while (fingerTable[next] == null || fingerTable[next].isUp() == false); - next++; - } - - /** - */ - public void emptyLookupMessage() { - index = 0; - this.lookupMessage = new int[0]; - } -} diff --git a/contrib/psg/src/example/chord/CreateNw.java b/contrib/psg/src/example/chord/CreateNw.java deleted file mode 100644 index 9268653533..0000000000 --- a/contrib/psg/src/example/chord/CreateNw.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * - */ -package example.chord; - -import peersim.core.*; -import peersim.config.Configuration; -import java.math.*; - -/** - * @author Andrea - * - */ -public class CreateNw implements Control { - - private int pid = 0; - - private static final String PAR_IDLENGTH = "idLength"; - - private static final String PAR_PROT = "protocol"; - - private static final String PAR_SUCCSIZE = "succListSize"; - - int idLength = 0; - - int successorLsize = 0; - - int fingSize = 0; - //campo x debug - boolean verbose = false; - - /** - * - */ - public CreateNw(String prefix) { - pid = Configuration.getPid(prefix + "." + PAR_PROT); - idLength = Configuration.getInt(prefix + "." + PAR_IDLENGTH); - successorLsize = Configuration.getInt(prefix + "." + PAR_SUCCSIZE); - } - - /* - * (non-Javadoc) - * - * @see peersim.core.Control#execute() - */ - - public boolean execute() { - for (int i = 0; i < Network.size(); i++) { - Node node = (Node) Network.get(i); - ChordProtocol cp = (ChordProtocol) node.getProtocol(pid); - cp.m = idLength; - cp.succLSize = successorLsize; - cp.varSuccList = 0; - cp.chordId = new BigInteger(idLength, CommonState.r); - cp.fingerTable = new Node[idLength]; - cp.successorList = new Node[successorLsize]; - } - NodeComparator nc = new NodeComparator(pid); - Network.sort(nc); - createFingerTable(); - return false; - } - - public Node findId(BigInteger id, int nodeOne, int nodeTwo) { - if (nodeOne >= (nodeTwo - 1)) - return Network.get(nodeOne); - int middle = (nodeOne + nodeTwo) / 2; - if (((middle) >= Network.size() - 1)) - System.out.print("ERROR: Middle is bigger than Network.size"); - if (((middle) <= 0)) - return Network.get(0); - try { - BigInteger newId = ((ChordProtocol) ((Node) Network.get(middle)) - .getProtocol(pid)).chordId; - BigInteger lowId; - if (middle > 0) - lowId = ((ChordProtocol) ((Node) Network.get(middle - 1)) - .getProtocol(pid)).chordId; - else - lowId = newId; - BigInteger highId = ((ChordProtocol) ((Node) Network - .get(middle + 1)).getProtocol(pid)).chordId; - if (id.compareTo(newId) == 0 - || ((id.compareTo(newId) == 1) && (id.compareTo(highId) == -1))) { - return Network.get(middle); - } - if ((id.compareTo(newId) == -1) && (id.compareTo(lowId) == 1)) { - if (middle > 0) - return Network.get(middle - 1); - else - return Network.get(0); - } - if (id.compareTo(newId) == -1) { - return findId(id, nodeOne, middle); - } else if (id.compareTo(newId) == 1) { - return findId(id, middle, nodeTwo); - } - return null; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - public void createFingerTable() { - BigInteger idFirst = ((ChordProtocol) Network.get(0).getProtocol(pid)).chordId; - BigInteger idLast = ((ChordProtocol) Network.get(Network.size() - 1) - .getProtocol(pid)).chordId; - for (int i = 0; i < Network.size(); i++) { - Node node = (Node) Network.get(i); - ChordProtocol cp = (ChordProtocol) node.getProtocol(pid); - for (int a = 0; a < successorLsize; a++) { - if (a + i < (Network.size() - 1)) - cp.successorList[a] = Network.get(a + i + 1); - else - cp.successorList[a] = Network.get(a); - } - if (i > 0) - cp.predecessor = (Node) Network.get(i - 1); - else - cp.predecessor = (Node) Network.get(Network.size() - 1); - int j = 0; - for (j = 0; j < idLength; j++) { - BigInteger base; - if (j == 0) - base = BigInteger.ONE; - else { - base = BigInteger.valueOf(2); - for (int exp = 1; exp < j; exp++) { - base = base.multiply(BigInteger.valueOf(2)); - } - } - BigInteger pot = cp.chordId.add(base); - if (pot.compareTo(idLast) == 1) { - pot = (pot.mod(idLast)); - if (pot.compareTo(cp.chordId) != -1) { - break; - } - if (pot.compareTo(idFirst) == -1) { - cp.fingerTable[j] = Network.get(Network.size() - 1); - continue; - } - } - cp.fingerTable[j] = findId(pot, 0, Network.size() - 1); - } - } - } -} diff --git a/contrib/psg/src/example/chord/FinalMessage.java b/contrib/psg/src/example/chord/FinalMessage.java deleted file mode 100644 index 847dba9b46..0000000000 --- a/contrib/psg/src/example/chord/FinalMessage.java +++ /dev/null @@ -1,14 +0,0 @@ -package example.chord; - -public class FinalMessage implements ChordMessage { - - private int hopCounter = 0; - - public FinalMessage(int hopCounter) { - this.hopCounter = hopCounter; - } - - public int getHopCounter() { - return hopCounter; - } -} diff --git a/contrib/psg/src/example/chord/LookUpMessage.java b/contrib/psg/src/example/chord/LookUpMessage.java deleted file mode 100644 index 091089e625..0000000000 --- a/contrib/psg/src/example/chord/LookUpMessage.java +++ /dev/null @@ -1,44 +0,0 @@ -package example.chord; - -import java.math.*; -import peersim.core.*; - -public class LookUpMessage implements ChordMessage { - - private Node sender; - - private BigInteger targetId; - - private int hopCounter = -1; - - public LookUpMessage(Node sender, BigInteger targetId) { - this.sender = sender; - this.targetId = targetId; - } - - public void increaseHopCounter() { - hopCounter++; - } - - /** - * @return the senderId - */ - public Node getSender() { - return sender; - } - - /** - * @return the target - */ - public BigInteger getTarget() { - return targetId; - } - - /** - * @return the hopCounter - */ - public int getHopCounter() { - return hopCounter; - } - -} diff --git a/contrib/psg/src/example/chord/MessageCounterObserver.java b/contrib/psg/src/example/chord/MessageCounterObserver.java deleted file mode 100644 index dbcbb8f06a..0000000000 --- a/contrib/psg/src/example/chord/MessageCounterObserver.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * - */ -package example.chord; - -import java.util.ArrayList; -import peersim.core.Control; -import peersim.core.Network; -import peersim.config.Configuration; - -/** - * @author Andrea - * - */ -public class MessageCounterObserver implements Control { - - private static final String PAR_PROT = "protocol"; - - private final String prefix; - - private final int pid; - - /** - * - */ - public MessageCounterObserver(String prefix) { - this.prefix = prefix; - this.pid = Configuration.getPid(prefix + "." + PAR_PROT); - } - - /* - * (non-Javadoc) - * - * @see peersim.core.Control#execute() - */ - public boolean execute() { - int size = Network.size(); - int totalStab = 0; - int totFails = 0; - ArrayList hopCounters = new ArrayList(); // struttura dati che - // memorizza gli hop di - // tutti i mess mandati - hopCounters.clear(); - int max = 0; - int min = Integer.MAX_VALUE; - for (int i = 0; i < size; i++) { - ChordProtocol cp = (ChordProtocol) Network.get(i).getProtocol(pid); - // trovare tutti gli hopCOunter dei messaggi lookup mandati - int[] counters = new int[cp.getLookupMessage().length]; - System.arraycopy(cp.getLookupMessage(), 0, counters, 0, cp - .getLookupMessage().length); - totalStab = totalStab + cp.stabilizations; - totFails = totFails + cp.fails; - cp.stabilizations = 0; - cp.fails = 0; - int maxNew = maxArray(counters, cp.index); - if (maxNew > max) - max = maxNew; - if (cp.index != 0) { - for (int j = 0; j < cp.index; j++) - hopCounters.add(counters[j]); - int minNew = minArray(counters, cp.index); - if (minNew < min) - min = minNew; - } - cp.emptyLookupMessage(); - } - double media = meanCalculator(hopCounters); - if (media > 0) - System.out.println("Mean: " + media + " Max Value: " + max - + " Min Value: " + min + " # Observations: " - + hopCounters.size()); - System.out.println(" # Stabilizations: " + totalStab + " # Failures: " - + totFails); - System.out.println(""); - return false; - } - - private double meanCalculator(ArrayList list) { - int lenght = list.size(); - if (lenght == 0) - return 0; - int sum = 0; - for (int i = 0; i < lenght; i++) { - sum = sum + ((Integer) list.get(i)).intValue(); - } - double mean = sum / lenght; - return mean; - } - - private int maxArray(int[] array, int dim) { - int max = 0; - for (int j = 0; j < dim; j++) { - if (array[j] > max) - max = array[j]; - } - return max; - } - - private int minArray(int[] array, int dim) { - int min = 0; - for (int j = 0; j < dim; j++) { - if (array[j] < min) - min = array[j]; - } - return min; - } -} diff --git a/contrib/psg/src/example/chord/NodeComparator.java b/contrib/psg/src/example/chord/NodeComparator.java deleted file mode 100644 index def16dccd8..0000000000 --- a/contrib/psg/src/example/chord/NodeComparator.java +++ /dev/null @@ -1,21 +0,0 @@ -package example.chord; - -import java.util.Comparator; -import java.math.*; -import peersim.core.*; - -public class NodeComparator implements Comparator { - - public int pid = 0; - - public NodeComparator(int pid) { - this.pid = pid; - } - - public int compare(Object arg0, Object arg1) { - BigInteger one = ((ChordProtocol) ((Node) arg0).getProtocol(pid)).chordId; - BigInteger two = ((ChordProtocol) ((Node) arg1).getProtocol(pid)).chordId; - return one.compareTo(two); - } - -} diff --git a/contrib/psg/src/example/chord/Parameters.java b/contrib/psg/src/example/chord/Parameters.java deleted file mode 100644 index d32d82f791..0000000000 --- a/contrib/psg/src/example/chord/Parameters.java +++ /dev/null @@ -1,7 +0,0 @@ -package example.chord; - -public class Parameters { - int pid; - - int tid; -} diff --git a/contrib/psg/src/example/chord/TrafficGenerator.java b/contrib/psg/src/example/chord/TrafficGenerator.java deleted file mode 100644 index 09c5854bff..0000000000 --- a/contrib/psg/src/example/chord/TrafficGenerator.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * - */ -package example.chord; - -import org.simgrid.msg.Host; - -import peersim.core.*; -import peersim.config.Configuration; -import peersim.edsim.EDSimulator; -import psgsim.PSGSimulator; - -/** - * @author Andrea - * - */ -public class TrafficGenerator implements Control { - - private static final String PAR_PROT = "protocol"; - - private final int pid; - - /** - * - */ - public TrafficGenerator(String prefix) { - pid = Configuration.getPid(prefix + "." + PAR_PROT); - } - - /* - * (non-Javadoc) - * - * @see peersim.core.Control#execute() - */ - public boolean execute() { - int size = Network.size(); - Node sender, target; - int i = 0; - do { - i++; - sender = Network.get(CommonState.r.nextInt(size)); - target = Network.get(CommonState.r.nextInt(size)); - } while (sender == null || sender.isUp() == false || target == null - || target.isUp() == false); - LookUpMessage message = new LookUpMessage(sender, - ((ChordProtocol) target.getProtocol(pid)).chordId); - System.out.println("TrafficGenerator at time "+CommonState.getTime()+" Node:" - + message.getSender().getID() +" target "+target.getID() + " pid:" - + pid); - EDSimulator.add(10, message, sender, pid); - return false; - } - -} diff --git a/contrib/psg/src/example/edaggregation/AverageED.java b/contrib/psg/src/example/edaggregation/AverageED.java deleted file mode 100644 index c5f335831a..0000000000 --- a/contrib/psg/src/example/edaggregation/AverageED.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2003 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package example.edaggregation; - -import peersim.vector.SingleValueHolder; -import peersim.config.*; -import peersim.core.*; -import peersim.transport.Transport; -import peersim.cdsim.CDProtocol; -import peersim.edsim.EDProtocol; - -/** - * Event driven version of epidemic averaging. - */ -public class AverageED extends SingleValueHolder implements CDProtocol, - EDProtocol { - - // -------------------------------------------------------------------------- - // Initialization - // -------------------------------------------------------------------------- - - /** - * @param prefix - * string prefix for config properties - */ - public AverageED(String prefix) { - super(prefix); - } - - // -------------------------------------------------------------------------- - // methods - // -------------------------------------------------------------------------- - - /** - * This is the standard method the define periodic activity. The frequency - * of execution of this method is defined by a - * {@link peersim.edsim.CDScheduler} component in the configuration. - */ - public void nextCycle(Node node, int pid) { - Linkable linkable = (Linkable) node.getProtocol(FastConfig - .getLinkable(pid)); - if (linkable.degree() > 0) { - int degree=linkable.degree(); - int i=CommonState.r.nextInt(degree); - Node peern = linkable.getNeighbor(i); - System.out.println("Pid of the protocol: "+pid); - System.out.println("Time="+CommonState.getTime()+" degree="+degree+" i="+i+" peernID="+peern.getID()+" peernIndex="+peern.getIndex()); - if (!peern.isUp()) - return; - AverageMessage ob=new AverageMessage(value, node); - System.out.println("NextCycle\t"+"\t Time: " + CommonState.getTime()+ "\t src: " + node.getID() + "\t dst: " + peern.getID()+"\t msg:"+ob.value); - ((Transport) node.getProtocol(FastConfig.getTransport(pid))).send( - node, peern, ob, pid); - } - } - - // -------------------------------------------------------------------------- - - /** - * This is the standard method to define to process incoming messages. - */ - public void processEvent(Node node, int pid, Object event) { - - AverageMessage aem = (AverageMessage) event; - - AverageMessage ob=null; - if (aem.sender != null){ - System.out.println("ProcessEventR\t"+"\t Time: " + CommonState.getTime() + "\t src: " + aem.sender.getID() + "\t dst: " + node.getID()+"\t msg:"+aem.value); - ob=new AverageMessage(value, null); - System.out.println("ProcessEventS\t"+"\t Time: " + CommonState.getTime()+ "\t src: " + node.getID() + "\t dst: " + aem.sender.getID()+"\t msg:"+ob.value); - ((Transport) node.getProtocol(FastConfig.getTransport(pid))).send( - node, aem.sender, ob, pid); - } else { - System.out.println("ProcessEventR\t"+"\t Time: " +CommonState.getTime() + "\t src: " + "NULL" + "\t dst: " + node.getID()+"\t msg:"+aem.value); - } - value = (value + aem.value) / 2; - } - -} - -// -------------------------------------------------------------------------- -// -------------------------------------------------------------------------- - -/** - * The type of a message. It contains a value of type double and the sender node - * of type {@link peersim.core.Node}. - */ -class AverageMessage { - - final double value; - /** - * If not null, this has to be answered, otherwise this is the answer. - */ - final Node sender; - - public AverageMessage(double value, Node sender) { - this.value = value; - this.sender = sender; - } -} \ No newline at end of file diff --git a/contrib/psg/src/example/symphony/AdapterIterableNetwork.java b/contrib/psg/src/example/symphony/AdapterIterableNetwork.java deleted file mode 100644 index 37bf1046af..0000000000 --- a/contrib/psg/src/example/symphony/AdapterIterableNetwork.java +++ /dev/null @@ -1,31 +0,0 @@ -package example.symphony; - -import java.util.Iterator; -import peersim.core.Network; -import peersim.core.Node; - -/** - * Adapter Class absolutely UNSAFE, just to be able to iterate peersim.core.Network - * - * @author Andrea Esposito - */ -public class AdapterIterableNetwork implements Iterable, Iterator { - - private int i = 0; - - public Iterator iterator() { - return this; - } - - public boolean hasNext() { - return i < Network.size(); - } - - public Node next() { - return Network.get(i++); - } - - public void remove() { - throw new UnsupportedOperationException("Not supported yet."); - } -} diff --git a/contrib/psg/src/example/symphony/AdapterSymphonyNodeComparator.java b/contrib/psg/src/example/symphony/AdapterSymphonyNodeComparator.java deleted file mode 100644 index b05bbb601a..0000000000 --- a/contrib/psg/src/example/symphony/AdapterSymphonyNodeComparator.java +++ /dev/null @@ -1,28 +0,0 @@ -package example.symphony; - -import java.util.Comparator; - -import example.symphony.SymphonyProtocol.BootstrapStatus; -import peersim.core.Node; - -/** - * Object-Adapter - * - * @author Andrea Esposito - */ -public class AdapterSymphonyNodeComparator implements Comparator> { - - private SymphonyNodeComparator comparator; - - public AdapterSymphonyNodeComparator(SymphonyNodeComparator comparator) { - this.comparator = comparator; - } - - public int compare(Tuple o1, Tuple o2) { - - Node node1 = o1.x; - Node node2 = o2.x; - - return comparator.compare(node1, node2); - } -} diff --git a/contrib/psg/src/example/symphony/Handler.java b/contrib/psg/src/example/symphony/Handler.java deleted file mode 100644 index c78d774566..0000000000 --- a/contrib/psg/src/example/symphony/Handler.java +++ /dev/null @@ -1,19 +0,0 @@ -package example.symphony; - -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public interface Handler { - - /** - * Handler associable to a routing request - * - * @param src Symphony Protocol that has sent the routing request - * @param evt Tuple that contains: Node that manages the identifier, Identifier that the routing - * has done on - */ - void handle(SymphonyProtocol src, Tuple evt); -} diff --git a/contrib/psg/src/example/symphony/LeaveTest.java b/contrib/psg/src/example/symphony/LeaveTest.java deleted file mode 100644 index b4c9167f21..0000000000 --- a/contrib/psg/src/example/symphony/LeaveTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package example.symphony; - -import peersim.config.Configuration; -import peersim.core.CommonState; -import peersim.core.Control; -import peersim.core.Network; -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class LeaveTest implements Control { - - private static final String PAR_NETMANAGER = "symphonynetworkmanager"; - private static final String PAR_NUMBER_LEAVES = "n"; - private static final String PAR_MIN_SIZE = "minsizeOnline"; - private static final String PAR_WAIT_TARGET_SIZE = "waitTargetSizeToStart"; - private final int networkManagerID; - private final double n; - private final int minSizeNetwork; - private int targetSize; - - public LeaveTest(String prefix) { - networkManagerID = Configuration.getPid(prefix + "." + PAR_NETMANAGER); - double nAppo = Configuration.getDouble(prefix + "." + PAR_NUMBER_LEAVES); - if (!(nAppo > 0.0 && nAppo < 1.0)) { - n = (int) Math.round(nAppo); - } else { - n = nAppo; - } - - minSizeNetwork = Configuration.getInt(prefix + "." + PAR_MIN_SIZE, -1); - targetSize = Configuration.getInt(prefix + "." + PAR_WAIT_TARGET_SIZE, -1); - } - - public boolean execute() { - - if (minSizeNetwork > 0) { - - int onlineNode = 0; - AdapterIterableNetwork it = new AdapterIterableNetwork(); - for (Node node : it) { - if (node.isUp()) { - onlineNode++; - } - } - - if (targetSize <= 0 || targetSize <= onlineNode) { - targetSize = -1; - - // verify if i have to remove an exact number of nodes or a percentage of them - int actualN = (int) (n < 1.0 ? Math.ceil(Network.size() * n) : n); - - for (int i = 0; i < actualN && Network.size() > 0; i++) { - if (onlineNode > minSizeNetwork) { - Node leaveNode = Network.get(Math.abs(CommonState.r.nextInt()) % Network.size()); - - while (!leaveNode.isUp()) { - leaveNode = Network.get(Math.abs(CommonState.r.nextInt()) % Network.size()); - } - - SymphonyNetworkManager networkManager = (SymphonyNetworkManager) leaveNode.getProtocol(networkManagerID); - - networkManager.leave(leaveNode); - - onlineNode--; - } else { - break; - } - } - } - } - - return false; - } -} diff --git a/contrib/psg/src/example/symphony/Message.java b/contrib/psg/src/example/symphony/Message.java deleted file mode 100644 index 5f63d118a1..0000000000 --- a/contrib/psg/src/example/symphony/Message.java +++ /dev/null @@ -1,90 +0,0 @@ -package example.symphony; - -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class Message implements Cloneable { - - public enum MessageType { - - ROUTE, ROUTE_RESPONSE, ROUTE_FAIL, - JOIN, JOIN_RESPONSE, - UPDATE_NEIGHBOURS, UPDATE_NEIGHBOURS_RESPONSE, - REQUEST_LONG_RANGE_LINK, ACCEPTED_LONG_RANGE_LINK, REJECT_LONG_RANGE_LINK, DISCONNECT_LONG_RANGE_LINK, UNAVAILABLE_LONG_RANGE_LINK, - UPDATE_STATUS, UPDATE_STATUS_RESPONSE, - LEAVE, - KEEP_ALIVE, KEEP_ALIVE_RESPONSE - } - private long hopCounter; - private MessageType type; - private Node src; - private Node currentHop; - private Object body; - private static long globalID = 0; - private final long id; - - public Message(Object body, Node src, MessageType type) { - this.type = type; - this.src = src; - this.body = body; - hopCounter = 0; - id = globalID++; - currentHop = src; - } - - public long getID() { - return id; - } - - public Object getBody() { - return body; - } - - public void incrementHop() { - hopCounter++; - } - - public long getHop() { - return hopCounter; - } - - public MessageType getType() { - return type; - } - - public Node getSourceNode() { - return src; - } - - public Node getCurrentHop() { - return currentHop; - } - - public void setCurrentHop(Node currentHop) { - this.currentHop = currentHop; - } - - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - @Override - public String toString() { - - StringBuilder builder = new StringBuilder(); - builder.append("Message@").append(this.hashCode()).append("[\n"); - - builder.append("\tID : ").append(id).append(",\n"); - builder.append("\tSource ID: ").append(src.getID()).append(",\n"); - builder.append("\tType : ").append(type).append(",\n"); - builder.append("\tBody : ").append(body).append(",\n"); - builder.append("\tCurrent Hop ID: ").append(currentHop.getID()).append(",\n"); - builder.append("\tHop Counter : ").append(hopCounter).append("\n]\n"); - - return builder.toString(); - } -} diff --git a/contrib/psg/src/example/symphony/NetworkSizeEstimatorProtocolInterface.java b/contrib/psg/src/example/symphony/NetworkSizeEstimatorProtocolInterface.java deleted file mode 100644 index ffb8ba9972..0000000000 --- a/contrib/psg/src/example/symphony/NetworkSizeEstimatorProtocolInterface.java +++ /dev/null @@ -1,13 +0,0 @@ -package example.symphony; - -import peersim.core.Node; -import peersim.core.Protocol; - -/** - * - * @author Andrea Esposito - */ -public interface NetworkSizeEstimatorProtocolInterface extends Protocol { - - public int getNetworkSize(Node node); -} diff --git a/contrib/psg/src/example/symphony/RandomRouteTest.java b/contrib/psg/src/example/symphony/RandomRouteTest.java deleted file mode 100644 index fe55f332b0..0000000000 --- a/contrib/psg/src/example/symphony/RandomRouteTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package example.symphony; - -import java.util.logging.Level; -import java.util.logging.Logger; -import peersim.config.Configuration; -import peersim.core.CommonState; -import peersim.core.Control; -import peersim.core.Network; -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class RandomRouteTest implements Control, Handler { - - private static final String PAR_SYMPHONY = "symphony"; - private final int symphonyID; - - public RandomRouteTest(String prefix) { - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMPHONY); - } - - public boolean execute() { - - Node src = Network.get(Math.abs(CommonState.r.nextInt()) % Network.size()); - - SymphonyProtocol symphony = (SymphonyProtocol) src.getProtocol(symphonyID); - try { - symphony.route(src, CommonState.r.nextDouble(), this); - } catch (RoutingException ex) { - Logger.getLogger(RandomRouteTest.class.getName()).log(Level.SEVERE, ex.getMessage()); - } - - return false; - - } - - public void handle(SymphonyProtocol symphony, Tuple tuple) { - - if (tuple == null) { - Logger.getLogger(RandomRouteTest.class.getName()).log(Level.SEVERE, "FAIL ROUTE RANDOMTEST"); - return; - } - - Logger.getLogger(RandomRouteTest.class.getName()).log(Level.FINE, symphony.getIdentifier() + " source find the manager of " + tuple.y + " and it is " + ((SymphonyProtocol) tuple.x.getProtocol(symphonyID)).getIdentifier()); - } -} diff --git a/contrib/psg/src/example/symphony/RingRouteTest.java b/contrib/psg/src/example/symphony/RingRouteTest.java deleted file mode 100644 index 06262cb119..0000000000 --- a/contrib/psg/src/example/symphony/RingRouteTest.java +++ /dev/null @@ -1,150 +0,0 @@ -package example.symphony; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.logging.Level; -import java.util.logging.Logger; - -import example.symphony.SymphonyProtocol.BootstrapStatus; -import peersim.config.Configuration; -import peersim.core.Control; -import peersim.core.Network; -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class RingRouteTest implements Control, Handler { - - private static final String PAR_SYMPHONY = "symphony"; - private static final String PAR_STARTNODE = "startnode"; - private final int symphonyID; - private final int indexStartNode; - private Node start; - private boolean finished; - private boolean flagTimeout; - private HashSet antiLoopSet; - - public RingRouteTest(String prefix) { - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMPHONY); - indexStartNode = Configuration.getInt(prefix + "." + PAR_STARTNODE, 0); - - finished = true; - flagTimeout = false; - antiLoopSet = new HashSet(); - } - - public boolean execute() { - - if (!finished && flagTimeout) { - - Logger.getLogger(RingRouteTest.class.getName()).log(Level.WARNING, "Sent msg but no aswer. Timeout. Ring Route Test terminated for Timeout."); - - finished = true; - flagTimeout = false; - } - - if (finished) { - - flagTimeout = true; - antiLoopSet.clear(); - - int indexRealStartNode = indexStartNode; - Node realStartNode = Network.get(indexStartNode); - SymphonyProtocol symphony = (SymphonyProtocol) realStartNode.getProtocol(symphonyID); - - while (!symphony.isBootstrapped() || !realStartNode.isUp()) { - indexRealStartNode = (indexRealStartNode + 1) % Network.size(); - realStartNode = Network.get(indexRealStartNode); - symphony = (SymphonyProtocol) realStartNode.getProtocol(symphonyID); - - if (indexRealStartNode == indexStartNode) { - Logger.getLogger(RingRouteTest.class.getName()).log(Level.WARNING, "No ONLINE nodes. The ring is vanished. Ring Route Terminated."); - finished = true; - flagTimeout = false; - return false; - } - } - - start = realStartNode; - finished = false; - - Logger.getLogger(RingRouteTest.class.getName()).log(Level.INFO, "RingRoute started."); - - doRoute(start, true); - } - - return false; - } - - public void handle(SymphonyProtocol symphony, Tuple tuple) { - - if (tuple == null) { - Logger.getLogger(RingRouteTest.class.getName()).log(Level.SEVERE, "FAIL RING ROUTING"); - finished = true; - return; - } - - Logger.getLogger(RingRouteTest.class.getName()).log(Level.FINER, symphony.getIdentifier() + " source find the manager of " + tuple.y + " and it is " + ((SymphonyProtocol) tuple.x.getProtocol(symphonyID)).getIdentifier()); - - doRoute(tuple.x, false); - } - - private void doRoute(Node node, boolean firstTime) { - - SymphonyProtocol symphonyStartNode = (SymphonyProtocol) start.getProtocol(symphonyID); - - if (!symphonyStartNode.isBootstrapped()) { - Logger.getLogger(RingRouteTest.class.getName()).log(Level.INFO, "The node i started from left. Ring Route Terminated."); - finished = true; - return; - } - - if (!firstTime && node.equals(start)) { - Logger.getLogger(RingRouteTest.class.getName()).log(Level.INFO, "RingRoute Terminated"); - finished = true; - return; - } - - if (antiLoopSet.contains(node)) { - Logger.getLogger(RingRouteTest.class.getName()).log(Level.INFO, "Not able to reach the node that i started from. Ring Route Terminated."); - finished = true; - return; - } else { - antiLoopSet.add(node); - } - - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - AdapterSymphonyNodeComparator adapterSymphonyNodeComparator = new AdapterSymphonyNodeComparator(new SymphonyNodeComparator(symphonyID, node)); - - Collection> collection = (Collection>) symphony.leftShortRangeLinks.clone(); - LinkedList> list = new LinkedList>(collection); - Collections.sort(list, adapterSymphonyNodeComparator); - - Node targetNode = null; - for (Tuple tuple : list) { - if (tuple.y == BootstrapStatus.ONLINE) { - targetNode = tuple.x; - break; - } - } - - if (targetNode == null || !targetNode.isUp()) { - Logger.getLogger(RingRouteTest.class.getName()).log(Level.WARNING, "Terminated Ring Route but not done completely"); - finished = true; - return; - } - - SymphonyProtocol symphonyTarget = (SymphonyProtocol) targetNode.getProtocol(symphonyID); - try { - symphony.route(node, symphonyTarget.getIdentifier(), this); - Logger.getLogger(RingRouteTest.class.getName()).log(Level.FINEST, "Ring from: " + symphony.getIdentifier() + " to " + symphonyTarget.getIdentifier()); - } catch (RoutingException ex) { - Logger.getLogger(RingRouteTest.class.getName()).log(Level.WARNING, "Finito AnelloRoute MA NON FATTO TUTTO"); - finished = true; - } - } -} diff --git a/contrib/psg/src/example/symphony/RoutingException.java b/contrib/psg/src/example/symphony/RoutingException.java deleted file mode 100644 index 1b6bb9b878..0000000000 --- a/contrib/psg/src/example/symphony/RoutingException.java +++ /dev/null @@ -1,15 +0,0 @@ -package example.symphony; - -/** - * - * @author Andrea Esposito - */ -public class RoutingException extends Exception { - - public RoutingException() { - } - - public RoutingException(String msg) { - super(msg); - } -} diff --git a/contrib/psg/src/example/symphony/SimpleNetworkSizeEstimatorProtocol.java b/contrib/psg/src/example/symphony/SimpleNetworkSizeEstimatorProtocol.java deleted file mode 100644 index 6d17371b87..0000000000 --- a/contrib/psg/src/example/symphony/SimpleNetworkSizeEstimatorProtocol.java +++ /dev/null @@ -1,23 +0,0 @@ -package example.symphony; - -import peersim.core.Network; -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class SimpleNetworkSizeEstimatorProtocol implements NetworkSizeEstimatorProtocolInterface { - - public SimpleNetworkSizeEstimatorProtocol(String prefix) { - } - - public int getNetworkSize(Node node) { - return Network.size(); - } - - @Override - public Object clone() { - return this; - } -} diff --git a/contrib/psg/src/example/symphony/SymphonyEstimationProtocol.java b/contrib/psg/src/example/symphony/SymphonyEstimationProtocol.java deleted file mode 100644 index 642677d2bb..0000000000 --- a/contrib/psg/src/example/symphony/SymphonyEstimationProtocol.java +++ /dev/null @@ -1,106 +0,0 @@ -package example.symphony; - -import java.util.*; -import peersim.config.Configuration; -import peersim.core.Network; -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class SymphonyEstimationProtocol implements NetworkSizeEstimatorProtocolInterface { - - private static final String PAR_SYMPHONY = "symphony"; - private static final String PAR_S = "s"; - private final int symphonyID; - private final int s; - - public SymphonyEstimationProtocol(String prefix) { - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMPHONY); - s = Configuration.getInt(prefix + "." + PAR_S, -1); - } - - /** - * Implementation of the estimated network size as a variant of the paper one. It use anyway the - * idea to calculate the size from the length segments but without exchanging the information - * with the neighbours instead using only the local information. - */ - public int getNetworkSize(Node node) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - - // If the node is not yet inside the ring i return the minimum size (2 nodes) - if (!symphony.isBootstrapped()) { - return 2; - } - - /* - * I clone the short range links views (wrapped into an ArrayList because the returned list - * 'Arrays.asList doesn't support the "removeAll" method or better its size is fixed) - */ - ArrayList> leftList = new ArrayList>(Arrays.asList((Tuple[]) symphony.leftShortRangeLinks.toArray(new Tuple[0]))); - ArrayList> rightList = new ArrayList>(Arrays.asList((Tuple[]) symphony.rightShortRangeLinks.toArray(new Tuple[0]))); - - // Remove the neighbours that are offline - LinkedList> offlineNeighbors = new LinkedList>(); - for (Tuple tuple : leftList) { - if (tuple.y == SymphonyProtocol.BootstrapStatus.OFFLINE) { - offlineNeighbors.add(tuple); - } - } - leftList.removeAll(offlineNeighbors); - offlineNeighbors.clear(); - for (Tuple tuple : rightList) { - if (tuple.y == SymphonyProtocol.BootstrapStatus.OFFLINE) { - offlineNeighbors.add(tuple); - } - } - rightList.removeAll(offlineNeighbors); - - // Sort the neighbours based on the distance from me - Comparator> comparator = new AdapterSymphonyNodeComparator(new SymphonyNodeComparator(symphonyID, symphony.getIdentifier())); - Collections.sort(leftList, comparator); - Collections.sort(rightList, comparator); - - // Calculate the variables to estimated the network size - double Xs = 0; - int countS = 0; - - List> appoList[] = new List[2]; - appoList[0] = leftList; - appoList[1] = rightList; - - double[] appoPrecIdentifier = new double[]{symphony.getIdentifier(), symphony.getIdentifier()}; - int[] appoCurrentIndex = new int[]{0, 0}; - - int realS = (int) (s <= 0 ? Math.log(Network.size() / Math.log(2)) : s); - - for (int i = 0; i < realS; i++) { - double precIdentifier = appoPrecIdentifier[i % 2]; - int currentIndex = appoCurrentIndex[i % 2]; - List> currentList = appoList[i % 2]; - - try { - double currentIdentifier = ((SymphonyProtocol) currentList.get(currentIndex).x.getProtocol(symphonyID)).getIdentifier(); - - appoPrecIdentifier[i % 2] = currentIdentifier; - appoCurrentIndex[i % 2] = appoCurrentIndex[i % 2] + 1; - - double distance = Math.abs(currentIdentifier - precIdentifier); - Xs += Math.min(distance, 1.0 - distance); - countS++; - } catch (IndexOutOfBoundsException ex) { - // Simply i skip the counting - } - } - - int ret = Xs == 0 ? 0 : (int) Math.round(countS / Xs); - - return ret; - } - - @Override - public Object clone() { - return this; - } -} diff --git a/contrib/psg/src/example/symphony/SymphonyNetworkBuilder.java b/contrib/psg/src/example/symphony/SymphonyNetworkBuilder.java deleted file mode 100644 index a012d600bb..0000000000 --- a/contrib/psg/src/example/symphony/SymphonyNetworkBuilder.java +++ /dev/null @@ -1,157 +0,0 @@ -package example.symphony; - -import java.util.Collection; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.logging.Level; -import java.util.logging.Logger; - -import example.symphony.SymphonyProtocol.BootstrapStatus; -import peersim.config.Configuration; -import peersim.core.CommonState; -import peersim.core.Control; -import peersim.core.Network; -import peersim.core.Node; - -/** - * Inizializer that create the initial ring - * - * @author Andrea Esposito - */ -public class SymphonyNetworkBuilder implements Control { - - private static final String PAR_SYMHONY = "symphony"; - private static final String PAR_LONG_LINK = "createLongLinks"; - private static final String PAR_MAX_ATTEMPTS = "attempts"; - private final int symphonyID; - private final boolean createLongRangeLinks; - private final int MAX_ATTEMPTS; - - public SymphonyNetworkBuilder(String prefix) { - - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMHONY); - createLongRangeLinks = Configuration.getBoolean(prefix + "." + PAR_LONG_LINK, true); - MAX_ATTEMPTS = Configuration.getInt(prefix + "." + PAR_MAX_ATTEMPTS, 5); - } - - public boolean execute() { - - // Sort the network for convenience (from 0.0 to 1.0) - Network.sort(new Comparator() { - - public int compare(Node o1, Node o2) { - - SymphonyProtocol symphony1 = (SymphonyProtocol) o1.getProtocol(symphonyID); - SymphonyProtocol symphony2 = (SymphonyProtocol) o2.getProtocol(symphonyID); - - Double identifier1 = symphony1.getIdentifier(); - Double identifier2 = symphony2.getIdentifier(); - - return identifier1.compareTo(identifier2); - } - }); - - int numShortLinksPerSide = ((SymphonyProtocol) Network.get(0).getProtocol(symphonyID)).numberShortRangeLinksPerSide; - - for (int i = 0; i < Network.size(); i++) { - - Node node = Network.get(i); - SymphonyProtocol symphonyNode = (SymphonyProtocol) node.getProtocol(symphonyID); - - // Create the short links - for (int j = 1; j <= numShortLinksPerSide; j++) { - - int pos = i - j; - pos = pos < 0 ? Network.size() + pos : pos; - symphonyNode.rightShortRangeLinks.add(new Tuple(Network.get(pos), BootstrapStatus.ONLINE)); - - pos = (i + j) % Network.size(); - symphonyNode.leftShortRangeLinks.add(new Tuple(Network.get(pos), BootstrapStatus.ONLINE)); - } - - symphonyNode.loggedIntoNetwork = SymphonyProtocol.BootstrapStatus.ONLINE; - } - - /* - * UPDATE: Putted a flag to decide if perform this part of code or not at configuration - * time. At default i create the long range links. - * - * The Long Range Links could be left to the networkmanager but the tests that we'll do have - * to put into account that in an initial phase will be some message exchanging to create - * the long range links and so the latency is faked... for that reason the long range links - * are created manually here such a way to have a complete symphony network from the - * beginning. - */ - if (createLongRangeLinks) { - for (Node node : new AdapterIterableNetwork()) { - - SymphonyProtocol symphonyNode = (SymphonyProtocol) node.getProtocol(symphonyID); - - // Create the long links - int k = (int) Math.ceil(Math.log(Network.size()) / Math.log(2)); - - if (symphonyNode.fixedLongRangeLinks) { - k = symphonyNode.numberFixedLongRangeLinks; - } - - Collection allShortLinks = new LinkedList(); - for (Tuple shortTuple : symphonyNode.leftShortRangeLinks) { - allShortLinks.add(shortTuple.x); - } - for (Tuple shortTuple : symphonyNode.rightShortRangeLinks) { - allShortLinks.add(shortTuple.x); - } - - int j = 0; - int attempts = MAX_ATTEMPTS; - while (j <= k) { - - double distance = Math.exp(k * (CommonState.r.nextDouble() - 1.0)); - double targetIdentifier = (symphonyNode.getIdentifier() + distance) % 1; - - Node targetNode; - try { - - // use the unidirectional routing because i want to catch the manager - targetNode = symphonyNode.findClosestNode(targetIdentifier, new AdapterIterableNetwork(), true); - SymphonyProtocol symphonyTargetNode = (SymphonyProtocol) targetNode.getProtocol(symphonyID); - if (!targetNode.equals(node) - && !symphonyNode.longRangeLinksOutgoing.contains(targetNode) - && symphonyTargetNode.longRangeLinksIncoming.size() < (2 * k) - && !allShortLinks.contains(targetNode)) { - - boolean fresh = symphonyTargetNode.longRangeLinksIncoming.add(node); - - if (fresh) { - j++; - attempts = MAX_ATTEMPTS; - symphonyNode.longRangeLinksOutgoing.add(targetNode); - } else { - attempts--; - if (attempts <= 0) { // Because i don't want to loop i try a finite number of times - attempts = MAX_ATTEMPTS; - j++; - } - - } - } else { - attempts--; - if (attempts <= 0) { // Because i don't want to loop i try a finite number of times - attempts = MAX_ATTEMPTS; - j++; - } - - } - } catch (RoutingException ex) { - Logger.getLogger(SymphonyNetworkBuilder.class.getName()).log(Level.SEVERE, null, ex); - } - } - } - } - - // Shuffle - Network.shuffle(); - - return false; - } -} diff --git a/contrib/psg/src/example/symphony/SymphonyNetworkChecker.java b/contrib/psg/src/example/symphony/SymphonyNetworkChecker.java deleted file mode 100644 index d5f2aef4aa..0000000000 --- a/contrib/psg/src/example/symphony/SymphonyNetworkChecker.java +++ /dev/null @@ -1,123 +0,0 @@ -package example.symphony; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import example.symphony.SymphonyProtocol.BootstrapStatus; -import peersim.config.Configuration; -import peersim.core.Control; -import peersim.core.Network; -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class SymphonyNetworkChecker implements Control { - - private static final String PAR_SYMHONY = "symphony"; - private static final String PAR_NETSIZE = "networkestimator"; - private final int symphonyID; - private final int networkEstimatorID; - - public SymphonyNetworkChecker(String prefix) { - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMHONY); - networkEstimatorID = Configuration.getPid(prefix + "." + PAR_NETSIZE); - } - - public boolean execute() { - - boolean isNotOK = false; - - Set idSet = new HashSet(); - Iterable coll = new AdapterIterableNetwork(); - - int countOnline = 0; - int count = 0; - int notBootstrapped = 0; - int countKO = 0; - int disconnected = 0; - - for (Node node : coll) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - - if (!node.isUp()) { - disconnected++; - } else { - count++; - } - - if (symphony.loggedIntoNetwork == SymphonyProtocol.BootstrapStatus.ONLINE) { - - countOnline++; - - NetworkSizeEstimatorProtocolInterface networkEstimator = (NetworkSizeEstimatorProtocolInterface) node.getProtocol(networkEstimatorID); - int k = (int) Math.ceil(Math.log(networkEstimator.getNetworkSize(node)) / Math.log(2)); - - boolean checkLeftShortRangeLinks = symphony.leftShortRangeLinks.size() > 0 && symphony.leftShortRangeLinks.size() <= symphony.numberShortRangeLinksPerSide; - boolean checkRightShortRangeLinks = symphony.rightShortRangeLinks.size() > 0 && symphony.rightShortRangeLinks.size() <= symphony.numberShortRangeLinksPerSide; - - boolean oneNeighborOnline = false; - for (Tuple leftTuple : symphony.leftShortRangeLinks) { - if (leftTuple.y != BootstrapStatus.ONLINE && leftTuple.y != BootstrapStatus.OFFLINE) { - notBootstrapped++; - } else { - oneNeighborOnline = true; - checkLeftShortRangeLinks = checkLeftShortRangeLinks && SymphonyProtocol.isLeftNeighbour(node, leftTuple.x); - } - } - checkLeftShortRangeLinks = checkLeftShortRangeLinks && oneNeighborOnline; - - oneNeighborOnline = false; - for (Tuple rightTuple : symphony.rightShortRangeLinks) { - if (rightTuple.y != BootstrapStatus.ONLINE && rightTuple.y != BootstrapStatus.OFFLINE) { - notBootstrapped++; - } else { - oneNeighborOnline = true; - checkRightShortRangeLinks = checkRightShortRangeLinks && !SymphonyProtocol.isLeftNeighbour(node, rightTuple.x); - } - } - checkRightShortRangeLinks = checkRightShortRangeLinks && oneNeighborOnline; - - // Check if the node is in its neighbours - if (checkLeftShortRangeLinks) { - AdapterSymphonyNodeComparator comparator = new AdapterSymphonyNodeComparator(new SymphonyNodeComparator(symphonyID, node)); - checkLeftShortRangeLinks = checkLeftShortRangeLinks && !Collections.min(symphony.leftShortRangeLinks, comparator).x.equals(node); - } - - if (checkRightShortRangeLinks) { - AdapterSymphonyNodeComparator comparator = new AdapterSymphonyNodeComparator(new SymphonyNodeComparator(symphonyID, node)); - checkRightShortRangeLinks = checkRightShortRangeLinks && !Collections.min(symphony.rightShortRangeLinks, comparator).x.equals(node); - } - - boolean checkLongRangeLinksOutgoing = !symphony.longRangeLinksOutgoing.contains(node); - boolean checkLongRangeLinksIncoming = /* - * symphony.longRangeLinksIncoming.size() <= (2 * k) && - */ !symphony.longRangeLinksIncoming.contains(node); - - boolean checkUniqueID = !idSet.contains(symphony.getIdentifier()); - idSet.add(symphony.getIdentifier()); - - boolean nextIsNotOK = !(checkUniqueID && checkLeftShortRangeLinks && checkRightShortRangeLinks && checkLongRangeLinksOutgoing && checkLongRangeLinksIncoming); - - if (nextIsNotOK) { - countKO++; - Logger.getLogger(SymphonyNetworkChecker.class.getName()).log(Level.SEVERE, "OPS"); - } - - isNotOK = isNotOK || nextIsNotOK; - } - } - - System.out.println("Error: " + countKO); - System.out.println("Online: " + countOnline + "/" + count); - System.out.println("Not Bootstrapped: " + notBootstrapped); - System.out.println("Disconnected: " + disconnected); - System.out.println("Network Size: " + Network.size()); - - return isNotOK; - } -} diff --git a/contrib/psg/src/example/symphony/SymphonyNetworkManager.java b/contrib/psg/src/example/symphony/SymphonyNetworkManager.java deleted file mode 100644 index 4a1277fc86..0000000000 --- a/contrib/psg/src/example/symphony/SymphonyNetworkManager.java +++ /dev/null @@ -1,864 +0,0 @@ -package example.symphony; - -import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; - -import example.symphony.Message.MessageType; -import example.symphony.SymphonyProtocol.BootstrapStatus; -import peersim.cdsim.CDProtocol; -import peersim.config.Configuration; -import peersim.core.CommonState; -import peersim.core.Fallible; -import peersim.core.Node; -import peersim.edsim.EDProtocol; -import peersim.transport.Transport; - -/** - * - * @author Andrea Esposito - */ -public class SymphonyNetworkManager implements EDProtocol, CDProtocol { - - private static final String PAR_SYMPHONY = "symphony"; - private static final String PAR_TRANSP = "transport"; - private static final String PAR_ATTEMPTS = "attempts"; - private static final String PAR_NETSIZE = "networkestimator"; - private static final String PAR_NUM_TIMEOUT = "nTimeout"; - private static final String PAR_RELINKING = "relinking"; - private static final String PAR_RELINKING_LOWER_BOUND = "relinkingLowerBound"; - private static final String PAR_RELINKING_UPPER_BOUND = "relinkingUpperBound"; - private static final int DEFAULT_K = 1; - private static final int DEFAULT_N = 2; - private static final double DEFAULT_RELINKING_LOWER_BOUND = 0.5; - private static final double DEFAULT_RELINKING_UPPER_BOUND = 2.0; - private final String prefix; - private final int symphonyID; - private final int transportID; - private final int networkEstimatorID; - private final int attempts; - private final int pid; - private final int nTimeout; - private final HashMap keepAliveMap; - private final boolean relinkingProtocolActivated; - private final double relinkingUpperBound; - private final double relinkingLowerBound; - private int k = DEFAULT_K; // Number of Long Range Link - private int n = DEFAULT_N; // Estimation Network size - private static boolean firstPrintConfig = true; - /* - * Estimation Network size at which last long distance link was established, at the beginning -1 - * to indicate that we never had Long Range Links - */ - private int nLink = -1; - private int currentAttempts; - - public SymphonyNetworkManager(String prefix) { - - this.prefix = prefix; - pid = Configuration.lookupPid(prefix.replaceAll("protocol.", "")); - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMPHONY); - transportID = Configuration.getPid(prefix + "." + PAR_TRANSP); - networkEstimatorID = Configuration.getPid(prefix + "." + PAR_NETSIZE); - attempts = Configuration.getInt(prefix + "." + PAR_ATTEMPTS); - nTimeout = Configuration.getInt(prefix + "." + PAR_NUM_TIMEOUT, 10); - relinkingProtocolActivated = !Configuration.getString(prefix + "." + PAR_RELINKING, "on").toLowerCase().equals("off"); - double relinkingLowerBoundAppo = Configuration.getDouble(prefix + "." + PAR_RELINKING_LOWER_BOUND, DEFAULT_RELINKING_LOWER_BOUND); - double relinkingUpperBoundAppo = Configuration.getDouble(prefix + "." + PAR_RELINKING_UPPER_BOUND, DEFAULT_RELINKING_UPPER_BOUND); - if (relinkingLowerBoundAppo > relinkingUpperBoundAppo) { - relinkingLowerBound = DEFAULT_RELINKING_LOWER_BOUND; - relinkingUpperBound = DEFAULT_RELINKING_UPPER_BOUND; - } else { - relinkingLowerBound = relinkingLowerBoundAppo; - relinkingUpperBound = relinkingUpperBoundAppo; - } - - keepAliveMap = new HashMap(); - - printConfig(); - } - - private void printConfig() { - - if (firstPrintConfig) { - firstPrintConfig = false; - System.out.println(SymphonyNetworkManager.class.getSimpleName() + " Configuration:"); - System.out.println("- Attempts per LongRangeLinks: " + attempts); - System.out.println("- Number of Timeout before a node is considered OFFLINE (through Keep-alive):" + nTimeout); - System.out.println("- Relinking: " + (relinkingProtocolActivated ? "ON" : "OFF")); - System.out.println("- Relinking Range: [" + relinkingLowerBound + ", " + relinkingUpperBound + "]"); - System.out.println("-------------------------------\n"); - } - } - - public void join(final Node node, final Node bootstrapNode) throws RoutingException { - final SymphonyProtocol bootstrapSymphony = (SymphonyProtocol) bootstrapNode.getProtocol(symphonyID); - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - - /* - * Search (through the bootstrap node) and contact the Manager Node of myself such a way to - * be able to insert myself into the ring and create the short links - * - */ - bootstrapSymphony.route(bootstrapNode, symphony.getIdentifier(), new Handler() { - - public void handle(SymphonyProtocol src, Tuple tuple) { - if (tuple == null) { - Logger.getLogger(SymphonyNetworkManager.class.getName()).log(Level.SEVERE, "FAIL ROUTE JOIN"); - node.setFailState(Fallible.DEAD); - return; - } - - Node managerNode = tuple.x; - - Transport transport = (Transport) node.getProtocol(transportID); - Message msg = new Message(node, node, MessageType.JOIN); - transport.send(node, managerNode, msg, pid); - } - }); - - // The Long Range Links are added after that i joined the ring (before i can't because i haven't got the nodes to do the routing) - } - - /** - * Conservative Re-Linking (i reuse the ones already created: not all fresh) - * - * @param node - */ - public void updateLongRangeLinks(Node node) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - Transport transport = (Transport) node.getProtocol(transportID); - - // if too much links i delete the farest ones - while (symphony.longRangeLinksOutgoing.size() > k) { - Node distantNode = Collections.max(symphony.longRangeLinksOutgoing, new SymphonyNodeComparator(symphonyID, node)); - symphony.longRangeLinksOutgoing.remove(distantNode); - - // Communicate to the outgoing node that it ins't anymore one of my long range links - Message disconnectMsg = new Message(null, node, MessageType.DISCONNECT_LONG_RANGE_LINK); - transport.send(node, distantNode, disconnectMsg, pid); - } - - // I can search Long Range Links only if i'm into the ring and i'm able to do routing - if (symphony.isBootstrapped()) { - // if only few i try again, untill attempts times, to add new ones - int difference = k - symphony.longRangeLinksOutgoing.size(); - currentAttempts = attempts; - for (int i = 0; i < difference; i++) { - sendLongRangeLinkRequest(symphony, node); - } - } - } - private static final int MAX_ANTILOOP_COUNT_MANAGER_MYSELF = 5; - private int antiLoopManagerMySelf = 0; - - private void sendLongRangeLinkRequest(final SymphonyProtocol symphony, final Node node) { - boolean routingOk; - do { - double distance = Math.exp((Math.log(n) / Math.log(2)) * (CommonState.r.nextDouble() - 1.0)); // Harmonic Distribution - double targetIdentifier = (symphony.getIdentifier() + distance) % 1; - try { - - symphony.route(node, targetIdentifier, new Handler() { - - public void handle(SymphonyProtocol src, Tuple tuple) { - - if (tuple == null) { - Logger.getLogger(SymphonyNetworkManager.class.getName()).log(Level.SEVERE, "FAIL ROUTE SENDLONGRANGELINKREQUEST"); - return; - } - - Collection allShortLinks = new LinkedList(); - for (Tuple shortTuple : symphony.leftShortRangeLinks) { - allShortLinks.add(shortTuple.x); - } - for (Tuple shortTuple : symphony.rightShortRangeLinks) { - allShortLinks.add(shortTuple.x); - } - - /* - * - * I'm myself one of my short links, special case... i try again without - * reduce the attempts for a maximum of MAX_ANTILOOP_COUNT_MANAGER_MYSELF - * times after that i start again to reduce the attempts - */ - if (tuple.x.equals(node) || allShortLinks.contains(tuple.x)) { - - if (antiLoopManagerMySelf < MAX_ANTILOOP_COUNT_MANAGER_MYSELF) { - - antiLoopManagerMySelf++; - sendLongRangeLinkRequest(symphony, node); - } else { - antiLoopManagerMySelf = 0; - currentAttempts--; - } - } else { - - boolean alreadyAdded = symphony.longRangeLinksOutgoing.contains(tuple.x); - /* - * - * OPINABLE: DESCREASE ATTEMPTS ONLY FOR REJECT? If yes i have to manage - * the possible loop (nodi exhaurited so already all added) - */ - if (alreadyAdded && currentAttempts > 0) { - currentAttempts--; - sendLongRangeLinkRequest(symphony, node); - } else if (!alreadyAdded) { - Message msg = new Message(null, node, MessageType.REQUEST_LONG_RANGE_LINK); - Transport transport = (Transport) node.getProtocol(transportID); - transport.send(node, tuple.x, msg, pid); - } - } - } - }); - routingOk = true; - } catch (RoutingException ex) { - routingOk = false; - } - } while (!routingOk); - } - - public void leave(Node node) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - - if (symphony.loggedIntoNetwork != BootstrapStatus.OFFLINE) { - Transport transport = (Transport) node.getProtocol(transportID); - - symphony.loggedIntoNetwork = BootstrapStatus.OFFLINE; - - // Communicate that i'm leaving to the outgoing (that i point to) nodes - for (Node outgoingNode : symphony.longRangeLinksOutgoing) { - Message disconnectMsg = new Message(null, node, MessageType.DISCONNECT_LONG_RANGE_LINK); - transport.send(node, outgoingNode, disconnectMsg, pid); - } - - // Communicate that i'm leaving to the incoming (that they point to me) nodes - for (Node incomingNode : symphony.longRangeLinksIncoming) { - Message unavailableMsg = new Message(null, node, MessageType.UNAVAILABLE_LONG_RANGE_LINK); - transport.send(node, incomingNode, unavailableMsg, pid); - } - - // Communicate to my neighbours (short range links) that i'm leaving and i send to them the near neighbours - for (Tuple leftTuple : symphony.leftShortRangeLinks) { - Message leaveMsg = new Message(symphony.rightShortRangeLinks.clone(), node, MessageType.LEAVE); - transport.send(node, leftTuple.x, leaveMsg, pid); - } - - for (Tuple rightTuple : symphony.rightShortRangeLinks) { - Message leaveMsg = new Message(symphony.leftShortRangeLinks.clone(), node, MessageType.LEAVE); - transport.send(node, rightTuple.x, leaveMsg, pid); - } - - node.setFailState(Fallible.DEAD); - } - } - - public void processEvent(Node node, int pid, Object event) { - - Message msg = (Message) event; - - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - Transport transport = (Transport) node.getProtocol(transportID); - - Collection> collection = null; - switch (msg.getType()) { - case JOIN: - // I send my current neighbours to the entering node - collection = (Collection>) symphony.leftShortRangeLinks.clone(); - collection.addAll((Collection>) symphony.rightShortRangeLinks.clone()); - Message responseMsg = new Message(collection, node, MessageType.JOIN_RESPONSE); - transport.send(node, msg.getSourceNode(), responseMsg, pid); - - /* - * Update my neighbours list, adding the new one (for sure it is entering in the - * left side) - * - * Put to "ONLINE_AND_ALL_NEIGHBOURS_OFFLINE" because maybe the bootstrap phase is - * not terminated yet (ashyncronous communication) - */ - symphony.leftShortRangeLinks.add(new Tuple(msg.getSourceNode(), BootstrapStatus.ONLINE_AND_ALL_NEIGHBOURS_OFFLINE)); - - - fixNeighbours(node, symphony.leftShortRangeLinks); - break; - case JOIN_RESPONSE: - - Collection> tupleCollection = (Collection>) msg.getBody(); - - /* - * - * My manager is a right neighbour. The manager is already inside the ring, boostrap - * obliviously ok - */ - symphony.rightShortRangeLinks.add(new Tuple(msg.getSourceNode(), BootstrapStatus.ONLINE)); - - // Set my neighbours in the correct position - for (Tuple tuple : tupleCollection) { - if (SymphonyProtocol.isLeftNeighbour(node, tuple.x)) { - symphony.leftShortRangeLinks.add(tuple); - } else { - symphony.rightShortRangeLinks.add(tuple); - } - } - - fixNeighbours(node, symphony.leftShortRangeLinks); - fixNeighbours(node, symphony.rightShortRangeLinks); - - // Update bootstrap status - checkBootstrapStatus(node); - - // I send the refresh command such a way to exchange the views - refreshNeighbours(node); - - // Update Long Range Links, because it's at the beginning is the same as adding k - updateLongRangeLinks(node); - break; - case UPDATE_NEIGHBOURS: - - Collection> collectionCloned = ((Collection>) symphony.leftShortRangeLinks.clone()); - collectionCloned.addAll(((Collection>) symphony.rightShortRangeLinks.clone())); - - // Send my neighbours such a way it can also update itself - Message responseUpdateMsg = new Message(collectionCloned, node, MessageType.UPDATE_NEIGHBOURS_RESPONSE); - transport.send(node, msg.getSourceNode(), responseUpdateMsg, pid); - - // Update my view with the new node - Tuple neighbourTuple = new Tuple(msg.getSourceNode(), (BootstrapStatus) msg.getBody()); - if (SymphonyProtocol.isLeftNeighbour(node, msg.getSourceNode())) { - collection = symphony.leftShortRangeLinks; - } else { - collection = symphony.rightShortRangeLinks; - } - collection.add(neighbourTuple); - - fixNeighbours(node, collection); - fixLookAheadMap(node); - break; - case UPDATE_NEIGHBOURS_RESPONSE: - - Collection> responseCollection = (Collection>) msg.getBody(); - - for (Tuple neighbourResponseTuple : responseCollection) { - if (SymphonyProtocol.isLeftNeighbour(node, neighbourResponseTuple.x)) { - collection = symphony.leftShortRangeLinks; - } else { - collection = symphony.rightShortRangeLinks; - } - collection.add(neighbourResponseTuple); - } - - // Fix the neighbours number to the maximum allow and maybe remove myself from the list - fixNeighbours(node, symphony.leftShortRangeLinks); - fixNeighbours(node, symphony.rightShortRangeLinks); - fixLookAheadMap(node); - break; - case UPDATE_STATUS: - case UPDATE_STATUS_RESPONSE: - - Node updNode = msg.getSourceNode(); - BootstrapStatus updStatus = (BootstrapStatus) msg.getBody(); - - // I search the neighbour and i update its status - boolean founded = false; - - // Try to see if it is on the left - for (Tuple leftTuple : symphony.leftShortRangeLinks) { - if (leftTuple.x.equals(updNode)) { - symphony.leftShortRangeLinks.remove(leftTuple); - symphony.leftShortRangeLinks.add(new Tuple(updNode, updStatus)); - - founded = true; - break; - } - } - - // If it isn't on the left i try with the neighbours on the right - if (!founded) { - for (Tuple rightTuple : symphony.rightShortRangeLinks) { - if (rightTuple.x.equals(updNode)) { - symphony.rightShortRangeLinks.remove(rightTuple); - symphony.rightShortRangeLinks.add(new Tuple(updNode, updStatus)); - - break; - } - } - - fixNeighbours(node, symphony.rightShortRangeLinks); - } else { - fixNeighbours(node, symphony.leftShortRangeLinks); - } - - checkBootstrapStatusAndAlert(node); - - if (msg.getType() == MessageType.UPDATE_STATUS) { - Message responseUpdStatus = new Message(symphony.loggedIntoNetwork, node, MessageType.UPDATE_STATUS_RESPONSE); - transport.send(node, updNode, responseUpdStatus, pid); - } - - break; - case REQUEST_LONG_RANGE_LINK: - MessageType responseType = MessageType.REJECT_LONG_RANGE_LINK; - if (symphony.longRangeLinksIncoming.size() < (2 * k)) { - boolean added = symphony.longRangeLinksIncoming.add(msg.getSourceNode()); - if (added) { - responseType = MessageType.ACCEPTED_LONG_RANGE_LINK; - } - } - Message responseLongLinkMsg = new Message(null, node, responseType); - transport.send(node, msg.getSourceNode(), responseLongLinkMsg, pid); - break; - case ACCEPTED_LONG_RANGE_LINK: - nLink = n; - symphony.longRangeLinksOutgoing.add(msg.getSourceNode()); - break; - case REJECT_LONG_RANGE_LINK: - if (currentAttempts > 0) { - currentAttempts--; - sendLongRangeLinkRequest(symphony, node); - } - break; - case DISCONNECT_LONG_RANGE_LINK: - symphony.longRangeLinksIncoming.remove(msg.getSourceNode()); - symphony.lookAheadMap.put(msg.getSourceNode(), null); - break; - case UNAVAILABLE_LONG_RANGE_LINK: - symphony.longRangeLinksOutgoing.remove(msg.getSourceNode()); - symphony.lookAheadMap.put(msg.getSourceNode(), null); - break; - case LEAVE: - Tuple foundedTuple = null; - - // Verify if the node that is leaving is a left neighbour - for (Tuple leftTuple : symphony.leftShortRangeLinks) { - if (leftTuple.x.equals(msg.getSourceNode())) { - collection = symphony.leftShortRangeLinks; - foundedTuple = leftTuple; - break; - } - } - - // Verify if the node that is leaving is a right neighbour - if (collection == null) { - for (Tuple rightTuple : symphony.rightShortRangeLinks) { - if (rightTuple.x.equals(msg.getSourceNode())) { - collection = symphony.rightShortRangeLinks; - foundedTuple = rightTuple; - break; - } - } - } - - // if i've found the neighbour i remove it and i add to myself its neighbours - if (collection != null) { - collection.addAll((Collection>) msg.getBody()); - collection.remove(foundedTuple); - fixNeighbours(node, collection); - - // Update status and ready to send an alert in case i'm out of the ring - checkBootstrapStatusAndAlert(node); - } - break; - case KEEP_ALIVE: - Set[] lookAheadSetArray = new LinkedHashSet[2]; - - /* - * Check if the contacting node is doing lookAhead and in case of affirmative answer - * i provide to it the long range link identifiers (according to my routing mode) - */ - if ((Boolean) msg.getBody()) { - int i = 0; - Iterable[] iterableArray; - if (symphony.bidirectionalRouting) { - iterableArray = new Iterable[]{symphony.longRangeLinksOutgoing, symphony.longRangeLinksIncoming}; - } else { - iterableArray = new Iterable[]{symphony.longRangeLinksOutgoing}; - } - - for (Iterable iterable : iterableArray) { - lookAheadSetArray[i] = new LinkedHashSet(); - Set lookAheadSet = lookAheadSetArray[i]; - Iterator it = iterable.iterator(); - while (it.hasNext()) { - Node longLinkNode = it.next(); - lookAheadSet.add(((SymphonyProtocol) longLinkNode.getProtocol(symphonyID)).getIdentifier()); - } - i++; - } - } - - transport.send(node, msg.getSourceNode(), new Message(lookAheadSetArray, node, MessageType.KEEP_ALIVE_RESPONSE), pid); - break; - case KEEP_ALIVE_RESPONSE: - // Reset the counter to 0 - keepAliveMap.put(msg.getSourceNode(), 0); - - if (symphony.lookAhead) { - symphony.lookAheadMap.put(msg.getSourceNode(), (Set[]) msg.getBody()); - } - - break; - } - } - - /** - * - * Update the status and communicate immediately to the neighbours if the node is gone out from - * the ring (and before it was inside) - * - * @param node - */ - private void checkBootstrapStatusAndAlert(Node node) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - BootstrapStatus beforeStatus = symphony.loggedIntoNetwork; - - checkBootstrapStatus(node); - - // Instead of waiting that the update happens periodically i do it now because i'm out of the ring and before i wasn't - if (symphony.loggedIntoNetwork != beforeStatus && !symphony.isBootstrapped()) { - updateBootstrapStatusNeighbours(node, true); - } - } - - private void fixNeighbours(Node node, Collection> neighbours) { - - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - - // Remove duplicates, remove that ones that are in an obsolete status - Collection> removedNeighbours = new LinkedHashSet>(); - for (Tuple tuple : neighbours) { - - // Remove myself from the neighbours list - if (tuple.x.equals(node)) { - removedNeighbours.add(tuple); - continue; - } - - EnumSet status = EnumSet.allOf(BootstrapStatus.class); - status.remove(tuple.y); - - for (BootstrapStatus opposite : status) { - Tuple oppositeNeighbour = new Tuple(tuple.x, opposite); - if (neighbours.contains(oppositeNeighbour)) { - if (tuple.y != BootstrapStatus.ONLINE) { - removedNeighbours.add(new Tuple(tuple.x, BootstrapStatus.OFFLINE)); - if (opposite == BootstrapStatus.ONLINE) { - removedNeighbours.add(new Tuple(tuple.x, BootstrapStatus.ONLINE_AND_ALL_NEIGHBOURS_OFFLINE)); - } - } - } - } - } - neighbours.removeAll(removedNeighbours); - - /* - * - * I count the neighbours that are in the ONLINE status but before i remove the ones that - * are gone in timeout during the keep-alive procedure because can be someone that is old - * but not remove from the exchanging views (UPDATE_NEIGHBOURS) procedure and are not - * effectively online. To do anyway the possibility to the node to join again i decrease its - * timeout value. This only if the node is ONLINE and so i'm really interested that it is ok - * for the routing. - * - */ - int onlineNeighbours = 0; - for (Tuple tuple : neighbours) { - - Integer value = keepAliveMap.get(tuple.x); - if (value != null && value >= nTimeout && tuple.y == BootstrapStatus.ONLINE) { - keepAliveMap.put(tuple.x, value - 1); - removedNeighbours.add(tuple); - } else { - - if (tuple.y == BootstrapStatus.ONLINE) { - onlineNeighbours++; - } - } - } - neighbours.removeAll(removedNeighbours); - - // Fix the neighbours number to the maximum allowed - SymphonyNodeComparator comparator = new SymphonyNodeComparator(symphonyID, node); - AdapterSymphonyNodeComparator adapterComparator = new AdapterSymphonyNodeComparator(comparator); - while (neighbours.size() > symphony.numberShortRangeLinksPerSide) { - Tuple distantTuple = Collections.max(neighbours, adapterComparator); - - // Mantain the link with the ring - if (distantTuple.y == BootstrapStatus.ONLINE) { - if (onlineNeighbours > 1) { - neighbours.remove(distantTuple); - onlineNeighbours--; - } else { - /* - * If will be only one neighbour that is online i save it and i'm going to - * eliminate another one (for sure it'll be not online) - * - */ - Tuple backupOnlineNeighbour = distantTuple; - neighbours.remove(backupOnlineNeighbour); - distantTuple = Collections.max(neighbours, adapterComparator); - neighbours.add(backupOnlineNeighbour); - neighbours.remove(distantTuple); - } - - } else { - neighbours.remove(distantTuple); - } - } - } - - @Override - public Object clone() { - SymphonyNetworkManager dolly = new SymphonyNetworkManager(prefix); - return dolly; - } - - public void nextCycle(Node node, int protocolID) { - - if (node.isUp()) { - - // Update the estimated network size - updateN(node); - - // Update the estimated K - updateK(node); - - // Update the bootstrap status of my neighbours that were joining the ring - updateBootstrapStatusNeighbours(node, false); - - // Refresh the neighbours views - refreshNeighbours(node); - - // I send and check the connection status of the neighbours - keepAlive(node); - - // Update the bootstrap status - checkBootstrapStatus(node); - - // If it's active i check the Relinking criteria - if (relinkingProtocolActivated) { - reLinkingProtocol(node); - } - - // Update the long range links (conservative) - updateLongRangeLinks(node); - } - } - - /** - * - * @param allNeighbours true, communicate/receive the status update from all the neighbours. - * false, communicate/receive the status update only from the neighbours that are NOT ONLINE - * - */ - private void updateBootstrapStatusNeighbours(Node node, boolean allNeighbours) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - Transport transport = (Transport) node.getProtocol(transportID); - - Collection> collection = new LinkedHashSet>(); - collection.addAll(symphony.leftShortRangeLinks); - collection.addAll(symphony.rightShortRangeLinks); - - for (Tuple neighbourTuple : collection) { - if (allNeighbours || neighbourTuple.y != BootstrapStatus.ONLINE) { - Message msg = new Message(symphony.loggedIntoNetwork, node, MessageType.UPDATE_STATUS); - transport.send(node, neighbourTuple.x, msg, pid); - } - } - } - - private void updateN(Node node) { - NetworkSizeEstimatorProtocolInterface networkEstimator = (NetworkSizeEstimatorProtocolInterface) node.getProtocol(networkEstimatorID); - n = networkEstimator.getNetworkSize(node); - if (n <= 0) { - n = DEFAULT_N; - } - } - - /** - * Update the K value with the current expectation of the network size - */ - private void updateK(Node node) { - - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - if (!symphony.fixedLongRangeLinks) { - k = (int) Math.ceil(Math.log(n) / Math.log(2)); - - if (k <= 0) { - k = DEFAULT_K; - } - } else { - k = symphony.numberFixedLongRangeLinks; - } - } - - private void refreshNeighbours(Node node) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - Transport transport = (Transport) node.getProtocol(transportID); - - for (Tuple leftTuple : symphony.leftShortRangeLinks) { - Node leftNode = leftTuple.x; - Message updateNeighbourMsg = new Message(symphony.loggedIntoNetwork, node, MessageType.UPDATE_NEIGHBOURS); - transport.send(node, leftNode, updateNeighbourMsg, pid); - } - - for (Tuple rightTuple : symphony.rightShortRangeLinks) { - Node rightNode = rightTuple.x; - Message updateNeighbourMsg = new Message(symphony.loggedIntoNetwork, node, MessageType.UPDATE_NEIGHBOURS); - transport.send(node, rightNode, updateNeighbourMsg, pid); - } - } - - /** - * Method to update the (connection) status of the node. Perform the update to the "up" so: - * OFFLINE -> ONLINE_AND_ALL_NEIGHBOURS_OFFLINE -> ONLINE - * - * and to the "down" only: ONLINE -> ONLINE_AND_ALL_NEIGHBOURS_OFFLINE - * - * @param node - */ - private void checkBootstrapStatus(Node node) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - - if (symphony.loggedIntoNetwork != BootstrapStatus.OFFLINE) { - - symphony.loggedIntoNetwork = BootstrapStatus.ONLINE_AND_ALL_NEIGHBOURS_OFFLINE; - - // Check if i'm inside the ring and i'm able to do routing - if (!symphony.leftShortRangeLinks.isEmpty() && !symphony.rightShortRangeLinks.isEmpty()) { - - boolean leftOk = false; - for (Tuple leftTuple : symphony.leftShortRangeLinks) { - if (leftTuple.y == BootstrapStatus.ONLINE) { - leftOk = true; - break; - } - } - - if (leftOk) { - for (Tuple rightTuple : symphony.rightShortRangeLinks) { - if (rightTuple.y == BootstrapStatus.ONLINE) { - symphony.loggedIntoNetwork = BootstrapStatus.ONLINE; - break; - } - } - } - } - } - } - - /** - * Remove the possible wrong entries from the lookAhead table - */ - private void fixLookAheadMap(Node node) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - for (Tuple tuple : symphony.leftShortRangeLinks) { - symphony.lookAheadMap.put(tuple.x, null); - } - for (Tuple tuple : symphony.rightShortRangeLinks) { - symphony.lookAheadMap.put(tuple.x, null); - } - } - - /** - * Sent keep-alive messages to verify if the links still online - * - * if enable the lookAhead mode i require the neighbours list from my neighbours (1-lookAhead). - * - * Note: I don't reuse the UPDATE_STATUS messages because i want to mantain separate the - * semantic and have more clear source code - */ - private void keepAlive(Node node) { - - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - Transport transport = (Transport) node.getProtocol(transportID); - - // Send and check for the long range links (both incoming and outgoing) - for (Iterable iterable : new Iterable[]{symphony.longRangeLinksOutgoing, symphony.longRangeLinksIncoming}) { - Iterator longLinksIterator = iterable.iterator(); - while (longLinksIterator.hasNext()) { - Node longLinkNode = longLinksIterator.next(); - Integer value = keepAliveMap.get(longLinkNode); - if (value == null) { - value = 0; - } - - /* - * Verify if i reached the sufficient time of sending and not receiving an answer - * and so i can consider that node as disconnected - */ - if (value >= nTimeout) { - symphony.lookAheadMap.put(longLinkNode, null); // Do it anyway if it's enabled the lookAhead or not - longLinksIterator.remove(); - } else { - keepAliveMap.put(longLinkNode, value + 1); - - Message keepAliveMsg = new Message(symphony.lookAhead, node, MessageType.KEEP_ALIVE); - transport.send(node, longLinkNode, keepAliveMsg, pid); - } - } - } - - // Send and check for the short links - for (Iterable> iterable : new Iterable[]{symphony.rightShortRangeLinks, symphony.leftShortRangeLinks}) { - Iterator> shortLinksIterator = iterable.iterator(); - while (shortLinksIterator.hasNext()) { - Node shortLinkNode = shortLinksIterator.next().x; - Integer value = keepAliveMap.get(shortLinkNode); - if (value == null) { - value = 0; - } - - // the same as above - if (value >= nTimeout) { - shortLinksIterator.remove(); - } else { - keepAliveMap.put(shortLinkNode, value + 1); - - // LookAhead is not to be performed to the short links! - Message keepAliveMsg = new Message(false, node, MessageType.KEEP_ALIVE); - transport.send(node, shortLinkNode, keepAliveMsg, pid); - } - } - } - } - - /** - * Implement the Re-Linking criteria of the Long Range Links. It does the complete refresh. The - * repopulation is done through the 'updateLongRangeLinks' method. - */ - private void reLinkingProtocol(Node node) { - // I do the check only if i succeed at least one time to create a long range link - if (nLink > 0) { - double criterionValue = n / nLink; - - if (!(criterionValue >= relinkingLowerBound && criterionValue <= relinkingUpperBound)) { - - /* - * Not explicitly precised in the paper: if i haven't created a new link i update - * anyway nLink because can happen a special case that i will not be able to create - * links because the reLinkingProtocol procedure is "faster". - */ - nLink = n; - - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - Transport transport = (Transport) node.getProtocol(transportID); - - // Communicate to the all Outgoing Long Range Links that they aren't anymore - for (Node longRangeLinkOutgoingNode : symphony.longRangeLinksOutgoing) { - Message disconnectMsg = new Message(null, node, MessageType.DISCONNECT_LONG_RANGE_LINK); - transport.send(node, longRangeLinkOutgoingNode, disconnectMsg, pid); - } - - symphony.longRangeLinksOutgoing.clear(); - } - } - } - - public int getK() { - return k; - } - - public int getN() { - return n; - } -} diff --git a/contrib/psg/src/example/symphony/SymphonyNodeComparator.java b/contrib/psg/src/example/symphony/SymphonyNodeComparator.java deleted file mode 100644 index e5a17d2b0d..0000000000 --- a/contrib/psg/src/example/symphony/SymphonyNodeComparator.java +++ /dev/null @@ -1,51 +0,0 @@ -package example.symphony; - -import java.util.Comparator; -import java.util.logging.Level; -import java.util.logging.Logger; -import peersim.core.Node; - -/** - * Comparator that measure the relative distance from a target node - * - * @author Andrea Esposito - */ -public class SymphonyNodeComparator implements Comparator { - - private final int symphonyID; - private double target; - - public SymphonyNodeComparator(int symphonyID) { - this.symphonyID = symphonyID; - } - - public SymphonyNodeComparator(int symphonyID, double target) { - this(symphonyID); - this.target = target; - } - - public SymphonyNodeComparator(int symphonyID, Node targetNode) { - this(symphonyID); - SymphonyProtocol symphony = (SymphonyProtocol) targetNode.getProtocol(symphonyID); - this.target = symphony.getIdentifier(); - } - - public int compare(Node o1, Node o2) { - - SymphonyProtocol symphony1 = (SymphonyProtocol) o1.getProtocol(symphonyID); - SymphonyProtocol symphony2 = (SymphonyProtocol) o2.getProtocol(symphonyID); - - Double identifier1 = symphony1.getIdentifier(); - Double identifier2 = symphony2.getIdentifier(); - - Double distance1 = Math.abs(target - identifier1) % 1; - Double distance2 = Math.abs(target - identifier2) % 1; - - identifier1 = Math.min(1.0 - distance1, distance1); - identifier2 = Math.min(1.0 - distance2, distance2); - - Logger.getLogger(SymphonyNodeComparator.class.getName()).log(Level.FINEST, "id1= " + symphony1.getIdentifier() + " target= " + target + " id2= " + symphony2.getIdentifier() + " res= " + identifier1.compareTo(identifier2)); - - return identifier1.compareTo(identifier2); - } -} diff --git a/contrib/psg/src/example/symphony/SymphonyNodeInizializer.java b/contrib/psg/src/example/symphony/SymphonyNodeInizializer.java deleted file mode 100644 index ec5dc685f3..0000000000 --- a/contrib/psg/src/example/symphony/SymphonyNodeInizializer.java +++ /dev/null @@ -1,59 +0,0 @@ -package example.symphony; - -import java.util.logging.Level; -import java.util.logging.Logger; -import peersim.config.Configuration; -import peersim.core.Network; -import peersim.core.Node; -import peersim.dynamics.NodeInitializer; - -/** - * - * @author Andrea Esposito - */ -public class SymphonyNodeInizializer implements NodeInitializer { - - private static final String PAR_NETMANAGER = "symphonynetworkmanager"; - private static final String PAR_SYMPHONY = "symphony"; - private static final String PAR_BOOTNODE = "bootstrapnode"; - private final int networkManagerID; - private final int symphonyID; - private final int indexBootstrapNode; - - public SymphonyNodeInizializer(String prefix) { - - networkManagerID = Configuration.getPid(prefix + "." + PAR_NETMANAGER); - indexBootstrapNode = Configuration.getInt(prefix + "." + PAR_BOOTNODE, 0); - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMPHONY); - } - - @Override - public void initialize(Node node) { - int indexRealBootstrapNode = indexBootstrapNode; - Node realBootstrapNode = Network.get(indexBootstrapNode); - SymphonyNetworkManager symphonyNetworkManager = (SymphonyNetworkManager) node.getProtocol(networkManagerID); - SymphonyProtocol symphony = (SymphonyProtocol) realBootstrapNode.getProtocol(symphonyID); - - boolean joinSent; - do { - try { - while (!symphony.isBootstrapped() || !realBootstrapNode.isUp()) { - indexRealBootstrapNode = (indexRealBootstrapNode + 1) % Network.size(); - realBootstrapNode = Network.get(indexRealBootstrapNode); - symphony = (SymphonyProtocol) realBootstrapNode.getProtocol(symphonyID); - - if (indexRealBootstrapNode == indexBootstrapNode) { - Logger.getLogger(SymphonyNodeInizializer.class.getName()).log(Level.WARNING, "No node ONLINE. Impossible to do the network bootstrap."); - return; - } - } - - symphonyNetworkManager.join(node, realBootstrapNode); - joinSent = true; - } catch (RoutingException ex) { - Logger.getLogger(SymphonyNodeInizializer.class.getName()).log(Level.SEVERE, "Join Issue"); - joinSent = false; - } - } while (!joinSent); - } -} diff --git a/contrib/psg/src/example/symphony/SymphonyProtocol.java b/contrib/psg/src/example/symphony/SymphonyProtocol.java deleted file mode 100644 index 478f81ef77..0000000000 --- a/contrib/psg/src/example/symphony/SymphonyProtocol.java +++ /dev/null @@ -1,530 +0,0 @@ -package example.symphony; - -import java.lang.ref.SoftReference; -import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; - -import example.symphony.Message.MessageType; -import peersim.config.Configuration; -import peersim.core.CommonState; -import peersim.core.Node; -import peersim.edsim.EDProtocol; -import peersim.transport.Transport; - -/** - * - * @author Andrea Esposito - */ -public class SymphonyProtocol implements EDProtocol { - - private static final String PAR_SHORT_LINK = "shortlink"; - private static final String PAR_LONG_LINK = "longlink"; - private static final String PAR_TRANSP = "transport"; - private static final String PAR_ROUTING = "routing"; - private static final String PAR_LOOKAHEAD = "lookahead"; - private static Set allIdentifier = new HashSet(); - private final String prefix; - private static int pid; - private final int transportID; - private final double identifier; - public final int sequentialIdentifier; - private static int sequentialCounter = 0; - public final int numberShortRangeLinksPerSide; - public final boolean bidirectionalRouting; - public final boolean lookAhead; - public final boolean fixedLongRangeLinks; - public final int numberFixedLongRangeLinks; - public LinkedHashSet longRangeLinksOutgoing; - public LinkedHashSet longRangeLinksIncoming; - public LinkedHashSet> rightShortRangeLinks; - public LinkedHashSet> leftShortRangeLinks; - /** - * Array Contract: at position 0 -> OutgoingLongRangeLinks, 1 -> IncomingLongRangeLinks - */ - public final LinkedHashMap[]> lookAheadMap; - private HashMap mapHandler; - /** - * IDs Set to verify if there are cycles - */ - private Set messageHistoryID; - /** - * - * Tuple chronology that contains: - * - * I use SoftReference as a trade off between memory usage and accurancy - */ - private Set>> messageHistory; - private static boolean firstPrintConfig = true; - - public enum BootstrapStatus { - - NEW, OFFLINE, ONLINE_AND_ALL_NEIGHBOURS_OFFLINE, ONLINE - } - public BootstrapStatus loggedIntoNetwork; - - public SymphonyProtocol(String prefix) { - - this.prefix = prefix; - pid = Configuration.lookupPid(prefix.replaceAll("protocol.", "")); - transportID = Configuration.getPid(prefix + "." + PAR_TRANSP); - numberShortRangeLinksPerSide = Configuration.getInt(prefix + "." + PAR_SHORT_LINK, 2) / 2; - bidirectionalRouting = !Configuration.getString(prefix + "." + PAR_ROUTING, "bidirectional").toLowerCase().equals("unidirectional"); - lookAhead = !Configuration.getString(prefix + "." + PAR_LOOKAHEAD, "on").toLowerCase().equals("off"); - numberFixedLongRangeLinks = Configuration.getInt(prefix + "." + PAR_LONG_LINK, -1); - fixedLongRangeLinks = numberFixedLongRangeLinks >= 0; - - longRangeLinksOutgoing = new LinkedHashSet(); - longRangeLinksIncoming = new LinkedHashSet(); - rightShortRangeLinks = new LinkedHashSet>(); - leftShortRangeLinks = new LinkedHashSet>(); - lookAheadMap = new LinkedHashMap[]>(); - - identifier = generateUniqueIdentifier(); - sequentialIdentifier = sequentialCounter++; - - mapHandler = new HashMap(); - - messageHistoryID = new HashSet(); - messageHistory = new LinkedHashSet>>(); - loggedIntoNetwork = BootstrapStatus.NEW; - - printConfig(); - } - - private void printConfig() { - - if (firstPrintConfig) { - firstPrintConfig = false; - System.out.println(SymphonyProtocol.class.getSimpleName() + " Configuration:"); - System.out.println("- Number of short range links per side: " + numberShortRangeLinksPerSide); - System.out.println("- Number of long range links: " + (fixedLongRangeLinks ? numberFixedLongRangeLinks : "log(n)")); - System.out.println("- Routing mode: " + (bidirectionalRouting ? "Bidirectional" : "Unidirectional")); - System.out.println("- LookAhead status: " + (lookAhead ? "ON" : "OFF")); - System.out.println("-------------------------------\n"); - } - } - - /** - * - * Method to identify the next node that has to be contacted. It's going to be used the mode - * that is described into the configuration file - */ - public Node getCandidateForRouting(double identifierToRoute) throws RoutingException { - if (bidirectionalRouting) { - return getCandidateForBidirectionalRoute(identifierToRoute); - } else { - return getCandidateForUnidirectionalRoute(identifierToRoute); - } - } - - /** - * - * Method to individuate the next node that as to be contacted through Unidirectional Routing - * mode - */ - public Node getCandidateForUnidirectionalRoute(double identifierToRoute) throws RoutingException { - - LinkedHashSet allLinks = new LinkedHashSet(); - Node manager = putShortRangeLinksIntoContainerForRouting(allLinks, identifierToRoute); - - if (manager != null) { - return manager; - } - - allLinks.addAll(longRangeLinksOutgoing); - - return findClosestNode(identifierToRoute, allLinks, true); - } - - /** - * Method to individuate the next node that as to be contacted through Bidirectional Routing - * mode - */ - public Node getCandidateForBidirectionalRoute(double identifierToRoute) throws RoutingException { - - LinkedHashSet allLinks = new LinkedHashSet(); - Node manager = putShortRangeLinksIntoContainerForRouting(allLinks, identifierToRoute); - - if (manager != null) { - return manager; - } - - allLinks.addAll(longRangeLinksOutgoing); - allLinks.addAll(longRangeLinksIncoming); - - return findClosestNode(identifierToRoute, allLinks, false); - } - - /** - * @return Null if it is NOT found the manager. Node if it is found. - */ - private Node putShortRangeLinksIntoContainerForRouting(Set container, double identifierToRoute) { - for (Tuple rightTuple : rightShortRangeLinks) { - if (rightTuple.y == BootstrapStatus.ONLINE) { - container.add(rightTuple.x); - } - } - - if (!container.isEmpty()) { - - // Special case: i verify if the neighbour at my right (ONLINE) is the manager - SymphonyNodeComparator comparator = new SymphonyNodeComparator(pid, identifier); - Node nearRightNeighbour = Collections.min(container, comparator); - if (nearRightNeighbour != null) { - SymphonyProtocol symphony = (SymphonyProtocol) nearRightNeighbour.getProtocol(pid); - if (!isLeftNeighbour(identifier, identifierToRoute) && isLeftNeighbour(symphony.getIdentifier(), identifierToRoute)) { - return nearRightNeighbour; - } - } - } - - for (Tuple leftTuple : leftShortRangeLinks) { - if (leftTuple.y == BootstrapStatus.ONLINE) { - container.add(leftTuple.x); - } - } - - return null; - } - - /** - * - * Individuates effectively the next candidate for the routing. Checks if the lookahead is - * activated and in case of affirmative answer it's going to use that information. - * - * @param identifierToRoute Identifier to reach - * @param container Candidate Nodes Container - * @param clockwise true, does unidirectional routing. false, does bidirectional routing. - * @return The nearest node to reach identifierToRoute - * @throws RoutingException Throw in case no candidate is found - */ - public Node findClosestNode(final double identifierToRoute, final Iterable container, final boolean clockwise) throws RoutingException { - Node ret = null; - double min = Double.MAX_VALUE; - - for (Node node : container) { - SymphonyProtocol symphonyNodeContainer = (SymphonyProtocol) node.getProtocol(pid); - double realCandidateIdentifier = symphonyNodeContainer.getIdentifier(); - - Set candidateIdentifierSet = new LinkedHashSet(); - candidateIdentifierSet.add(realCandidateIdentifier); - - boolean lookAheadClockwise = true; - - /* - * - * If lookahead is activated add all the reachable identifiers. No checks are performed - * on the node type (short/long) because at maximum the map return null. - */ - if (lookAhead) { - Set[] lookAheadIdentifierSetArray = lookAheadMap.get(node); - - if (lookAheadIdentifierSetArray != null) { - Set lookAheadIdentifierSet = lookAheadIdentifierSetArray[0]; - - if (lookAheadIdentifierSet == null) { - lookAheadIdentifierSet = new LinkedHashSet(); - } - - /* - * - * If bidirectional routing is going to be performed so i put into account also - * the Incoming Long Range Links of the current neighbour - */ - if (bidirectionalRouting && lookAheadIdentifierSetArray[1] != null) { - lookAheadIdentifierSet.addAll(lookAheadIdentifierSetArray[1]); - lookAheadClockwise = false; - } - - if (!lookAheadIdentifierSet.isEmpty()) { - candidateIdentifierSet.addAll(lookAheadIdentifierSet); - } - } - } - - for (Double candidateIdentifier : candidateIdentifierSet) { - // if it is a my neighbour i use my routing mode instead if it is a looAhead one i use its routing mode - boolean currentClockwise = candidateIdentifier.equals(realCandidateIdentifier) ? clockwise : lookAheadClockwise; - - double distance = Math.abs(candidateIdentifier - identifierToRoute); - distance = Math.min(distance, 1.0 - distance); - - // if clockwise i have to exclude the case: candidateIdentifier - indentifierToRoute - identifier - if (currentClockwise) { - if (isLeftNeighbour(candidateIdentifier, identifierToRoute)) { - - // Special case (0.9 - 0.1) the normal order is not more meanful to decide the side - if (identifierToRoute >= candidateIdentifier) { - distance = identifierToRoute - candidateIdentifier; - } else { - distance = (1.0 - candidateIdentifier) + identifierToRoute; - } - } else { - distance = (1.0 - (candidateIdentifier - identifierToRoute)) % 1; - } - } - - /* - * - * Priority to the node that i'm directly connected and only after i use the - * lookAhead information - */ - if (min >= Math.abs(distance) - && (candidateIdentifier.equals(realCandidateIdentifier) - || ret == null - || min > Math.abs(distance))) { - ret = node; - min = Math.abs(distance); - } - } - } - - if (ret == null) { - throw new RoutingException("Impossible do routing. [Hit: Neighbour links (maybe) not yet online."); - } - - return ret; - } - - /** - * - * @param neighbourNode Neighbour Node - * @return true if the node is a left neighbour (or itself), false if it is a right one - */ - public static boolean isLeftNeighbour(Node rootNode, Node neighbourNode) { - SymphonyProtocol rootSymphony = (SymphonyProtocol) rootNode.getProtocol(pid); - SymphonyProtocol neighbourSymphony = (SymphonyProtocol) neighbourNode.getProtocol(pid); - - return isLeftNeighbour(rootSymphony.getIdentifier(), neighbourSymphony.getIdentifier()); - } - - public static boolean isLeftNeighbour(double rootIdentifier, double neighbourIdentifier) { - - // I calculate putting the hypotesis that i have to translate/"normalize", after i'll check if it was useless - double traslateRootIdentifier = (rootIdentifier + 0.5) % 1; - double traslateNeighbourIdentifier = (neighbourIdentifier + 0.5) % 1; - double distance = traslateNeighbourIdentifier - traslateRootIdentifier; - - // I verify if the neighbourIdentifier is over half ring, if yes i don't need to do the translation/"normalization" - if ((neighbourIdentifier + 0.5) != traslateNeighbourIdentifier) { - distance = neighbourIdentifier - rootIdentifier; - } - - return distance >= 0 && distance <= 0.5; - } - - public void route(Node src, double key, Handler handler) throws RoutingException { - - mapHandler.put(key, handler); - - Message msg = new Message(key, src, MessageType.ROUTE); - - Node targetNode = src; - - if (!isManagerOf(key)) { - targetNode = getCandidateForRouting(key); - Transport transport = (Transport) src.getProtocol(transportID); - transport.send(src, targetNode, msg, pid); - } - - // Insert the message into the chronology - Tuple historyTuple = new Tuple(); - try { - historyTuple.x = msg; - historyTuple.y = (Message) msg.clone(); - historyTuple.y.setCurrentHop(targetNode); - } catch (CloneNotSupportedException ex) { - Logger.getLogger(SymphonyProtocol.class.getName()).log(Level.SEVERE, "Impossible to clonate the message!"); - historyTuple.x = null; - historyTuple.y = msg; - msg.setCurrentHop(targetNode); - } - messageHistory.add(new SoftReference>(historyTuple)); - messageHistoryID.add(msg.getID()); - - /* - * - * If i am the manager (brutally through the reference), i don't do the loopback routing but - * i soddisfy immediately the request - */ - if (targetNode == src) { - - // Uppdate the chronology - historyTuple.y = new Message(key, targetNode, MessageType.ROUTE_RESPONSE); - - Tuple tuple = new Tuple(src, key); - mapHandler.remove(key); - handler.handle(this, tuple); - } - } - - public void processEvent(Node node, int pid, Object event) { - Message msg = (Message) event; - msg.incrementHop(); // I increment the message Hop - - Tuple historyTuple = new Tuple(); - try { - // I clone the message such a way to store into the chronology the hop sender's information - historyTuple.x = (Message) msg.clone(); - } catch (CloneNotSupportedException ex) { - Logger.getLogger(SymphonyProtocol.class.getName()).log(Level.SEVERE, "Impossible to clonate the message!"); - historyTuple.x = msg; - } - - messageHistory.add(new SoftReference>(historyTuple)); - - Double key; - Transport transport; - Handler handler; - - // Individuate cycles - if (messageHistoryID.contains(msg.getID())) { - Message responseMsg = new Message(msg, node, MessageType.ROUTE_FAIL); - - historyTuple.y = responseMsg; - - transport = (Transport) node.getProtocol(transportID); - transport.send(node, msg.getSourceNode(), responseMsg, pid); - return; - } - - /* - * If i'm arrived till here means that i'm not into a cycle --> i insert the message ID into - * the chronology - */ - messageHistoryID.add(msg.getID()); - - switch (msg.getType()) { - case ROUTE: - key = (Double) msg.getBody(); - Logger.getLogger(SymphonyProtocol.class.getName()).log(Level.FINEST, key + " " + identifier); - if (isManagerOf(key)) { - transport = (Transport) msg.getSourceNode().getProtocol(transportID); - Message responseMsg = new Message(new Tuple(node, key), node, MessageType.ROUTE_RESPONSE); - historyTuple.y = responseMsg; - transport.send(node, msg.getSourceNode(), responseMsg, pid); - } else { - try { - Node targetNode = getCandidateForRouting(key); - - try { - // I clone the message such a way to store the info (into the chronology) of the hop receiver - historyTuple.y = (Message) msg.clone(); - historyTuple.y.setCurrentHop(targetNode); - } catch (CloneNotSupportedException ex) { - Logger.getLogger(SymphonyProtocol.class.getName()).log(Level.SEVERE, "Impossible to clonate the message!"); - historyTuple.y = msg; - msg.setCurrentHop(targetNode); - } - - transport = (Transport) node.getProtocol(transportID); - transport.send(node, targetNode, msg, pid); - } catch (RoutingException ex) { - /* - * - * I send the same message to myself (it is going to queue into the event - * queue and in this way i "earn" time (postpone) and i hope that the - * network will be ok in the meanwhile) - */ - historyTuple.y = msg; - msg.setCurrentHop(node); - transport = (Transport) node.getProtocol(transportID); - transport.send(node, node, msg, pid); - } - } - break; - case ROUTE_RESPONSE: - Tuple tuple = (Tuple) msg.getBody(); - key = tuple.y; - handler = mapHandler.get(key); - mapHandler.remove(key); - handler.handle(this, tuple); - break; - case ROUTE_FAIL: - Message requestMsg = (Message) msg.getBody(); - key = (Double) requestMsg.getBody(); - handler = mapHandler.get(key); - mapHandler.remove(key); - handler.handle(this, null); - break; - } - } - - public boolean isManagerOf(double key) { - - if (key == identifier) { - return true; - } - - SymphonyNodeComparator comparator = new SymphonyNodeComparator(pid, identifier); - AdapterSymphonyNodeComparator adapterComparator = new AdapterSymphonyNodeComparator(comparator); - - Collection> leftShortRangeLinksCloned = (Collection>) leftShortRangeLinks.clone(); - Node targetNode = null; - - while (targetNode == null && !leftShortRangeLinksCloned.isEmpty()) { - Tuple nearTuple = Collections.min(leftShortRangeLinksCloned, adapterComparator); - if (nearTuple.y == BootstrapStatus.ONLINE) { - targetNode = nearTuple.x; - } else { - leftShortRangeLinksCloned.remove(nearTuple); - } - } - - // SPECIAL CASE: NO LEFT NEIGHBOURS. I became the Manager. - if (targetNode == null) { - return true; - } - - SymphonyProtocol symphony = (SymphonyProtocol) targetNode.getProtocol(pid); - // Check if it's the situation: right neighbour - key - me. So if i'm the manager or not. - boolean ret = isLeftNeighbour(identifier, key) && (!isLeftNeighbour(symphony.getIdentifier(), key) && symphony.getIdentifier() != key); - - return ret; - } - - public double getIdentifier() { - return identifier; - } - - public Tuple[] getHistoryMessage() { - SoftReference>[] array = messageHistory.toArray(new SoftReference[0]); - LinkedList> list = new LinkedList>(); - for (SoftReference> reference : array) { - Tuple tuple = reference.get(); - if (tuple != null) { - list.add(tuple); - } - } - return list.toArray(new Tuple[0]); - } - - public void clearHistoryMessage() { - messageHistory.clear(); - } - - private double generateUniqueIdentifier() { - boolean duplicated = true; - Double id = null; - - while (duplicated) { - id = CommonState.r.nextDouble(); - duplicated = allIdentifier.contains(id); - } - - allIdentifier.add(id); - - return id; - } - - @Override - public Object clone() { - SymphonyProtocol dolly = new SymphonyProtocol(prefix); - return dolly; - } - - public boolean isBootstrapped() { - return loggedIntoNetwork == BootstrapStatus.ONLINE; - } -} diff --git a/contrib/psg/src/example/symphony/SymphonyStatistics.java b/contrib/psg/src/example/symphony/SymphonyStatistics.java deleted file mode 100644 index 4e97219654..0000000000 --- a/contrib/psg/src/example/symphony/SymphonyStatistics.java +++ /dev/null @@ -1,77 +0,0 @@ -package example.symphony; - -import peersim.config.Configuration; -import peersim.core.Control; -import peersim.core.Network; -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class SymphonyStatistics implements Control { - - private static final String PAR_SYMPHONY = "symphony"; - private final int symphonyID; - private long totalMsg = 0; - private long numRouteResposeMsg = 0; - private long numRouteMsg = 0; - private long numRouteFailMsg = 0; - private long numRouteFoundManagerMsg = 0; - private double mediaHopRouteResponseMsg = 0.0; - - public SymphonyStatistics(String prefix) { - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMPHONY); - } - - public boolean execute() { - - AdapterIterableNetwork itNetwork = new AdapterIterableNetwork(); - for (Node node : itNetwork) { - SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID); - Tuple[] tupleMessages = symphony.getHistoryMessage(); - totalMsg += tupleMessages.length; - - for (Tuple tupleMessage : tupleMessages) { - - Message message = tupleMessage.x; - - if (message != null) { - switch (message.getType()) { - case ROUTE: - numRouteMsg++; - if (tupleMessage.y != null && tupleMessage.y.getType() == Message.MessageType.ROUTE_RESPONSE) { - numRouteFoundManagerMsg++; - mediaHopRouteResponseMsg = ((mediaHopRouteResponseMsg * (numRouteFoundManagerMsg - 1)) + message.getHop()) / (double) numRouteFoundManagerMsg; - } - break; - case ROUTE_FAIL: - numRouteFailMsg++; - break; - case ROUTE_RESPONSE: - numRouteResposeMsg++; - break; - } - } - } - - symphony.clearHistoryMessage(); - } - - printStatistics(); - - return false; - } - - private void printStatistics() { - System.out.println("### Statistics ###"); - System.out.println("- Total Messages: " + totalMsg); - System.out.println("- Total Route Messages: " + numRouteMsg); - System.out.println("- Found Manager Route Message: " + numRouteFoundManagerMsg); - System.out.println("- Response Message: " + numRouteResposeMsg); - System.out.println("- Fail Message: " + numRouteFailMsg); - System.out.println(); - System.out.println("Average Hop:" + mediaHopRouteResponseMsg + " Expected value (k = log n): " + (Math.log(Network.size()) / Math.log(2))); - System.out.println("### END ###\n"); - } -} diff --git a/contrib/psg/src/example/symphony/Tuple.java b/contrib/psg/src/example/symphony/Tuple.java deleted file mode 100644 index ed82b64a1a..0000000000 --- a/contrib/psg/src/example/symphony/Tuple.java +++ /dev/null @@ -1,45 +0,0 @@ -package example.symphony; - -/** - * - * @author Andrea Esposito - */ -public class Tuple { - - public X x; - public Y y; - - public Tuple() { - } - - public Tuple(X x, Y y) { - this.x = x; - this.y = y; - } - - @Override - public boolean equals(Object obj) { - - if (obj instanceof Tuple) { - Tuple tuple = (Tuple) obj; - - // (x != null && tuple.x != null) ==> (x==tuple.x || x.equals(tuple.x)) - // x == null <==> tuple.x == null - - boolean equalsX = (x == null && tuple.x == null) || ((x != null && tuple.x != null) && (x == tuple.x || x.equals(tuple.x))); - boolean equalsY = (y == null && tuple.y == null) || ((y != null && tuple.y != null) && (y == tuple.y || y.equals(tuple.y))); - - return equalsX && equalsY; - } - - return false; - } - - @Override - public int hashCode() { - int hash = 5; - hash = 89 * hash + (this.x != null ? this.x.hashCode() : 0); - hash = 89 * hash + (this.y != null ? this.y.hashCode() : 0); - return hash; - } -} diff --git a/contrib/psg/src/example/symphony/test/NetworkEstimationTest.java b/contrib/psg/src/example/symphony/test/NetworkEstimationTest.java deleted file mode 100644 index 1d0d945307..0000000000 --- a/contrib/psg/src/example/symphony/test/NetworkEstimationTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package example.symphony.test; - -import example.symphony.AdapterIterableNetwork; -import example.symphony.SymphonyNetworkManager; -import example.symphony.SymphonyProtocol; -import peersim.config.Configuration; -import peersim.core.Control; -import peersim.core.Node; - -/** - * - * @author Andrea Esposito - */ -public class NetworkEstimationTest implements Control { - - private static final String PAR_NETMANAGER = "symphonynetworkmanager"; - private static final String PAR_SYMPHONY = "symphony"; - private final int symphonyID; - private final int networkManagerID; - - public NetworkEstimationTest(String prefix) { - - networkManagerID = Configuration.getPid(prefix + "." + PAR_NETMANAGER); - symphonyID = Configuration.getPid(prefix + "." + PAR_SYMPHONY); - } - - public boolean execute() { - - AdapterIterableNetwork it = new AdapterIterableNetwork(); - int max = Integer.MIN_VALUE; - int min = Integer.MAX_VALUE; - int sum = 0; - int total = 0; - for (Node node : it) { - if (node.isUp() && ((SymphonyProtocol) node.getProtocol(symphonyID)).isBootstrapped()) { - SymphonyNetworkManager networkManager = (SymphonyNetworkManager) node.getProtocol(networkManagerID); - int n = networkManager.getN(); - min = n < min ? n : min; - max = n > max ? n : max; - sum += n; - total++; - } - } - - System.out.println("Real Dimension: " + (Math.log(total) / Math.log(2))); - System.out.println("Average Estimated Dimension: " + (total == 0 ? "No Node online" : (Math.log((sum / total)) / Math.log(2)))); - System.out.println("MAX: " + Math.log(max) / Math.log(2)); - System.out.println("MIN: " + Math.log(min) / Math.log(2)); - - return false; - } -} diff --git a/contrib/psg/src/peersim/Simulator.java b/contrib/psg/src/peersim/Simulator.java deleted file mode 100644 index 97c7965150..0000000000 --- a/contrib/psg/src/peersim/Simulator.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim; - -import psgsim.PSGSimulator; - -import java.io.*; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.simgrid.msg.HostNotFoundException; -import org.simgrid.msg.NativeException; - -import peersim.cdsim.*; -import peersim.config.*; -import peersim.core.*; -import peersim.edsim.*; - -/** - * This is the main entry point to peersim. This class loads configuration and - * detects the simulation type. According to this, it invokes the appropriate - * simulator. The known simulators at this moment, along with the way to detect - * them are the following: - *
    - *
  • {@link CDSimulator}: if {@link CDSimulator#isConfigurationCycleDriven} - * returns true
  • - *
  • {@link EDSimulator}: if {@link EDSimulator#isConfigurationEventDriven} - * returns true
  • - *
- * This list represents the order in which these alternatives are checked. That - * is, if more than one return true, then the first will be taken. Note that - * this class checks only for these clues and does not check if the - * configuration is consistent or valid. - * - * @see #main - */ -public class Simulator { - - // ========================== static constants ========================== - // ====================================================================== - public static int nbreR = 0; - /** {@link CDSimulator} */ - public static final int CDSIM = 0; - - /** {@link EDSimulator} */ - public static final int EDSIM = 1; - - /** {@link psgsim.PSGSimulator} */ - public static final int PSGSIM = 2; - - /** Unknown simulator */ - public static final int UNKNOWN = -1; - - /** the class names of simulators used */ - protected static final String[] simName = { "peersim.cdsim.CDSimulator", - "peersim.edsim.EDSimulator", "psgsim.PSGSimulator" }; - - /** - * Parameter representing the number of times the experiment is run. - * Defaults to 1. - * - * @config - */ - public static final String PAR_EXPS = "simulation.experiments"; - - /** - * If present, this parameter activates the redirection of the standard - * output to a given PrintStream. This comes useful for processing the - * output of the simulation from within the simulator. - * - * @config - */ - public static final String PAR_REDIRECT = "simulation.stdout"; - - // ==================== static fields =================================== - // ====================================================================== - - /** */ - private static int simID = UNKNOWN; - - // ========================== methods =================================== - // ====================================================================== - - /** - * Returns the numeric id of the simulator to invoke. At the moment this can - * be {@link #CDSIM}, {@link #EDSIM} or {@link #UNKNOWN}. - */ - public static int getSimID() { - - if (simID == UNKNOWN) { - if (CDSimulator.isConfigurationCycleDriven()) { - simID = CDSIM; - } else if (EDSimulator.isConfigurationEventDriven()) { - simID = EDSIM; - } else - simID = PSGSIM; - - } - return simID; - } - - // ---------------------------------------------------------------------- - - /** - * Loads the configuration and executes the experiments. The number of - * independent experiments is given by config parameter {@value #PAR_EXPS}. - * In all experiments the configuration is the same, only the random seed is - * not re-initialized between experiments. - *

- * Loading the configuration is currently done with the help of constructing - * an instance of {@link ParsedProperties} using the constructor - * {@link ParsedProperties#ParsedProperties(String[])}. The parameter - * args is simply passed to this class. This class is then used - * to initialize the configuration. - *

- * After loading the configuration, the experiments are run by invoking the - * appropriate engine, which is identified as follows: - *

    - *
  • {@link CDSimulator}: if - * {@link CDSimulator#isConfigurationCycleDriven} returns true
  • - *
  • {@link EDSimulator}: if - * {@link EDSimulator#isConfigurationEventDriven} returns true
  • - *
- *

- * This list represents the order in which these alternatives are checked. - * That is, if more than one return true, then the first will be taken. Note - * that this class checks only for these clues and does not check if the - * configuration is consistent or valid. - * - * @param args - * passed on to - * {@link ParsedProperties#ParsedProperties(String[])} - * @throws InterruptedException - * @throws HostNotFoundException - * @see ParsedProperties - * @see Configuration - * @see CDSimulator - * @see EDSimulator - */ - public static void main(String[] args) throws InterruptedException, - HostNotFoundException { - long time = System.currentTimeMillis(); - long start; - System.err.println("Simulator: loading configuration"); - Configuration.setConfig(new ParsedProperties(args)); - PrintStream newout = (PrintStream) Configuration.getInstance( - PAR_REDIRECT, System.out); - if (newout != System.out) - System.setOut(newout); - - int exps = Configuration.getInt(PAR_EXPS, 1); - final int SIMID = getSimID(); - if (SIMID == UNKNOWN) { - System.err - .println("Simulator: unable to determine simulation engine type"); - return; - } - - try { - - for (int k = 0; k < exps; ++k) { - if (k > 0) { - long seed = CommonState.r.nextLong(); - CommonState.initializeRandom(seed); - } - System.err.print("Simulator: starting experiment " + k); - System.err.println(" invoking " + simName[SIMID]); - System.err.println("Random seed: " - + CommonState.r.getLastSeed()); - // XXX could be done through reflection, but - // this is easier to read. - - switch (SIMID) { - case CDSIM: - CDSimulator.nextExperiment(); - break; - case EDSIM: - log("ps"); - start = System.currentTimeMillis(); - EDSimulator.nextExperiment(); - System.err.print("Duration of Simulation in ps:" - + (System.currentTimeMillis() - start) + " ms\n"); - break; - case PSGSIM: - try { - log("psg"); - start = System.currentTimeMillis(); - PSGSimulator.main(); - System.err.print("Duration of Simulation in psg:" - + (System.currentTimeMillis() - start) - + " ms\n"); - } catch (NativeException e) { - System.err - .println("***********Native exception***************"); - e.printStackTrace(); - } - break; - } - } - - } catch (MissingParameterException e) { - System.err.println(e + ""); - System.exit(1); - } catch (IllegalParameterException e) { - System.err.println(e + ""); - System.exit(1); - } - - // undocumented testing capabilities - if (Configuration.contains("__t")) - System.out.println(System.currentTimeMillis() - time); - if (Configuration.contains("__x")) - Network.test(); - - } - - /** - * - * @param sim - */ - public static void log(String sim) { - String propName = "OutputName"; - - /** le nom de l'OS */ - final String OS_NAME = System.getProperty("os.name"); - File file = null; - String prot = Configuration.getString(propName, "null"); - if (prot.contentEquals("null")) { - System.err.println("OutputName parameter not defined"); - } else { - if ("Linux".equals(OS_NAME) || "Mac".equals(OS_NAME)) { - if (!new File("outputs" + prot).exists()) { - new File("outputs/" + prot).mkdirs(); - } - String path = "outputs/" + prot + "/"; - file = new File(path + sim + ".txt"); - } else { - if (!new File("outputs" + prot).exists()) - new File("outputs\\" + prot).mkdirs(); - String path = "outputs\\" + prot + "\\"; - file = new File(path + sim + ".txt"); - } - try { - PrintStream printStream = new PrintStream(file); - System.setOut(printStream); - // System.setErr(printStream); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - } - - } - -} diff --git a/contrib/psg/src/peersim/cdsim/CDProtocol.java b/contrib/psg/src/peersim/cdsim/CDProtocol.java deleted file mode 100644 index c0d2f0de66..0000000000 --- a/contrib/psg/src/peersim/cdsim/CDProtocol.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.cdsim; - -import peersim.core.Protocol; -import peersim.core.Node; - -/** -* Defines cycle driven protocols, that is, protocols that have a periodic -* activity in regular time intervals. -*/ -public interface CDProtocol extends Protocol -{ - -/** - * A protocol which is defined by performing an algorithm in more or less - * regular periodic intervals. - * This method is called by the simulator engine once in each cycle with - * the appropriate parameters. - * - * @param node - * the node on which this component is run - * @param protocolID - * the id of this protocol in the protocol array - */ -public void nextCycle(Node node, int protocolID); - -} diff --git a/contrib/psg/src/peersim/cdsim/CDSimulator.java b/contrib/psg/src/peersim/cdsim/CDSimulator.java deleted file mode 100644 index f4875949ee..0000000000 --- a/contrib/psg/src/peersim/cdsim/CDSimulator.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.cdsim; - -import java.util.*; -import peersim.config.*; -import peersim.core.*; - -/** - * This is the cycle driven simulation engine. It is a fully static - * singleton class. For a cycle driven simulation the configuration can - * describe a set of {@link Protocol}s, and their ordering, a set of - * {@link Control}s and their ordering and a set of initializers and their - * ordering. See parameters {@value #PAR_INIT}, {@value #PAR_CTRL}. Out - * of the set of protocols, this engine only executes the ones that - * implement the {@link CDProtocol} interface. - *

- * One experiment run by {@link #nextExperiment} works as follows. First - * the initializers are run in the specified order, then the following is - * iterated {@value #PAR_CYCLES} times: If {@value #PAR_NOMAIN} is - * specified, then simply the controls specified in the configuration are - * run in the specified order. If {@value #PAR_NOMAIN} is not specified, - * then the controls in the configuration are run in the specified order, - * followed by the execution of {@link FullNextCycle}. - *

- * All components (controls and protocols) can have configuration - * parameters that control their scheduling (see {@link Scheduler}). This - * way they can skip cycles, start from a specified cycle, etc. As a - * special case, components can be scheduled to run after the last cycle. - * That is, each experiment is finished by running the controls that are - * scheduled after the last cycle. - *

- * Finally, any control can interrupt an experiment at any time it is - * executed by returning true in method {@link Control#execute}. However, - * the controls scheduled to run after the last cycle are still executed - * completely, irrespective of their return value and even if the - * experiment was interrupted. - * @see Configuration - */ -public class CDSimulator -{ - -// ============== fields =============================================== -// ===================================================================== - -/** - * Parameter representing the maximum number of cycles to be performed - * @config - */ -public static final String PAR_CYCLES = "simulation.cycles"; - -/** - * This option is only for experts. It switches off the main cycle that - * calls the cycle driven protocols. When you switch this off, you need to - * control the execution of the protocols by configuring controls that do - * the job (e.g., {@link FullNextCycle}, {@link NextCycle}). It's there for - * people who want maximal flexibility for their hacks. - * @config - */ -private static final String PAR_NOMAIN = "simulation.nodefaultcycle"; - -/** - * This is the prefix for initializers. These have to be of type - * {@link Control}. They are run at the beginning of each experiment, in - * the order specified by the configuration. - * @see Configuration - * @config - */ -private static final String PAR_INIT = "init"; - -/** - * This is the prefix for controls. These have to be of type - * {@link Control}. They are run before each cycle, in the order specified - * by the configuration. - * @see Configuration - * @config - */ -private static final String PAR_CTRL = "control"; - -// -------------------------------------------------------------------- - -/** The maximum number of cycles to be performed */ -private static int cycles; - -/** holds the modifiers of this simulation */ -private static Control[] controls = null; - -/** Holds the control schedulers of this simulation */ -private static Scheduler[] ctrlSchedules = null; - -// =============== initialization ====================================== -// ===================================================================== - -/** to prevent construction */ -private CDSimulator() -{ -} - -// =============== private methods ===================================== -// ===================================================================== - -/** - * Load and run initializers. - */ -private static void runInitializers() -{ - - Object[] inits = Configuration.getInstanceArray(PAR_INIT); - String names[] = Configuration.getNames(PAR_INIT); - - for (int i = 0; i < inits.length; ++i) { - System.err.println("- Running initializer " + names[i] + ": " - + inits[i].getClass()); - ((Control) inits[i]).execute(); - } -} - -// -------------------------------------------------------------------- - -private static String[] loadControls() -{ - - boolean nomaincycle = Configuration.contains(PAR_NOMAIN); - String[] names = Configuration.getNames(PAR_CTRL); - if (nomaincycle) { - controls = new Control[names.length]; - ctrlSchedules = new Scheduler[names.length]; - } else { - // provide for an extra control that handles the main cycle - controls = new Control[names.length + 1]; - ctrlSchedules = new Scheduler[names.length + 1]; - // calling with a prefix that cannot exist - controls[names.length] = new FullNextCycle(" "); - ctrlSchedules[names.length] = new Scheduler(" "); - } - for (int i = 0; i < names.length; ++i) { - controls[i] = (Control) Configuration.getInstance(names[i]); - ctrlSchedules[i] = new Scheduler(names[i]); - } - System.err.println("CDSimulator: loaded controls " + Arrays.asList(names)); - return names; -} - -// --------------------------------------------------------------------- - -/** - * This method is used to check whether the current configuration can be - * used for cycle-driven simulations. It checks for the existence of - * configuration parameter {@value #PAR_CYCLES}. - */ -public static final boolean isConfigurationCycleDriven() -{ - return Configuration.contains(PAR_CYCLES); -} - -// --------------------------------------------------------------------- - -/** - * Runs an experiment, resetting everything except the random seed. - */ -public static final void nextExperiment() -{ - - // Reading parameter - cycles = Configuration.getInt(PAR_CYCLES); - if (CommonState.getEndTime() < 0) // not initialized yet - CDState.setEndTime(cycles); - - // initialization - CDState.setCycle(0); - CDState.setPhase(CDState.PHASE_UNKNOWN); - System.err.println("CDSimulator: resetting"); - controls = null; - ctrlSchedules = null; - Network.reset(); - System.err.println("CDSimulator: running initializers"); - runInitializers(); - - // main cycle - loadControls(); - - System.err.println("CDSimulator: starting simulation"); - for (int i = 0; i < cycles; ++i) { - CDState.setCycle(i); - - boolean stop = false; - for (int j = 0; j < controls.length; ++j) { - if (ctrlSchedules[j].active(i)) - stop = stop || controls[j].execute(); - } - if (stop) - break; - //System.err.println("CDSimulator: cycle " + i + " DONE"); - } - - CDState.setPhase(CDState.POST_SIMULATION); - - // analysis after the simulation - for (int j = 0; j < controls.length; ++j) { - if (ctrlSchedules[j].fin) - controls[j].execute(); - } -} - -} diff --git a/contrib/psg/src/peersim/cdsim/CDState.java b/contrib/psg/src/peersim/cdsim/CDState.java deleted file mode 100644 index ef52f78682..0000000000 --- a/contrib/psg/src/peersim/cdsim/CDState.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.cdsim; - -import peersim.core.CommonState; - - -/** - * This is the common state of a cycle driven simulation that all objects see. - * It contains additional information, specific to the cycle driven model, - * in addition to the info in {@link peersim.core.CommonState}. - */ -public class CDState extends CommonState { - - -// ======================= fields ================================== -// ================================================================= - -/** - * Current time within the current cycle. - * Note that {@link #cycle} gives the cycle id to which this value is relative. - */ -private static int ctime = -1; - -/** - * Current cycle in the simulation. It makes sense only in the case of a - * cycle based simulator, that is, cycle based simulators will maintain this - * value, others will not. It still makes sense to keep it separate from - * {@link #time} because it is an int, while time is a long. - */ -private static int cycle = -1; - - -// ======================== initialization ========================= -// ================================================================= - - -static {} - -/** to avoid construction */ -private CDState() {} - -// ======================= methods ================================= -// ================================================================= - - -/** -* Returns true if and only if there is a cycle driven simulation going on. -*/ -public static boolean isCD() { return cycle >= 0; } - -//----------------------------------------------------------------- - -/** - * Returns the current cycle. - * Note that {@link #getTime()} returns the same value. - * @throws UnsupportedOperationException if no cycle-driven state is available - */ -public static int getCycle() -{ - if( cycle >= 0 ) return cycle; - else throw new UnsupportedOperationException( - "Cycle driven state accessed when "+ - "no cycle state information is available."); -} - -//----------------------------------------------------------------- - -/** - * Sets current cycle. Resets also cycle time to 0. It also calls - * {@link #setTime(long)} with the given parameter, to make sure - * {@link #getTime()} is indeed independent of the simulation model. - */ -public static void setCycle(int t) -{ - cycle = t; - ctime = 0; - setTime(t); -} - -//----------------------------------------------------------------- - -/** - * Returns current cycle as an Integer object. - * @throws UnsupportedOperationException if no cycle-driven state is available - */ -public static Integer getCycleObj() -{ - if( cycle >= 0 ) return Integer.valueOf(cycle); - else throw new UnsupportedOperationException( - "Cycle driven state accessed when "+ - "no cycle state information is available."); -} - -//----------------------------------------------------------------- - -/** - * Returns the current time within the current cycle. - * Note that the time returned by {@link #getCycle} is the cycle id - * in this case. In other words, it returns the number of nodes that have - * already been visited in a given cycle. - * @throws UnsupportedOperationException if no cycle-driven state is available - */ -public static int getCycleT() -{ - if( ctime >= 0 ) return ctime; - else throw new UnsupportedOperationException( - "Cycle driven state accessed when "+ - "no cycle state information is available."); -} - -// ----------------------------------------------------------------- - -public static void setCycleT(int t) -{ - ctime = t; -} -} - - diff --git a/contrib/psg/src/peersim/cdsim/DaemonProtocol.java b/contrib/psg/src/peersim/cdsim/DaemonProtocol.java deleted file mode 100644 index 73f9a4eac4..0000000000 --- a/contrib/psg/src/peersim/cdsim/DaemonProtocol.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.cdsim; - -import java.util.Arrays; -import peersim.config.Configuration; -import peersim.core.Node; -import peersim.core.Control; - -/** -* A protocol that is not really a protocol, but a trick to carry out all -* kinds of tasks during the simulation. Many users will probably not need it, -* but it is a nice way to e.g. run controls at any time, not only between cycles. -*/ -public class DaemonProtocol implements CDProtocol { - - -// ========================= fields ================================= -// ================================================================== - - -/** -* This is the prefix for network dynamism managers. -* @config -*/ -private static final String PAR_CTRL = "control"; - -/** -* The controls will be run according to this frequency. -* It is interpreted within a cycle, in terms of cycle time -* ({@link CDState#getCycleT}). The first cycletime is 0. -* Defaults to 1. -* @config -*/ -private static final String PAR_STEP = "cstep"; - -// -------------------------------------------------------------------- - -private static Control[] controls=null; - -private static int step; - -// ========================= initialization ========================= -// ================================================================== - - -public DaemonProtocol(String s) -{ - step = Configuration.getInt(s+"."+PAR_STEP,1); - - String[] names = Configuration.getNames(s+"."+PAR_CTRL); - controls = new Control[names.length]; - for(int i=0; i -* The goal is to provide a mechanism to test a configuration file, -* without having to perform the actual simulations (that could be -* time-consuming) and without necessarily blocking after the first -* error encountered. It may be useful, for example, when a major -* refactoring of your code requires a thorough check on all your -* configuration files. -*

-* Loading the configuration is currently done with the help of -* constructing an instance of {@link ParsedProperties} using the -* constructor {@link ParsedProperties#ParsedProperties(String[])}, -* in the same way as the normal simulator. -*

-* After loading the configuration, the collection of nodes forming a -* Network is instantiated, together with all protocols forming a -* node. Initialization controls are executed, and then the simulation -* stops. -*

-* For each error encountered, a message is printed ons standard error, -* and the initialization keeps going without interruption. If multiple -* errors are present, an error message for each of them is printed. -* Apart from errors, default choices are also printed as warnings, to -* allow developers to spot subtle configuration errors such as missing -* parameters that defaults to standard values. -* -* @param args passed on to -* {@link ParsedProperties#ParsedProperties(String[])} -*/ -public static void main(String[] args) - throws Exception -{ - System.setErr(new NullPrintStream()); - Properties prop = new ParsedProperties(args); - Configuration.setConfig( prop, true ); - parseRanges(prop); - - final int SIMID = getSimID(); - if( SIMID == UNKNOWN ) - { - System.err.println( - "Simulator: unable to identify configuration, exiting."); - return; - } - - try { - - // XXX could be done through reflection, but - // this is easier to read. - switch(SIMID) - { - case CDSIM: - // Set cycles to 0, so no simulation is ever performed. - prop.setProperty(CDSimulator.PAR_CYCLES, "0"); - CDSimulator.nextExperiment(); - break; - case EDSIM: - // Set endtime to 0, so no simulation is ever performed. - prop.setProperty(EDSimulator.PAR_ENDTIME, "0"); - EDSimulator.nextExperiment(); - break; - } - - } catch (MissingParameterException e) { - System.out.println(e.getMessage()); - System.exit(1); - } catch (IllegalParameterException e) { - System.out.println(e.getMessage()); - System.exit(1); - } -} - -/** - * Parses a collection of range specifications, identifies the set - * of parameters that will change during the simulation and - * instantiates them with the first value of their ranges. - */ -private static void parseRanges(Properties prop) -{ - // Get ranges - String[] ranges = Configuration.getNames(PAR_RANGE); - - for (int i = 0; i < ranges.length; i++) { - String[] array = Configuration.getString(ranges[i]).split(";"); - if (array.length != 2) { - throw new IllegalParameterException(ranges[i], - " should be formatted as ;"); - } - String[] values = StringListParser.parseList(array[1]); - prop.setProperty(array[0], values[0]); - } -} - -} diff --git a/contrib/psg/src/peersim/config/ClassFinder.java b/contrib/psg/src/peersim/config/ClassFinder.java deleted file mode 100644 index b7cab6b326..0000000000 --- a/contrib/psg/src/peersim/config/ClassFinder.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -import java.io.*; -import java.util.*; -import java.util.zip.*; - -/** - * Provides static methods to obtain the package-qualified class name - * of a class, given just the non-qualified name, and to obtain - * the non-qualified name, given the package-qualified class name. - * - * Inspired from some code written by David Postill (david@postill.org.uk) - * (found in http://groups.google.com). - * - * - * @author Alberto Montresor - * @version $Revision: 1.9 $ - */ -class ClassFinder -{ - -//-------------------------------------------------------------------------- -//Fields and initialization -//-------------------------------------------------------------------------- - - -/** Local map containing the associations */ -private static Map map = new TreeMap(); - -/** The number of directories that have been touched by the search. -This does not include directories in jar files. */ -private static int visitedDirs = 0; - -private static final int maxDirs; - -static { - - maxDirs = 10000; - - try { - findClasses(map); - } catch (IOException e) { - e.printStackTrace(); - } - - if(visitedDirs >= maxDirs ) - { - System.err.println("Configuration: some directories in your "+ - "classpath probably contain filesystem\nConfiguration: "+ - "loops because the number of visited directories "+ - "reached "+maxDirs+".\nConfiguration: This means automatic "+ - "class lookup might fail and you might have\nConfiguration: "+ - "to fully qualify class names in the configuration."); - } -} - - -//-------------------------------------------------------------------------- -//Public static methods -//-------------------------------------------------------------------------- - -/** - * Returns the non-qualified name of a class, removing all the package - * information. - */ -public static String getShortName(String className) { - - int index = className.lastIndexOf('.'); - if (index < 0) { - return className; - } else { - return className.substring(index+1); - } -} - -/** - * Returns the package-qualified name associated to the specified - * non-qualified name, if exists. Otherwise it returns null. - * - * Only classes reachable from the classpath defined by the - * "java.class.path" property are considered. - * Jar files and directories are both parsed. - * If multiple classes with the same name but different - * fully-qualified names are present, a comma-separated list - * of fully-qualified class names is returned. - * - * @param name the non-qualified name of the class to be searched - * @return the qualified name, if exists. - */ -public static String getQualifiedName(String name) -{ - return map.get(name); -} - -//-------------------------------------------------------------------------- -//Private static methods -//-------------------------------------------------------------------------- - -/** - * Finds all the classes reachable from the current classpath; - * for each of them, inserts an association (name, fully-qualified - * name) in the specified map. Both names are String objects. - * - * Only classes reachable from the classpath defined by the - * "java.class.path" property are considered. - * Jar files and directories are both parsed. - * If multiple classes with the same name but different - * fully-qualified names are present, they are inserted - * in the map as associations (name, comma-separated list of - * fully-qualified names). - * - * @param map - * @throws IOException - */ -private static void findClasses(Map map) -throws IOException -{ - String classPath = System.getProperty( "java.class.path" ); - String separator = System.getProperty( "path.separator" ); - String filesep = System.getProperty( "file.separator"); - StringTokenizer path = new StringTokenizer( classPath, separator ); - - while( path.hasMoreTokens() ) { - - String pathElement = path.nextToken(); - File pathFile = new File( pathElement ); - - if( pathFile.isDirectory() ) { - if (!pathElement.endsWith(filesep)) { - pathElement = pathElement + filesep; - pathFile = new File( pathElement); - } - findClassInPathDir( map, pathElement, pathFile ); - // Search directories - } else if ( pathFile.exists() ) { - findClassInJar( map, pathFile); - } - } -} - -//-------------------------------------------------------------------------- - -/** - * Parses jar file. - * - * @param map the map where to insert associations - * @param pathFile the file name of the associated jar file - * @throws IOException - */ -private static void findClassInJar(Map map, File pathFile) -throws IOException -{ - ZipFile zipFile = new ZipFile( pathFile ); - Enumeration entries = zipFile.entries(); - while( entries.hasMoreElements() ) { - - String entry = entries.nextElement().toString(); - if( entry.endsWith( ".class" ) ) { - // File names in ZIP archives (so, also in JARs) - // are separated by forward slashes '/', independently - // of the architecture. - String className = classname( entry, "/" ); - String shortName = getShortName( className ); - if (map.containsKey(shortName)) { - map.put(shortName, - map.get(shortName)+","+className); - } else { - map.put(shortName, className); - } - } - } -} - -//-------------------------------------------------------------------------- - -/** - * Recursively parses directories. - * - * @param map the map where to insert associations - * @param pathElement the path string used for recursion - * @param pathFile the file (directory) to be analyzed - * @throws IOException - */ -private static void findClassInPathDir( Map map, - String pathElement, File pathFile ) -throws IOException -{ - visitedDirs++; - if(visitedDirs>=maxDirs) return; - - String[] list = pathFile.list(); - String filesep = System.getProperty( "file.separator"); - - for( int i = 0; i < list.length; i++ ) { - File file = new File( pathFile, list[i] ); - if( file.isDirectory() ) { - findClassInPathDir( map, pathElement, file ); - } - else if ( file.exists() && (file.length() != 0) && list[i].endsWith( ".class" ) ) { - String classFile = file.toString().substring( pathElement.length()); - String className = classname( classFile, filesep ); - String shortName = getShortName( className ); - if (map.containsKey(shortName)) { - map.put(shortName, map.get(shortName)+","+className); - } else { - map.put(shortName, className); - } - } - } -} - -//-------------------------------------------------------------------------- - -/** - * Translates a class file name in a class name using - * the specified file separator. - */ -private static String classname(String classFile, String filesep) -{ - return classFile.replace( filesep, "." ).substring( - 0, classFile.length() - ".class".length() ); -} - -//-------------------------------------------------------------------------- - -/** - * Testing. - * - * @param argv - */ -public static void main( String[] argv ) -{ - Iterator i = map.keySet().iterator(); - while (i.hasNext()) { - String key = (String) i.next(); - String name = map.get(key); - System.out.println(key + " --> " + name); - } -} -} diff --git a/contrib/psg/src/peersim/config/ConfigContainer.java b/contrib/psg/src/peersim/config/ConfigContainer.java deleted file mode 100644 index 75f3cb6ad9..0000000000 --- a/contrib/psg/src/peersim/config/ConfigContainer.java +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -import java.lang.reflect.*; -import java.util.*; -import org.lsmp.djep.groupJep.*; - -/** - * This class is the container for the configuration data used in - * {@link Configuration}; see that class for more information. - */ -public class ConfigContainer -{ - -// =================== static fields ================================= -// =================================================================== - -/** Symbolic constant for no debug */ -private static final int DEBUG_NO = 0; - -/** Symbolic constant for regular debug */ -private static final int DEBUG_REG = 1; - -/** Symbolic constant for extended debug */ -private static final int DEBUG_CONTEXT = 2; - -//========================== fields ================================= -//=================================================================== - -/** - * The properties object that stores all configuration information. - */ -private Properties config; - -/** - * Map associating string protocol names to the numeric protocol - * identifiers. The protocol names are understood without prefix. - */ -private Map protocols; - -/** - * The maximum depth that can be reached when analyzing expressions. This - * value can be substituted by setting the configuration parameter - * PAR_MAXDEPTH. - */ -private int maxdepth; - -/** Debug level */ -private int debugLevel; - -/** - * If true, no exception is thrown. Instead, an error is printed and the - * Configuration tries to return a reasonable return value - */ -private boolean check = false; - -// =================== initialization ================================ -// =================================================================== - -public ConfigContainer(Properties config, boolean check) -{ - this.config = config; - this.check = check; - maxdepth = getInt(Configuration.PAR_MAXDEPTH, Configuration.DEFAULT_MAXDEPTH); - - // initialize protocol id-s - protocols = new HashMap(); - String[] prots = getNames(Configuration.PAR_PROT);// they're returned in correct order - for (int i = 0; i < prots.length; ++i) { - protocols.put(prots[i].substring(Configuration.PAR_PROT.length() + 1), Integer.valueOf(i)); - } - String debug = config.getProperty(Configuration.PAR_DEBUG); - if (Configuration.DEBUG_EXTENDED.equals(debug)) - debugLevel = DEBUG_CONTEXT; - else if (Configuration.DEBUG_FULL.equals(debug)) { - Map map = new TreeMap(); - Enumeration e = config.propertyNames(); - while (e.hasMoreElements()) { - String name = (String) e.nextElement(); - String value = config.getProperty(name); - map.put(name, value); - } - Iterator i = map.keySet().iterator(); - while (i.hasNext()) { - String name = (String) i.next(); - System.err.println("DEBUG " + name - + ("".equals(map.get(name)) ? "" : " = " + map.get(name))); - } - } else if (debug != null) { - debugLevel = DEBUG_REG; - } else { - debugLevel = DEBUG_NO; - } -} - -// =================== static public methods ========================= -// =================================================================== - -/** - * @return true if and only if name is a specified (existing) property. - */ -public boolean contains(String name) -{ - boolean ret = config.containsKey(name); - debug(name, "" + ret); - return ret; -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * {@link MissingParameterException}. - * @param name - * Name of configuration property - * @param def - * default value - */ -public boolean getBoolean(String name, boolean def) -{ - try { - return getBool(name); - } catch (RuntimeException e) { - manageDefault(name, def, e); - return def; - } -} - -// ------------------------------------------------------------------- - - -/** - * Reads given property. If not found, or the value is empty string then - * throws a {@link MissingParameterException}. Empty string is not - * accepted as false due to the similar function of {@link #contains} which - * returns true in that case. True is returned if the lowercase value of - * the property is "true", otherwise false is returned. - * @param name - * Name of configuration property - */ -public boolean getBoolean(String name) -{ - try { - return getBool(name); - } catch (RuntimeException e) { - manageException(name, e); - return false; - } -} - -//------------------------------------------------------------------- - -/** - * The actual methods that implements getBoolean. - */ -private boolean getBool(String name) -{ - if (config.getProperty(name) == null) { - throw new MissingParameterException(name); -// "\nPossibly incorrect property: " + getSimilarProperty(name)); - } - if (config.getProperty(name).matches("\\p{Blank}*")) { - throw new MissingParameterException(name, - "Blank value is not accepted when parsing Boolean."); - } - boolean ret = Boolean.valueOf(config.getProperty(name)); - debug(name, "" + ret); - return ret; -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - */ -public int getInt(String name, int def) -{ - try { - Number ret = getVal(name, name, 0); - debug(name, "" + ret); - return ret.intValue(); - } catch (RuntimeException e) { - manageDefault(name, def, e); - return def; - } -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * {@link MissingParameterException}. - * @param name - * Name of configuration property - */ -public int getInt(String name) -{ - try { - Number ret = getVal(name, name, 0); - debug(name, "" + ret); - return ret.intValue(); - } catch (RuntimeException e) { - manageException(name, e); - return 0; - } -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - */ -public long getLong(String name, long def) -{ - try { - Number ret = getVal(name, name, 0); - debug(name, "" + ret); - return ret.longValue(); - } catch (RuntimeException e) { - manageDefault(name, def, e); - return def; - } -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * {@link MissingParameterException}. - * @param name - * Name of configuration property - */ -public long getLong(String name) -{ - try { - Number ret = getVal(name, name, 0); - debug(name, "" + ret); - return ret.longValue(); - } catch (RuntimeException e) { - manageException(name, e); - return 0; - } -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - */ -public double getDouble(String name, double def) -{ - try { - Number ret = getVal(name, name, 0); - debug(name, "" + ret); - return ret.doubleValue(); - } catch (RuntimeException e) { - manageDefault(name, def, e); - return def; - } -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * MissingParameterException. - * @param name - * Name of configuration property - */ -public double getDouble(String name) -{ - try { - Number ret = getVal(name, name, 0); - debug(name, "" + ret); - return ret.doubleValue(); - } catch (RuntimeException e) { - manageException(name, e); - return 0; - } -} - -// ------------------------------------------------------------------- - -/** - * Read numeric property values, parsing expression if necessary. - * - * @param initial - * the property name that started this expression evaluation - * @param property - * the current property name to be evaluated - * @param depth - * the depth reached so far - * @return the evaluation of the expression associated to property - */ -private Number getVal(String initial, String property, int depth) -{ - if (depth > maxdepth) { - throw new IllegalParameterException(initial, - "Probable recursive definition - exceeded maximum depth " + - maxdepth); - } - - String s = config.getProperty(property); - if (s == null || s.equals("")) { - throw new MissingParameterException(property, - " when evaluating property " + initial); -// + "\nPossibly incorrect property: " + getSimilarProperty(property)); - } - - GroupJep jep = new GroupJep(new Operators()); - jep.setAllowUndeclared(true); - - jep.parseExpression(s); - String[] symbols = getSymbols(jep); - for (int i = 0; i < symbols.length; i++) { - Object d = getVal(initial, symbols[i], depth + 1); - jep.addVariable(symbols[i], d); - } - Object ret = jep.getValueAsObject(); - if (jep.hasError()) - System.err.println(jep.getErrorInfo()); - return (Number) ret; -} - -// ------------------------------------------------------------------- - -/** - * Returns an array of string, containing the symbols contained in the - * expression parsed by the specified JEP parser. - * @param jep - * the java expression parser containing the list of variables - * @return an array of strings. - */ -private String[] getSymbols(org.nfunk.jep.JEP jep) -{ - Hashtable h = jep.getSymbolTable(); - String[] ret = new String[h.size()]; - Enumeration e = h.keys(); - int i = 0; - while (e.hasMoreElements()) { - ret[i++] = (String) e.nextElement(); - } - return ret; -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - */ -public String getString(String name, String def) -{ - try { - return getStr(name); - } catch (RuntimeException e) { - manageDefault(name, def, e); - return def; - } -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * MissingParameterException. Removes trailing whitespace characters. - * @param name - * Name of configuration property - */ -public String getString(String name) -{ - try { - return getStr(name); - } catch (RuntimeException e) { - manageException(name, e); - return ""; - } -} - -/** - * The actual method implementing getString(). - */ -private String getStr(String name) -{ - String result = config.getProperty(name); - if (result == null) { - throw new MissingParameterException(name); -// "\nPossibly incorrect property: " + getSimilarProperty(name)); - } - debug(name, "" + result); - - return result.trim(); -} - -// ------------------------------------------------------------------- - -/** - * Reads the given property from the configuration interpreting it as a - * protocol name. Returns the numeric protocol identifier of this protocol - * name. See the discussion of protocol name at {@link Configuration} for - * details on how this numeric id is calculated - * - * @param name - * Name of configuration property - * @return the numeric protocol identifier associated to the value of the - * property - */ -public int getPid(String name) -{ - try { - String protname = getStr(name); - return lookupPid(protname); - } catch (RuntimeException e) { - manageException(name, e); - return 0; - } -} - -// ------------------------------------------------------------------- - -/** - * Calls {@link #getPid(String)}, and returns the default if no property - * is defined with the given name. - * - * @param name - * Name of configuration property - * @param pid - * the default protocol identifier - * @return the numeric protocol identifier associated to the value of the - * property, or the default if not defined - */ -public int getPid(String name, int pid) -{ - try { - String protname = getStr(name); - return lookupPid(protname); - } catch (RuntimeException e) { - manageDefault(name, pid, e); - return pid; - } -} - -// ------------------------------------------------------------------- - -/** - * Returns the numeric protocol identifier of the given protocol name. - * - * @param protname - * the protocol name. - * @return the numeric protocol identifier associated to the protocol name - */ -public int lookupPid(String protname) -{ - Integer ret = protocols.get(protname); - if (ret == null) { - throw new MissingParameterException(Configuration.PAR_PROT + "." + protname); -// "\nPossibly incorrect property: " -// + getSimilarProperty(PAR_PROT + "." + protname)); - } - return ret.intValue(); -} - -// ------------------------------------------------------------------- - -/** - * Returns the name of a protocol that has the given identifier. - *

- * Note that this is not a constant time operation in the number of - * protocols, although typically there are very few protocols defined. - * - * @param pid - * numeric protocol identifier. - * @return name of the protocol that has the given id. null if no protocols - * have the given id. - */ -public String lookupPid(int pid) -{ - - if (!protocols.containsValue(pid)) - return null; - for (Map.Entry i : protocols.entrySet()) { - if (i.getValue().intValue() == pid) - return i.getKey(); - } - - // never reached but java needs it... - return null; -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * {@link MissingParameterException}. When creating the Class object, a - * few attempts are done to resolve the classname. See - * {@link Configuration} for details. - * @param name - * Name of configuration property - */ -public Class getClass(String name) -{ - try { - return getClazz(name); - } catch (RuntimeException e) { - manageException(name, e); - return null; - } -} - -private Class getClazz(String name) -{ - String classname = config.getProperty(name); - if (classname == null) { - throw new MissingParameterException(name); -// "\nPossibly incorrect property: " + getSimilarProperty(name)); - } - debug(name, classname); - - Class c = null; - - try { - // Maybe classname is just a fully-qualified name - c = Class.forName(classname); - } catch (ClassNotFoundException e) { - } - if (c == null) { - // Maybe classname is a non-qualified name? - String fullname = ClassFinder.getQualifiedName(classname); - if (fullname != null) { - try { - c = Class.forName(fullname); - } catch (ClassNotFoundException e) { - } - } - } - if (c == null) { - // Maybe there are multiple classes with the same - // non-qualified name. - String fullname = ClassFinder.getQualifiedName(classname); - if (fullname != null) { - String[] names = fullname.split(","); - if (names.length > 1) { - for (int i = 0; i < names.length; i++) { - for (int j = i + 1; j < names.length; j++) { - if (names[i].equals(names[j])) { - throw new IllegalParameterException(name, - "The class " + names[i] - + " appears more than once in the classpath; please check" - + " your classpath to avoid duplications."); - } - } - } - throw new IllegalParameterException(name, - "The non-qualified class name " + classname - + "corresponds to multiple fully-qualified classes:" + fullname); - } - } - } - if (c == null) { - // Last attempt: maybe the fully classified name is wrong, - // but the classname is correct. - String shortname = ClassFinder.getShortName(classname); - String fullname = ClassFinder.getQualifiedName(shortname); - if (fullname != null) { - throw new IllegalParameterException(name, "Class " - + classname + " does not exist. Possible candidate(s): " + fullname); - } - } - if (c == null) { - throw new IllegalParameterException(name, "Class " - + classname + " not found"); - } - return c; -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - * @see #getClass(String) - */ -public Class getClass(String name, Class def) -{ - - try { - return Configuration.getClass(name); - } catch (RuntimeException e) { - manageDefault(name, def, e); - return def; - } -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property for a class name. It returns an - * instance of the class. The class must implement a constructor that takes - * a String as an argument. The value of this string will be name. - * The constructor of the class can see the configuration so it can make - * use of this name to read its own parameters from it. - * @param name - * Name of configuration property - * @throws MissingParameterException - * if the given property is not defined - * @throws IllegalParameterException - * if there is any problem creating the instance - */ -public Object getInstance(String name) -{ - try { - return getInst(name); - } catch (RuntimeException e) { - manageException(name, e); - return null; - } -} - -/** - * The actual method implementing getInstance(). - */ -private Object getInst(String name) -{ - Class c = getClass(name); - if (c == null) - return null; - final String classname = c.getSimpleName(); - - try { - Class pars[] = {String.class}; - Constructor cons = c.getConstructor(pars); - Object objpars[] = {name}; - return cons.newInstance(objpars); - } catch (NoSuchMethodException e) { - throw new IllegalParameterException(name, "Class " - + classname + " has no " + classname + "(String) constructor"); - } catch (InvocationTargetException e) { - if (e.getTargetException() instanceof RuntimeException) { - throw (RuntimeException) e.getTargetException(); - } else { - e.getTargetException().printStackTrace(); - throw new RuntimeException("" + e.getTargetException()); - } - } catch (Exception e) { - throw new IllegalParameterException(name, e + ""); - } -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property for a class name. It returns an - * instance of the class. The class must implement a constructor that takes - * a String as an argument. The value of this string will be name. - * The constructor of the class can see the configuration so it can make - * use of this name to read its own parameters from it. - * @param name - * Name of configuration property - * @param def - * The default object that is returned if there is no property - * defined with the given name - * @throws IllegalParameterException - * if the given name is defined but there is a problem creating - * the instance. - */ -public Object getInstance(String name, Object def) -{ - if (!contains(name)) - return def; - try { - return getInst(name); - } catch (RuntimeException e) { - manageException(name, e); - return def; - } -} - -// ------------------------------------------------------------------- - -/** - * It returns an array of class instances. The instances are constructed by - * calling {@link #getInstance(String)} on the names returned by - * {@link #getNames(String)}. - * @param name - * The component type (i.e. prefix of the list of configuration - * properties) which will be passed to {@link #getNames(String)}. - */ -public Object[] getInstanceArray(String name) -{ - - String names[] = getNames(name); - Object[] result = new Object[names.length]; - - for (int i = 0; i < names.length; ++i) { - result[i] = getInstance(names[i]); - } - - return result; -} - -// ------------------------------------------------------------------- - -/** - * Returns an array of names prefixed by the specified name. The array is - * sorted as follows. If there is no config entry - * {@value peersim.config.Configuration#PAR_INCLUDE}+"."+name or - * {@value peersim.config.Configuration#PAR_ORDER}+"."+name then the order is - * alphabetical. Otherwise this entry defines the order. For more - * information see {@link Configuration}. - * @param name - * the component type (i.e., the prefix) - * @return the full property names in the order specified by the - * configuration - */ -public String[] getNames(String name) -{ - ArrayList ll = new ArrayList(); - final String pref = name + "."; - - Enumeration e = config.propertyNames(); - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - if (key.startsWith(pref) && key.indexOf(".", pref.length()) < 0) - ll.add(key); - } - String[] ret = ll.toArray(new String[ll.size()]); - return order(ret, name); -} - -// ------------------------------------------------------------------- - -/** - * The input of this method is a set of property names (e.g. - * initializers, controls and protocols) and a string specifying the type - * (prefix) of these. The output is in names, which will - * contain a permutation of the original array. Parameter - * PAR_INCLUDE+"."+type, or if not present, PAR_ORDER+"."+type is read from - * the configuration. If none of them are defined then the order is - * identical to that of names. Otherwise the configuration - * entry must contain entries from names. It is assumed - * that the entries in names contain only word characters - * (alphanumeric and underscore '_'. The order configuration entry thus - * contains a list of entries from names separated by any - * non-word characters. - *

- * It is not required that all entries are listed. If PAR_INCLUDE is used, - * then only those entries are returned that are listed. If PAR_ORDER is - * used, then all names are returned, but the array will start with those - * that are listed. The rest of the names follow in alphabetical order. - * - * - * @param names - * the set of property names to be searched - * @param type - * the string identifying the particular set of properties to be - * inspected - */ -private String[] order(String[] names, String type) -{ - String order = getString(Configuration.PAR_INCLUDE + "." + type, null); - boolean include = order != null; - if (!include) - order = getString(Configuration.PAR_ORDER + "." + type, null); - - int i = 0; - if (order != null && !order.equals("")) { - // split around non-word characters - String[] sret = order.split("\\W+"); - for (; i < sret.length; i++) { - int j = i; - for (; j < names.length; ++j) - if (names[j].equals(type + "." + sret[i])) - break; - if (j == names.length) { - throw new IllegalParameterException( - (include ? Configuration.PAR_INCLUDE : Configuration.PAR_ORDER) - + "." + type, type + "." + sret[i] + " is not defined."); - } else // swap the element to current position - { - String tmps = names[j]; - names[j] = names[i]; - names[i] = tmps; - } - } - } - - Arrays.sort(names, i, names.length); - int retsize = (include ? i : names.length); - String[] ret = new String[retsize]; - for (int j = 0; j < retsize; ++j) - ret[j] = names[j]; - return ret; -} - -// ------------------------------------------------------------------- - -/** - * Print debug information for configuration. The amount of information - * depends on the debug level DEBUG. 0 = nothing 1 = just the config name 2 = - * config name plus method calling - * - * @param name - */ -private void debug(String name, String result) -{ - if (debugLevel == DEBUG_NO) - return; - StringBuffer buffer = new StringBuffer(); - buffer.append("DEBUG "); - buffer.append(name); - buffer.append(" = "); - buffer.append(result); - - // Additional info - if (debugLevel == DEBUG_CONTEXT) { - - buffer.append("\n at "); - // Obtain the stack trace - StackTraceElement[] stack = null; - try { - throw new Exception(); - } catch (Exception e) { - stack = e.getStackTrace(); - } - - // Search the element that invoked Configuration - // It's the first whose class is different from Configuration - int pos; - for (pos = 0; pos < stack.length; pos++) { - if (!stack[pos].getClassName().equals(Configuration.class.getName())) - break; - } - - buffer.append(stack[pos].getClassName()); - buffer.append(":"); - buffer.append(stack[pos].getLineNumber()); - buffer.append(", method "); - buffer.append(stack[pos - 1].getMethodName()); - buffer.append("()"); - } - - System.err.println(buffer); -} - -// ------------------------------------------------------------------- - -/** - * @return an array of adjacent letter pairs contained in the input string - * http://www.catalysoft.com/articles/StrikeAMatch.html - */ -private String[] letterPairs(String str) -{ - int numPairs = str.length() - 1; - String[] pairs = new String[numPairs]; - for (int i = 0; i < numPairs; i++) { - pairs[i] = str.substring(i, i + 2); - } - return pairs; -} - -// ------------------------------------------------------------------- - -/** - * @return an ArrayList of 2-character Strings. - * http://www.catalysoft.com/articles/StrikeAMatch.html - */ -private ArrayList wordLetterPairs(String str) -{ - ArrayList allPairs = new ArrayList(); - // Tokenize the string and put the tokens/words into an array - String[] words = str.split("\\s"); - // For each word - for (int w = 0; w < words.length; w++) { - // Find the pairs of characters - String[] pairsInWord = letterPairs(words[w]); - for (int p = 0; p < pairsInWord.length; p++) { - allPairs.add(pairsInWord[p]); - } - } - return allPairs; -} - -// ------------------------------------------------------------------- - -/** - * @return lexical similarity value in the range [0,1] - * http://www.catalysoft.com/articles/StrikeAMatch.html - */ -private double compareStrings(String str1, String str2) -{ - ArrayList pairs1 = wordLetterPairs(str1.toUpperCase()); - ArrayList pairs2 = wordLetterPairs(str2.toUpperCase()); - int intersection = 0; - int union_ = pairs1.size() + pairs2.size(); - for (int i = 0; i < pairs1.size(); i++) { - Object pair1 = pairs1.get(i); - for (int j = 0; j < pairs2.size(); j++) { - Object pair2 = pairs2.get(j); - if (pair1.equals(pair2)) { - intersection++; - pairs2.remove(j); - break; - } - } - } - return (2.0 * intersection) / union_; -} - -// ------------------------------------------------------------------- - -/** - * Among the defined properties, returns the one more similar to String - * property - */ -private String getSimilarProperty(String property) -{ - String bestProperty = null; - double bestValue = 0.0; - Enumeration e = config.keys(); - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - double compare = compareStrings(key, property); - if (compare > bestValue) { - bestValue = compare; - bestProperty = key; - } - } - return bestProperty; -} - -//------------------------------------------------------------------- - -private void manageDefault(String name, Object def, - RuntimeException e) -{ - debug(name, "" + def + " (DEFAULT)"); - if (check) { - System.out.println("Warning: Property " + name + " = " + - def + " (DEFAULT)"); - } - if (e instanceof MissingParameterException) { - // Do nothing - } else { - manageException(name, e); - } -} - -//------------------------------------------------------------------- - -private void manageException(String name, RuntimeException e) -{ - if (check) { - if (e instanceof MissingParameterException) { - // Print just the short message in this case - System.out.println("Error: " + - ((MissingParameterException) e).getShortMessage()); - } else if (e instanceof IllegalParameterException) { - // Print just the short message in this case - System.out.println("Error: " + - ((IllegalParameterException) e).getShortMessage()); - } else { - System.out.println("Error: " + e.getMessage()); - } - } else { - throw e; - } -} - -//------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/config/ConfigProperties.java b/contrib/psg/src/peersim/config/ConfigProperties.java deleted file mode 100644 index 4f36892d14..0000000000 --- a/contrib/psg/src/peersim/config/ConfigProperties.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -import java.util.Properties; -import java.io.*; - -/** -* Class for handling configuration files. Extends the functionality -* of Properties by handling files, system resources and command lines. -*/ -public class ConfigProperties extends Properties { - - -// =========== Public Constructors =================================== -// =================================================================== - - -/** -* Calls super constructor. -*/ -public ConfigProperties() { super(); } - -// ------------------------------------------------------------------- - -/** -* Constructs a ConfigProperty object from a parameter list. -* The algorithm is as follows: first resource is used to attempt -* loading default values from the given system resource. -* Then all Strings in pars are processed in the order they -* appear in the array. For pars[i], first a property file -* with the name pars[i] is attempted to be loaded. If the file -* does not exist or loading produces any other IOException, pars[i] -* is interpreted as a property definition, and it is set. -*

-* A little inconvenience is that if pars[i] is supposed to be -* a command line argument, but it is a valid filename at the same time by -* accident, the algorithm will process it as a file instead of a command line -* argument. The caller must take care of that. -*

-* No exceptions are thrown, instead error messages are written to the -* standard error. Users who want a finer control should use -* the public methods of this class. -* -* @param pars The (probably command line) parameter list. -* @param resource The name of the system resource that contains the -* defaults. null if there isn't any. -* -*/ -public ConfigProperties( String[] pars, String resource ) { - - try - { - if( resource != null ) - { - loadSystemResource(resource); - System.err.println("ConfigProperties: System resource " - +resource+" loaded."); - } - } - catch( Exception e ) - { - System.err.println("ConfigProperties: " + e ); - } - - if( pars == null || pars.length == 0 ) return; - - for (int i=0; i < pars.length; i++) - { - try - { - load( pars[i] ); - System.err.println( - "ConfigProperties: File "+pars[i]+" loaded."); - pars[i] = ""; - } - catch( IOException e ) - { - try - { - loadPropertyString( pars[i] ); - System.err.println("ConfigProperties: Property '" + - pars[i] + "' set."); - } - catch( Exception e2 ) - { - System.err.println("ConfigProperties: " + e2 ); - } - } - catch( Exception e ) - { - System.err.println("ConfigProperties: " + e ); - } - } -} - -// ------------------------------------------------------------------- - -/** -* Constructs a ConfigProperty object by loading a file by calling -* {@link #load}. -* @param fileName The name of the configuration file. -*/ -public ConfigProperties( String fileName ) throws IOException { - - load( fileName ); -} - -// ------------------------------------------------------------------- - -/** -* Calls super constructor. -*/ -public ConfigProperties( Properties props ) { - - super( props ); -} - -// ------------------------------------------------------------------- - -/** -* Calls {@link #ConfigProperties(String[],String)} with resource set to null. -*/ -public ConfigProperties( String[] pars ) { - - this( pars, null ); -} - - -// =========== Public methods ======================================== -// =================================================================== - - -/** -* Loads given file. Calls Properties.load with a file -* input stream to the given file. -*/ -public void load( String fileName ) throws IOException { - - FileInputStream fis = new FileInputStream( fileName ); - load( fis ); - fis.close(); -} - -// ------------------------------------------------------------------- - -/** -* Adds the properties from the given property file. Searches in the class path -* for the file with the given name. -*/ -public void loadSystemResource( String n ) throws IOException { - - ClassLoader cl = getClass().getClassLoader(); - load( cl.getResourceAsStream( n ) ); -} - -// ------------------------------------------------------------------- - -/** -* Appends a property defined in the given string. -* The string is considered as a property file line. -* It is converted to a byte array according to the -* default character encoding and then loaded by the -* Properties.load method. This means that the ISO-8859-1 -* (or compatible) encoding is assumed. -*/ -public void loadPropertyString( String prop ) throws IOException { - - StringBuffer sb = new StringBuffer(); - sb.append( prop ).append( "\n" ); - load( new ByteArrayInputStream(sb.toString().getBytes()) ); -} -} - diff --git a/contrib/psg/src/peersim/config/Configuration.java b/contrib/psg/src/peersim/config/Configuration.java deleted file mode 100644 index 4188111bef..0000000000 --- a/contrib/psg/src/peersim/config/Configuration.java +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -import java.util.*; - -/** - * Fully static class to store configuration information. It defines a - * method, {@link #setConfig(Properties)}, to set configuration data. This - * method is called by the simulator engines as the very first thing they - * do. It can be called only once, after that the class becomes read only. - * All components can then access this configuration and utility methods to - * read property values based on their names. - *

- * The design of this class also hides the actual implementation of the - * configuration which can be Properties, XML, whatever. Currently only - * Properties is supported. - *

- * Apart from storing (name,value) pairs, this class also does some - * processing, and offers some utility functions. This extended - * functionality consists of the following: reading values with type - * checking, ordering of entries, pre-processing protocol names, parsing - * expressions, resolving underspecified classnames, and finally some basic - * debugging possibilities. We discuss these in the following. - *

- * Note that the configuration is initialized using a Properties object. - * The class of this object might implement some additional pre-processing - * on the file or provide an extended syntax for defining property files. - * See {@link ParsedProperties} for more details. This is the class that is - * currently used by simulation engines. - *

Typed reading of values

- * Properties can have arbitrary values of type String. This class offers a - * set of read methods that perform the appropriate conversion of the - * string value to the given type, eg long. They also allow for specifying - * default values in case the given property is not specified. - *

Resolving class names

- * - * The possibilities for the typed reading of a value includes interpreting - * the value as a class name. In this case an object will be constructed. - * It is described at method {@link #getInstance(String)} how this is - * achieved exactly. What needs to be noted here is that the property value - * need not be a fully specified classname. It might contain only the short - * class name without the package specification. In this case, it is - * attempted to locate a class with that name in the classpath, and if a - * unique class is found, it will be used. This simplifies the - * configuration files and also allows to remove their dependence on the - * exact location of the class. - * - *

Components and their ordering

- * The idea of the configuration is that it mostly contains components and - * their descriptions (parameters). Although this class is blind to the - * semantics of these components, it offers some low level functionality - * that helps dealing with them. This functionality is based on the - * assumption that components have a type and a name. Both types and names - * are strings of alphanumeric and underscore characters. For example, - * {@value #PAR_PROT} is a type, "foo" can be a name. Method - * {@link #getNames} allow the caller to get the list of names for a given - * type. Some other methods, like {@link #getInstanceArray} use this list - * to return a list of components. - * - *

- * Assuming the configuration is in Properties format (which is currently - * the only format available) component types and names are defined as - * follows. Property names containing two non-empty words separated by one - * dot (".") character are treated specially (the words contain word - * characters: alphanumeric and underscore ("_")). The first word will be - * the type, and the second is the name of a component. For example, - * - *

- *   control.conn ConnectivityObserver
- *   control.1 WireKOut
- *   control.2 PrintGraph
- * 
- * - * defines control components of names "conn","1" an "2" (arguments of the - * components not shown). When {@link #getNames} or - * {@link #getInstanceArray} are called, eg - * getNames("control"), then the order in which these are - * returned is alphabetical: - * ["control.1","control.2","control.conn"]. If you are not - * satisfied with lexicographic order, you can specify the order in this - * way. - * - *
- *   order.control 1,conn,2
- * 
- * - * where the names are separated by any non-word character (non - * alphanumeric or underscore). If not all names are listed then the given - * order is followed by alphabetical order of the rest of the items, e.g. - * - *
- *   order.control 2
- * 
- * - * results in ["control.2","control.1","control.conn"]. - *

- * It is also possible to exclude elements from the list, while ordering - * them. The syntax is identical to that of the above, only the parameter - * name begins with include. For example - * - *

- *   include.control conn 2
- * 
- * - * will result in returning only control.conn and - * control.2, in this order. Note that for example the - * empty list results in a zero length array in this case. - * Important! If include is defined then ordering is ignored. - * That is, include is stronger than order. - *

Protocol names

- * As mentioned, the configuration is generally blind to the actual names - * of the components. There is an exception: the components of type - * {@value #PAR_PROT}. These are pre-processed a bit to enhance - * performance: protocol names are mapped to numeric protocol identifiers. - * The numeric identifier of a protocol is its index in the array returned - * by {@link #getNames}. See above how to control this order. The numeric - * identifiers then can be looked up based on the name and vice versa. - * Besides, the identifier can be directly requested based on a property - * name when the protocol name is the value of a property which is - * frequently the case. - *

- *

Expressions

- * Numeric property values can be complex expressions, that are parsed - * using
JEP. You can write - * expression using the syntax that you can find here. - * For example, - * - *
- *   MAG 2
- *   SIZE 2ˆMAG
- * 
- * - * SIZE=4. You can also have complex expression trees like this: - * - *
- *   A B+C
- *   B D+E
- *   C E+F
- *   D 1
- *   E F
- *   F 2
- * 
- * - * that results in A=7, B=3, C=4, D=1, E=2, F=2 - * - *

- * Expressions like "sub-expression op sub-expression" are computed based - * on the type of the sub-expressions. If both sub-expressions are integer, - * the computation is done using integer arithmetics and the result is an - * integer. So, for example, 5/2 returns 2. If one of the sub-expression is - * floating point, the computation is based on floating-point arithmetics - * (double precision) and the result is a floating point value. So, for - * example, 5.0/2 returns 2.5. - * - *

- * Expressions are parsed recursively. Note that no optimization is done, - * so expression F is evaluated three times here (due to the fact that - * appears twice in C and once in B). But since properties are read just - * once at initialization, this is not a performance problem. - * - *

- * Finally, recursive definitions are not allowed (and without function - * definitions, they make no sense). Since it is difficult to discover - * complex recursive chains, a simple trick is used: if the depth of - * recursion is greater than a given threshold (configurable, currently - * {@value #DEFAULT_MAXDEPTH}, an error message is printed. This avoids to - * fill the stack, that results in an anonymous OutOfMemoryError. So, if - * you write - * - *

- *   overlay.size SIZE
- *   SIZE SIZE-1
- * 
- * - * you get an error message: Parameter "overlay.size": Probable recursive - * definition - exceeded maximum depth {@value #DEFAULT_MAXDEPTH} - * - *

Debug

- * - * It is possible to obtain debug information about the configuration - * properties by activating special configuration properties. - *

- * If property {@value #PAR_DEBUG} is defined, each config property and the - * associated value are printed. Properties that are not present in the - * config file but have default values are postfixed with the string - * "(DEFAULT)". - *

- * If property {@value #PAR_DEBUG} is defined and it is equal to - * {@value #DEBUG_EXTENDED}, information about the configuration method - * invoked, and where this method is invoked, is also printed. If it is - * equal to {@value #DEBUG_FULL}, all the properties are printed, even if - * they are not read. - *

- * Each line printed by this debug feature is prefixed by the string - * "DEBUG". - * - *

Use of brackets

- * - * For the sake of completeness, we mention it here that if this class is - * initialized using {@link ParsedProperties}, then it is possible to use - * some more compressed format to specify the components. See - * {@link ParsedProperties#load}. - * - */ -public class Configuration -{ - -// =================== static fields ================================= -// =================================================================== - -/** Default max depth limit to avoid recursive definitions */ -public static final int DEFAULT_MAXDEPTH = 100; - -/** - * The debug level for the configuration. If defined, a line is printed for - * each configuration parameter read. If defined and equal to - * {@value #DEBUG_EXTENDED}, additional context information for debug is - * printed. If defined and equal to {@value #DEBUG_FULL}, all the - * configuration properties are printed at the beginning, not just when - * they are called. - * @config - */ -static final String PAR_DEBUG = "debug.config"; - -/** - * If parameter {@value #PAR_DEBUG} is equal to this string, additional - * context information for debug is printed. - */ -static final String DEBUG_EXTENDED = "context"; - -/** - * If parameter {value #PAR_DEBUG} is equal to this string, all the - * configuration properties are printed at the beginning, not just when - * they are called. - */ -static final String DEBUG_FULL = "full"; - -/** - * The maximum depth for expressions. This is a simple mechanism to avoid - * unbounded recursion. The default is {@value #DEFAULT_MAXDEPTH}, and you - * probably don't want to change it. - * @config - */ -static final String PAR_MAXDEPTH = "expressions.maxdepth"; - -/** - * Used to configure ordering of the components. Determines the ordering in - * the array as returned by {@link #getNames}. See the general description - * of {@link Configuration} for details. - * @config - */ -static final String PAR_ORDER = "order"; - -/** - * Used to configure ordering of the components. Determines the ordering in - * the array as returned by {@link #getNames}, and can bu used to also - * exclude elements. See the general description of {@link Configuration} - * for details. - * @config - */ -static final String PAR_INCLUDE = "include"; - -// XXX it's ugly because it replicates the definition of Node.PAR_PROT, but -// this would be the only dependence on the rest of the core... -/** - * The type name of components describing protocols. This is the only point - * at which the class is not blind to the actual semantics of the - * configuration. - */ -static final String PAR_PROT = "protocol"; - -/** - * The properties object that stores all configuration information. - */ -private static ConfigContainer config = null; - -// =================== initialization ================================ -// =================================================================== - -/** to prevent construction */ -private Configuration() -{ -} - -// =================== static public methods ========================= -// =================================================================== - -/** - * Sets the system-wide configuration in Properties format. It can be - * called only once. After that the configuration becomes unmodifiable - * (read only). If modification is attempted, a RuntimeException is thrown - * and no change is made. - * @param p - * The Properties object containing configuration info - */ -public static void setConfig(Properties p) -{ - if (config != null) { - throw new RuntimeException("Setting configuration was attempted twice."); - } - config = new ConfigContainer(p, false); -} - -// ------------------------------------------------------------------- - -/** - * Sets the system-wide configuration in Properties format. It can be - * called only once. After that the configuration becomes unmodifiable - * (read only). If modification is attempted, a RuntimeException is thrown - * and no change is made. - * @param p - * The Properties object containing configuration info - */ -public static void setConfig(Properties p, boolean check) -{ - if (config != null) { - throw new RuntimeException("Setting configuration was attempted twice."); - } - config = new ConfigContainer(p, check); -} - -// ------------------------------------------------------------------- - -/** - * @return true if and only if name is a specified (existing) property. - */ -public static boolean contains(String name) -{ - return config.contains(name); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * {@link MissingParameterException}. - * @param name - * Name of configuration property - * @param def - * default value - */ -public static boolean getBoolean(String name, boolean def) -{ - return config.getBoolean(name, def); -} - -// ------------------------------------------------------------------- - -/** - * Reads given property. If not found, or the value is empty string then - * throws a {@link MissingParameterException}. Empty string is not - * accepted as false due to the similar function of {@link #contains} which - * returns true in that case. True is returned if the lowercase value of - * the property is "true", otherwise false is returned. - * @param name - * Name of configuration property - */ -public static boolean getBoolean(String name) -{ - return config.getBoolean(name); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - */ -public static int getInt(String name, int def) -{ - return config.getInt(name, def); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * {@link MissingParameterException}. - * @param name - * Name of configuration property - */ -public static int getInt(String name) -{ - return config.getInt(name); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - */ -public static long getLong(String name, long def) -{ - return config.getLong(name, def); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * {@link MissingParameterException}. - * @param name - * Name of configuration property - */ -public static long getLong(String name) -{ - return config.getLong(name); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - */ -public static double getDouble(String name, double def) -{ - return config.getDouble(name, def); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * MissingParameterException. - * @param name - * Name of configuration property - */ -public static double getDouble(String name) -{ - return config.getDouble(name); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - */ -public static String getString(String name, String def) -{ - return config.getString(name, def); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * MissingParameterException. Removes trailing whitespace characters. - * @param name - * Name of configuration property - */ -public static String getString(String name) -{ - return config.getString(name); -} - -// ------------------------------------------------------------------- - -/** - * Reads the given property from the configuration interpreting it as a - * protocol name. Returns the numeric protocol identifier of this protocol - * name. See the discussion of protocol name at {@link Configuration} for - * details on how this numeric id is calculated - * - * @param name - * Name of configuration property - * @return the numeric protocol identifier associated to the value of the - * property - */ -public static int getPid(String name) -{ - return config.getPid(name); -} - -// ------------------------------------------------------------------- - -/** - * Calls {@link #getPid(String)}, and returns the default if no property - * is defined with the given name. - * - * @param name - * Name of configuration property - * @param pid - * the default protocol identifier - * @return the numeric protocol identifier associated to the value of the - * property, or the default if not defined - */ -public static int getPid(String name, int pid) -{ - return config.getPid(name, pid); -} - -// ------------------------------------------------------------------- - -/** - * Returns the numeric protocol identifier of the given protocol name. - * - * @param protname - * the protocol name. - * @return the numeric protocol identifier associated to the protocol name - */ -public static int lookupPid(String protname) -{ - return config.lookupPid(protname); -} - -// ------------------------------------------------------------------- - -/** - * Returns the name of a protocol that has the given identifier. - *

- * Note that this is not a constant time operation in the number of - * protocols, although typically there are very few protocols defined. - * - * @param pid - * numeric protocol identifier. - * @return name of the protocol that has the given id. null if no protocols - * have the given id. - */ -public static String lookupPid(int pid) -{ - return config.lookupPid(pid); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, throws a - * {@link MissingParameterException}. When creating the Class object, a - * few attempts are done to resolve the classname. See - * {@link Configuration} for details. - * @param name - * Name of configuration property - */ -public static Class getClass(String name) -{ - return config.getClass(name); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property. If not found, returns the default - * value. - * @param name - * Name of configuration property - * @param def - * default value - * @see #getClass(String) - */ -public static Class getClass(String name, Class def) -{ - return config.getClass(name, def); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property for a class name. It returns an - * instance of the class. The class must implement a constructor that takes - * a String as an argument. The value of this string will be name. - * The constructor of the class can see the configuration so it can make - * use of this name to read its own parameters from it. - * @param name - * Name of configuration property - * @throws MissingParameterException - * if the given property is not defined - * @throws IllegalParameterException - * if there is any problem creating the instance - */ -public static Object getInstance(String name) -{ - return config.getInstance(name); -} - -// ------------------------------------------------------------------- - -/** - * Reads given configuration property for a class name. It returns an - * instance of the class. The class must implement a constructor that takes - * a String as an argument. The value of this string will be name. - * The constructor of the class can see the configuration so it can make - * use of this name to read its own parameters from it. - * @param name - * Name of configuration property - * @param def - * The default object that is returned if there is no property - * defined with the given name - * @throws IllegalParameterException - * if the given name is defined but there is a problem creating - * the instance. - */ -public static Object getInstance(String name, Object def) -{ - return config.getInstance(name, def); -} - -// ------------------------------------------------------------------- - -/** - * It returns an array of class instances. The instances are constructed by - * calling {@link #getInstance(String)} on the names returned by - * {@link #getNames(String)}. - * @param name - * The component type (i.e. prefix of the list of configuration - * properties) which will be passed to {@link #getNames(String)}. - */ -public static Object[] getInstanceArray(String name) -{ - return config.getInstanceArray(name); -} - -// ------------------------------------------------------------------- - -/** - * Returns an array of names prefixed by the specified name. The array is - * sorted as follows. If there is no config entry - * {@value #PAR_INCLUDE}+"."+name or - * {@value #PAR_ORDER}+"."+name then the order is - * alphabetical. Otherwise this entry defines the order. For more - * information see {@link Configuration}. - * @param name - * the component type (i.e., the prefix) - * @return the full property names in the order specified by the - * configuration - */ -public static String[] getNames(String name) -{ - return config.getNames(name); -} - -} diff --git a/contrib/psg/src/peersim/config/FastConfig.java b/contrib/psg/src/peersim/config/FastConfig.java deleted file mode 100644 index d2eba1b174..0000000000 --- a/contrib/psg/src/peersim/config/FastConfig.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -/** - * Reads configuration regarding relations between protocols. - * - * Technically, this class is not necessary because protocols could - * access the configuration directly. However, it provides much faster - * access to "linkable" and "transport" information, enhancing runtime speed. - * - * This class is a static singleton and is initialized only when first accessed. - * During initialization it reads and caches the configuration info it handles. - */ -public class FastConfig -{ - -// ======================= fields =========================================== -// =========================================================================== - -/** - * Parameter name in configuration that attaches a linkable protocol to a - * protocol. The property can contain multiple protocol names, in one line, - * separated by non-word characters (e.g. whitespace or ","). - * @config - */ -private static final String PAR_LINKABLE = "linkable"; - -/** - * Parameter name in configuration that attaches a transport layer protocol to a - * protocol. - * @config - */ -private static final String PAR_TRANSPORT = "transport"; - -/** - * This array stores the protocol ids of the {@link peersim.core.Linkable} - * protocols that are linked to the protocol given by the array index. - */ -protected static final int[][] links; - -/** - * This array stores the protocol id of the {@link peersim.transport.Transport} - * protocol that is linked to the protocol given by the array index. - */ -protected static final int[] transports; - - -// ======================= initialization =================================== -// ========================================================================== - - -/** - * This static initialization block reads the configuration for information that - * it understands. Currently it understands property {@value #PAR_LINKABLE} - * and {@value #PAR_TRANSPORT}. - * - * Protocols' linkable and transport definitions are prefetched - * and stored in arrays, to enable fast access during simulation. - * - * Note that this class does not perform any type checks. The purpose of the - * class is purely to speed up access to linkable and transport information, - * by providing a fast alternative to reading directly from the - * Configuration class. - */ -static { - String[] names = Configuration.getNames(Configuration.PAR_PROT); - links = new int[names.length][]; - transports = new int[names.length]; - for (int i = 0; i < names.length; ++i) - { - if (Configuration.contains(names[i] + "." + PAR_LINKABLE)) - { - // get string of linkables - String str = Configuration.getString(names[i] + "." + PAR_LINKABLE); - // split around non-word characters - String[] linkNames = str.split("\\W+"); - links[i] = new int[linkNames.length]; - for (int j=0; j 0; } - -// --------------------------------------------------------------------- - -/** - * Returns the number of linkable protocols associated with a given protocol. - */ -public static int numLinkables(int pid) { return links[pid].length; } - -// --------------------------------------------------------------------- - -/** - * Returns the protocol id of the linkIndex-th linkable used by - * the protocol identified by pid. Throws an - * IllegalParameterException if there is no linkable associated with the given - * protocol: we assume here that this happens when the configuration is - * incorrect. - */ -public static int getLinkable(int pid, int linkIndex) -{ - if (linkIndex >= numLinkables(pid)) { - String[] names = Configuration.getNames(Configuration.PAR_PROT); - throw new IllegalParameterException(names[pid], - "Protocol " + pid + " has no "+PAR_LINKABLE+ - " parameter with index" + linkIndex); - } - return links[pid][linkIndex]; -} - -//--------------------------------------------------------------------- - -/** - * Invokes getLinkable(pid, 0). - */ -public static int getLinkable(int pid) -{ - return getLinkable(pid, 0); -} - -// --------------------------------------------------------------------- - -/** - * Returns true if the given protocol has a transport protocol associated with - * it, otherwise false. - */ -public static boolean hasTransport(int pid) -{ - return transports[pid] >= 0; -} - -// --------------------------------------------------------------------- - -/** - * Returns the id of the transport protocol used by the protocol identified - * by pid. - * Throws an IllegalParameterException if there is no transport associated - * with the given protocol: we assume here that his happens when the - * configuration is incorrect. - */ -public static int getTransport(int pid) -{ - if (transports[pid] < 0) { - String[] names = Configuration.getNames(Configuration.PAR_PROT); - throw new IllegalParameterException(names[pid], - "Protocol " + pid + " has no "+PAR_TRANSPORT + " parameter"); - } - return transports[pid]; -} - -} diff --git a/contrib/psg/src/peersim/config/IllegalParameterException.java b/contrib/psg/src/peersim/config/IllegalParameterException.java deleted file mode 100644 index 1285350ff9..0000000000 --- a/contrib/psg/src/peersim/config/IllegalParameterException.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -/** -* Exception thrown to indicate that a -* configuration property has an invalid value. It is thrown by -* several methods in {@link Configuration} and can be thrown by any -* component that reads the configuration. -*/ -public class IllegalParameterException extends RuntimeException { - -// ================== initialization ===================================== -// ======================================================================= - -/** -* Calls super constructor. It passes a string message which is the given -* message, prefixed with the given property name. -* @param name Name of configuration property that is invalid -* @param message Additional info about why the value is invalid -*/ -public IllegalParameterException(String name, String message) { - - super("Parameter \"" + name + "\": " + message); -} - -// ================== methods ============================================ -// ======================================================================= - -/** -* Extends message with info from stack trace. -* It tries to guess what class called {@link Configuration} and -* adds relevant info from the stack trace about it to the message. -*/ -public String getMessage() { - - StackTraceElement[] stack = getStackTrace(); - - // Search the element that invoked Configuration - // It's the first whose class is different from Configuration - int pos; - for (pos=0; pos < stack.length; pos++) - { - if (!stack[pos].getClassName().equals( - Configuration.class.getName())) - break; - } - - return super.getMessage()+"\nAt "+ - getStackTrace()[pos].getClassName()+"."+ - getStackTrace()[pos].getMethodName()+":"+ - getStackTrace()[pos].getLineNumber(); -} - -/** - * Returns the exception message without stack trace information - */ -public String getShortMessage() -{ - return super.getMessage(); -} - -} - diff --git a/contrib/psg/src/peersim/config/MissingParameterException.java b/contrib/psg/src/peersim/config/MissingParameterException.java deleted file mode 100644 index 58b85cde60..0000000000 --- a/contrib/psg/src/peersim/config/MissingParameterException.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -/** -* Exception thrown to indicate that a -* configuration property is not defined. It is thrown exclusively by -* {@link Configuration}, since it is the only class that has access to the -* set of defined properties. - */ -public class MissingParameterException extends RuntimeException { - -// ================== initialization ===================================== -// ======================================================================= - -MissingParameterException(String name) { - - super("Parameter \"" + name + "\" not found."); -} - -MissingParameterException(String name, String motivation) { - - super("Parameter \"" + name + "\" not found " + motivation); -} - -// ================== methods ============================================ -// ======================================================================= - -/** -* Extends message with info from stack trace. -* It tries to guess what class called {@link Configuration} and -* adds relevant info from the stack trace about it to the message. -*/ -public String getMessage() { - - StackTraceElement[] stack = getStackTrace(); - - // Search the element that invoked Configuration - // It's the first whose class is different from Configuration - int pos; - for (pos=0; pos < stack.length; pos++) { - if (!stack[pos].getClassName().equals( - Configuration.class.getName())) - break; - } - - return super.getMessage()+"\nAt "+ - getStackTrace()[pos].getClassName()+"."+ - getStackTrace()[pos].getMethodName()+":"+ - getStackTrace()[pos].getLineNumber(); -} - -/** - * Returns the exception message without stack trace information - */ -public String getShortMessage() -{ - return super.getMessage(); -} - -} diff --git a/contrib/psg/src/peersim/config/NullPrintStream.java b/contrib/psg/src/peersim/config/NullPrintStream.java deleted file mode 100644 index 612492265d..0000000000 --- a/contrib/psg/src/peersim/config/NullPrintStream.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -import java.io.*; - -/** - * A subclass of PrintStream whose methods ignore the content - * being written. - * - * @author Alberto Montresor - * @version $Revision: 1.1 $ - */ -public class NullPrintStream extends PrintStream -{ - -/** - * Creates a null print stream that does not print anything. - */ -public NullPrintStream() -{ - super(System.out); -} - -/** - * This methods does not print anything. - */ -public synchronized void write(byte[] b, int off, int len) -{ -} - -/** - * This methods does not print anything. - */ -public synchronized void write(int b) -{ -} - -/** - * This methods does not print anything. - */ -private void printLine() -{ -} - -} diff --git a/contrib/psg/src/peersim/config/Operators.java b/contrib/psg/src/peersim/config/Operators.java deleted file mode 100644 index 1d5d523f31..0000000000 --- a/contrib/psg/src/peersim/config/Operators.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -package peersim.config; -import java.math.*; -import org.lsmp.djep.groupJep.groups.*; -import org.lsmp.djep.groupJep.interfaces.*; - -/** - * This class implements the Group interface of JEP, - * enabling the configuration system to read integers with arbitrary - * length. - */ -public class Operators extends Group implements IntegralDomainI,HasDivI, - OrderedSetI,HasModI,HasPowerI { - - - /** - * Operations on the reals (Implemented as BigInteger). - */ - public Operators() { - } - - public Number getZERO() { - return BigInteger.ZERO; - } - - public Number getONE() { - return BigInteger.ONE; - } - - public Number getInverse(Number num) { - if (num instanceof BigInteger) { - BigInteger a = (BigInteger) num; - return a.negate(); - } else { - return -num.doubleValue(); - } - } - - public Number add(Number num1, Number num2) { - if (num1 instanceof Double || num2 instanceof Double) { - // One is double - return num1.doubleValue() + num2.doubleValue(); - } else { - // Both integer - BigInteger a = (BigInteger) num1; - BigInteger b = (BigInteger) num2; - return a.add(b); - } - } - - public Number sub(Number num1, Number num2) { - if (num1 instanceof Double || num2 instanceof Double) { - // One is double - return num1.doubleValue() - num2.doubleValue(); - } else { - // Both integer - BigInteger a = (BigInteger) num1; - BigInteger b = (BigInteger) num2; - return a.subtract(b); - } - } - - public Number mul(Number num1, Number num2) { - if (num1 instanceof Double || num2 instanceof Double) { - // One is double - return num1.doubleValue() * num2.doubleValue(); - } else { - // Both integer - BigInteger a = (BigInteger) num1; - BigInteger b = (BigInteger) num2; - return a.multiply(b); - } - } - - public Number div(Number num1, Number num2) { - if (num1 instanceof Double || num2 instanceof Double) { - // One is double - return num1.doubleValue() / num2.doubleValue(); - } else { - // Both integer - BigInteger a = (BigInteger) num1; - BigInteger b = (BigInteger) num2; - return a.divide(b); - } - } - - - public Number mod(Number num1, Number num2) { - if (num1 instanceof Double || num2 instanceof Double) { - // One is double - return num1.doubleValue() % num2.doubleValue(); - } else { - // Both integer - BigInteger a = (BigInteger) num1; - BigInteger b = (BigInteger) num2; - return a.remainder(b); - } - } - - public Number pow(Number num1, Number num2) { - if (num1 instanceof Double || num2 instanceof Double) { - // One is double - return Math.pow(num1.doubleValue(), num2.doubleValue()); - } else { - // Both integer - BigInteger a = (BigInteger) num1; - BigInteger b = (BigInteger) num2; - return a.pow(b.intValue()); - } - } - - public boolean equals(Number num1, Number num2) { - if (num1 instanceof Double || num2 instanceof Double) { - // One is double - return num1.doubleValue() == num2.doubleValue(); - } else { - // Both integer - BigInteger a = (BigInteger) num1; - BigInteger b = (BigInteger) num2; - return a.equals(b); - } - } - - public int compare(Number num1,Number num2) { - if (num1 instanceof Double || num2 instanceof Double) { - // One is double - double n1 = num1.doubleValue(); - double n2 = num2.doubleValue(); - return (n1 < n2 ? -1 : (n1 == n2 ? 0 : 1)); - } else { - // Both integer - BigInteger a = (BigInteger) num1; - BigInteger b = (BigInteger) num2; - return a.compareTo(b); - } - } - - public Number valueOf(String str) { - try { - return new BigInteger(str); - } catch (NumberFormatException e) { - return new Double(str); - } - } - - public String toString() { return ""; } -} diff --git a/contrib/psg/src/peersim/config/ParsedProperties.java b/contrib/psg/src/peersim/config/ParsedProperties.java deleted file mode 100644 index 9a58e4114d..0000000000 --- a/contrib/psg/src/peersim/config/ParsedProperties.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.config; - -import java.io.*; -import java.util.*; - -/** -* Extends the class {@link ConfigProperties} with basic parsing capabilities. -* @see #load -*/ -public class ParsedProperties extends ConfigProperties { - -//================= variables ====================================== -//================================================================== - -// ================= initialization ================================= -// ================================================================== - -/** -* Calls super constructor. -* @see ConfigProperties#ConfigProperties(String[]) -*/ -public ParsedProperties( String[] pars ) { - - super( pars ); -} - -// ------------------------------------------------------------------ - -/** -* Calls super constructor. -* @see ConfigProperties#ConfigProperties(String) -*/ -public ParsedProperties( String filename ) throws IOException { - - super( filename ); -} - - -// =========== Public methods ======================================== -// =================================================================== - - -/** -* Loads given file. It works exactly as Properties.load -* with a file input stream to the given file, except that the file is parsed -* the following way allowing to compress some property names -* using { and }. - - When a bracket is present, it must - be the only non-space element of a line. The last property defined - before the opening bracket define the prefix that is added to all the - properties defined included between brackets. - In other words, a construct like this: -

-  control.degree GraphObserver 
-  {
-    protocol newscast
-    undir
-  }
-  
- is equivalent to the definition of these three properties: -
-  control.degree GraphObserver 
-  control.degree.protocol newscast
-  control.degree.undir
-  
- - Nested brackets are possible. The rule of the last property before - the opening bracket applies also to the inside brackets, with - the prefix being the complete property definition (so, including - the prefix observed before). Example: -
-	control.1 DynamicNetwork
-	{
-	  add CRASH
-	  substitute
-	  init.0 WireKOut 
-	  {
-	    degree DEGREE
-	    protocol 0
-	  }
-	}
-  
- defines the following properties: -
-	control.1 DynamicNetwork
-	control.1.add CRASH
-	control.1.substitute
-	control.1.init.0 WireKOut 
-	control.1.init.0.degree DEGREE
-	control.1.init.0.protocol 0
-  
- -

- Know limitations: - The parsing mechanism is very simple; no complex error messages - are provided. In case of missing closing brackets, the method - will stop reporting the number of missing brackets. Additional - closing brackets (i.e., missing opening brackets) produce an - error messages reporting the line where the closing bracket - is present. Misplaced brackets (included in lines that - contains other characters) are ignored, thus may indirectly produce - the previous error messages. -*/ -public void load( String fileName ) throws IOException { - - /* This set is used to store prefixes that have been associated - * to brackets blocks. If a prefix is inserted twice, this means - * that there are two blocks referring to the same prefix - - * which may be caused by a commented prefix in the config - * file, something like this: - * - * prefix1 - * { - * property 1 - * } - * #prefix2 - * { - * property 2 - * } - * - */ - Set prefixes = new HashSet(); - - BufferedReader f = - new BufferedReader(new FileReader( fileName )); - int lines = 0; - parseStream(f, "", 0, lines, prefixes); - - f.close(); -} - -// -------------------------------------------------------------------- - -private int parseStream(BufferedReader f, String prefix, int pars, - int lines, Set prefixes) -throws IOException { - - if (prefix.equals(".")) { - System.err.println("Error at line " + lines + ": bracket block not " + - "associated with any configuration entry"); - System.exit(1); - } - if (prefixes.contains(prefix)) { - System.err.println("Error at line " + lines + ": multiple bracket " + - "blocks referring to the same configuration entry " + prefix); - System.exit(1); - } else { - prefixes.add(prefix); - } - - boolean complete = true; - String part; - String line = ""; - String last = ""; - while ((part = f.readLine()) != null) - { - lines++; - - // Reset line - if (complete) line = ""; - - // Check if the line is a comment line - // If so, remove the comment - int index = part.indexOf('#'); - if (index >= 0) - { - part = part.substring(0, index); - } - - // Check if the line is empty - part = part.trim(); - if ("".equals(part)) continue; - - complete = (part.charAt(part.length()-1) != '\\'); - if (!complete) - { - line = line + part.substring(0, part.length()-2) + " "; - continue; - } - - // Complete the line - line = line + part; - if (line.equals("{")) - { - lines = parseStream(f, last+".", pars+1, lines, prefixes); - } - else if (line.equals("}")) - { - if (pars == 0) - { - System.err.println( - "Error: Additional } at line " + lines + - " when parsing the configuration file"); - System.exit(1); - } - return lines; - } - else - { - // Search the first token - String[] tokens = line.split("[\\s:=]+", 2); - if (tokens.length == 1) - { - setProperty(prefix+tokens[0], ""); - } - else - { - setProperty(prefix+tokens[0], tokens[1]); - } - last = prefix + tokens[0]; - } - } - if (pars == 1) - { - System.err.println("Error: One closing bracket ('}') is missing"); - System.exit(1); - } - else if (pars > 1) - { - System.err.println("Error: " + pars+" closing brackets ('}') are missing"); - System.exit(1); - } - return lines; -} - -// -------------------------------------------------------------------- - -/* -public static void main(String[] args) -{ - java.util.Properties prop = new ParsedProperties(args); -} -*/ -} - diff --git a/contrib/psg/src/peersim/core/Cleanable.java b/contrib/psg/src/peersim/core/Cleanable.java deleted file mode 100644 index ac14f2163f..0000000000 --- a/contrib/psg/src/peersim/core/Cleanable.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -/** - * This interface must be implemented by protocols that need to release - * some references when the fail state of their host node is set to - * {@link Fallible#DEAD}. Recall that this fail state means that the node - * will never get back online. However, other nodes and protocols might - * still have references to these dead nodes and protocols, and this fact - * is not always a bug. So implementing this interface allows for removing - * stuff that we know is no longer necessary. Especially for linkable - * protocols in the presence of churn, this is essential: they typically - * have to release their links to other nodes to prevent the formation of - * trees of removed nodes with a live reference to the root. - */ -public interface Cleanable -{ - -/** - * Performs cleanup when removed from the network. This is called by the - * host node when its fail state is set to {@link Fallible#DEAD}. - * It is very important that after calling this method, NONE of the methods - * of the implementing object are guaranteed to work any longer. - * They might throw arbitrary exceptions, etc. The idea is that after - * calling this, typically no one should access this object. - * However, as a recommendation, at least toString should be guaranteed to - * execute normally, to aid debugging. - */ -public void onKill(); - -} diff --git a/contrib/psg/src/peersim/core/CommonState.java b/contrib/psg/src/peersim/core/CommonState.java deleted file mode 100644 index 93b6e21840..0000000000 --- a/contrib/psg/src/peersim/core/CommonState.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -import org.simgrid.msg.Msg; - -import peersim.Simulator; -import peersim.config.*; -import peersim.util.*; -import psgsim.PSGPlatform; - -/** - * This is the common state of the simulation all objects see. - * Static singleton. One of its purposes is - * simplification of parameter structures and increasing efficiency by putting - * state information here instead of passing parameters. - *

- * The set methods should not be used by applications, - * they are for system - * components. Use them only if you know exactly what you are doing, e.g. - * if you are so advanced that you can write your own simulation engine. - * Ideally, they should not be visible, but due to the lack of more - * flexibility in java access rights, we are forced to make them public. - */ -public class CommonState -{ - -//======================= constants =============================== -//================================================================= - -/** -* Constant that can be used as a value of simulation phase. -* It means that the simulation has finished. -* @see #getPhase -*/ -public static final int POST_SIMULATION = 1; - -/** -* Constant that can be used as a value of simulation phase. -* It means that the simulation phase information has not been set (unknown). -* @see #getPhase -*/ -public static final int PHASE_UNKNOWN = 0; - -// ======================= fields ================================== -// ================================================================= - -/** - * Current time. Note that this value is simulator independent, all simulation - * models have a notion related to time. For example, in the cycle based model, - * the cycle id gives time, while in even driven simulations there is a more - * realistic notion of time. - */ -private static long time = 0; - -/** - * The maximal value {@link #time} can ever take. - */ -private static long endtime = -1; - -/** - * Number of used bits in the long representation of time, calculated - * based on the endtime. - */ -private static int toshift = -1; - -/** - * Information about where exactly the simulation is. - */ -private static int phase = PHASE_UNKNOWN; - -/** - * The current pid. - */ -private static int pid; - -/** - * The current node. - */ -private static Node node; - -/** -* This source of randomness should be used by all components. -* This field is public because it doesn't matter if it changes -* during an experiment (although it shouldn't) until no other sources of -* randomness are used within the system. Besides, we can save the cost -* of calling a wrapper method, which is important because this is needed -* very often. -*/ -public static ExtendedRandom r = null; - - -// ======================== initialization ========================= -// ================================================================= - -/** -* Configuration parameter used to define which random generator -* class should be used. If not specified, the default implementation -* {@link ExtendedRandom} is used. User-specified random generators -* must extend class {@link ExtendedRandom}. -* @config -*/ -public static final String PAR_RANDOM = "random"; - -/** -* Configuration parameter used to initialize the random seed. -* If it is not specified the current time is used. -* @config -*/ -public static final String PAR_SEED = "random.seed"; - - -/** -* Initializes the field {@link r} according to the configuration. -* Assumes that the configuration is already -* loaded. -*/ -static { - - long seed = - Configuration.getLong(PAR_SEED,System.currentTimeMillis()); - initializeRandom(seed); -} - - -/** Does nothing. To avoid construction but allow extension. */ -protected CommonState() {} - -// ======================= methods ================================= -// ================================================================= - - -/** - * Returns current time. In event-driven simulations, returns the current - * time (a long-value). - * In cycle-driven simulations, returns the current cycle (a long that - * can safely be cast into an integer). - */ -public static long getTime() -{ - /* if the engine simulator used is PSG (simId=2 */ - if(Simulator.getSimID()==2) - return (long) PSGPlatform.getTime(); - else - return time; -} - -//----------------------------------------------------------------- - -/** - * Returns current time in integer format. The purpose is to enhance the - * performance of protocols (ints are smaller and faster) when absolute - * precision is not required. It assumes that endtime has been set via - * {@link #setEndTime} by the simulation engine. It uses the endtime for - * the optimal mapping to get the maximal precision. - * In particular, in the cycle - * based model, time is the same as cycle which can be safely cast into - * integer, so no precision is lost. - */ -public static int getIntTime() -{ - return (int)(time>>toshift); -} - -//----------------------------------------------------------------- - -/** - * Sets the current time. - */ -public static void setTime(long t) -{ - time = t; -} - -//----------------------------------------------------------------- - -/** - * Returns endtime. - * It is the maximal value {@link #getTime} ever returns. If it's negative, it - * means the endtime is not known. - */ -public static long getEndTime() -{ - return endtime; -} - -//----------------------------------------------------------------- - -/** - * Sets the endtime. - */ -public static void setEndTime(long t) -{ - if( endtime >= 0 ) - throw new RuntimeException("You can set endtime only once"); - if( t < 0 ) - throw new RuntimeException("No negative values are allowed"); - - endtime = t; - toshift = 32-Long.numberOfLeadingZeros(t); - if( toshift<0 ) toshift = 0; -} - -//----------------------------------------------------------------- - -/** - * Returns the simulation phase. Currently the following phases are - * understood. - *

    - *
  • {@link #PHASE_UNKNOWN} phase is unknown
  • - *
  • {@link #POST_SIMULATION} the simulation is completed
  • - *
- */ -public static int getPhase() -{ - return phase; -} - -// ----------------------------------------------------------------- - -public static void setPhase(int p) -{ - phase = p; -} - -// ----------------------------------------------------------------- - -/** -* Returns the current protocol identifier. In other words, control is -* held by the indicated protocol on node {@link #getNode}. -*/ -public static int getPid() -{ - return pid; -} - -//----------------------------------------------------------------- - -/** Sets the current protocol identifier.*/ -public static void setPid(int p) -{ - pid = p; -} - -//----------------------------------------------------------------- - -/** - * Returns the current node. When a protocol is executing, it is the node - * hosting the protocol. - */ -public static Node getNode() -{ - return node; -} - -//----------------------------------------------------------------- - -/** Sets the current node */ -public static void setNode(Node n) -{ - node = n; -} - -//----------------------------------------------------------------- - -public static void initializeRandom(long seed) -{ - if (r == null) { - r = (ExtendedRandom) Configuration.getInstance(PAR_RANDOM, new ExtendedRandom(seed)); - } - r.setSeed(seed); -} - -//----------------------------------------------------------------- - -/* -public static void main(String pars[]) { - - setEndTime(Long.parseLong(pars[0])); - setTime(Long.parseLong(pars[1])); - System.err.println(getTime()+" "+getIntTime()); -} -*/ -} - diff --git a/contrib/psg/src/peersim/core/Control.java b/contrib/psg/src/peersim/core/Control.java deleted file mode 100644 index 7644aa9df0..0000000000 --- a/contrib/psg/src/peersim/core/Control.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -/** - * Generic interface for classes that are responsible for observing or modifying - * the ongoing simulation. It is designed to allow maximal flexibility therefore - * poses virtually no restrictions on the implementation. - */ -public interface Control -{ - -/** - * Performs arbitrary modifications or reports arbitrary information over the - * components. - * @return true if the simulation has to be stopped, false otherwise. - */ -public boolean execute(); - -} diff --git a/contrib/psg/src/peersim/core/Fallible.java b/contrib/psg/src/peersim/core/Fallible.java deleted file mode 100644 index 089cffef62..0000000000 --- a/contrib/psg/src/peersim/core/Fallible.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - - -/** -* Instances of classes implementing this interface -* maintain a fail state, i.e. information about the availability -* of the object. -*/ -public interface Fallible { - - - /** - * Fail state which indicates that the object is operating normally. - */ - public int OK = 0; - - /** - * Fail state indicating that the object is dead and recovery is - * not possible. When this state is set, it is a good idea to make sure - * that the state of the object becomes such that any attempt to - * operate on it causes a visible error of some kind. - */ - public int DEAD = 1; - - /** - * Fail state indicating that the object is not dead, but is temporarily - * not accessible. - */ - public int DOWN = 2; - - /** - * Returns the state of this object. Must be one of the constants - * defined in interface {@link Fallible}. - */ - public int getFailState(); - - /** - * Sets the fails state of this object. Parameter must be one of the - * constants defined in interface {@link Fallible}. - */ - public void setFailState(int failState); - - /** - * Convenience method to check if the node is up and running - * @return must return true if and only if - * getFailState()==OK - */ - public boolean isUp(); -} - - diff --git a/contrib/psg/src/peersim/core/GeneralNode.java b/contrib/psg/src/peersim/core/GeneralNode.java deleted file mode 100644 index 2f2c02eb3c..0000000000 --- a/contrib/psg/src/peersim/core/GeneralNode.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -import peersim.config.*; - -/** -* This is the default {@link Node} class that is used to compose the -* {@link Network}. -*/ -public class GeneralNode implements Node { - - -// ================= fields ======================================== -// ================================================================= - -/** used to generate unique IDs */ -private static long counterID = -1; - -/** -* The protocols on this node. -*/ -protected Protocol[] protocol = null; - -/** -* The current index of this node in the node -* list of the {@link Network}. It can change any time. -* This is necessary to allow -* the implementation of efficient graph algorithms. -*/ -private int index; - -/** -* The fail state of the node. -*/ -protected int failstate = Fallible.OK; - -/** -* The ID of the node. It should be final, however it can't be final because -* clone must be able to set it. -*/ -private long ID; - -// ================ constructor and initialization ================= -// ================================================================= - -/** Used to construct the prototype node. This class currently does not -* have specific configuration parameters and so the parameter -* prefix is not used. It reads the protocol components -* (components that have type {@value peersim.core.Node#PAR_PROT}) from -* the configuration. -*/ -public GeneralNode(String prefix) { - - String[] names = Configuration.getNames(PAR_PROT); - CommonState.setNode(this); - ID=nextID(); - protocol = new Protocol[names.length]; - for (int i=0; i < names.length; i++) { - CommonState.setPid(i); - Protocol p = (Protocol) - Configuration.getInstance(names[i]); - protocol[i] = p; - } -} - - -// ----------------------------------------------------------------- - -public Object clone() { - - GeneralNode result = null; - try { result=(GeneralNode)super.clone(); } - catch( CloneNotSupportedException e ) {} // never happens - result.protocol = new Protocol[protocol.length]; - CommonState.setNode(result); - result.ID=nextID(); - for(int i=0; i(int)getID(). */ -public int hashCode() { return (int)getID(); } - -} - - diff --git a/contrib/psg/src/peersim/core/IdleProtocol.java b/contrib/psg/src/peersim/core/IdleProtocol.java deleted file mode 100644 index dd602d5b6d..0000000000 --- a/contrib/psg/src/peersim/core/IdleProtocol.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -import peersim.config.Configuration; - -/** - * A protocol that stores links. It does nothing apart from that. - * It is useful to model a static link-structure - * (topology). The only function of this protocol is to serve as a source of - * neighborhood information for other protocols. - */ -public class IdleProtocol implements Protocol, Linkable -{ - -// -------------------------------------------------------------------------- -// Parameters -// -------------------------------------------------------------------------- - -/** - * Default init capacity - */ -private static final int DEFAULT_INITIAL_CAPACITY = 10; - -/** - * Initial capacity. Defaults to {@value #DEFAULT_INITIAL_CAPACITY}. - * @config - */ -private static final String PAR_INITCAP = "capacity"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** Neighbors */ -protected Node[] neighbors; - -/** Actual number of neighbors in the array */ -protected int len; - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -public IdleProtocol(String s) -{ - neighbors = new Node[Configuration.getInt(s + "." + PAR_INITCAP, - DEFAULT_INITIAL_CAPACITY)]; - len = 0; -} - -//-------------------------------------------------------------------------- - -public Object clone() -{ - IdleProtocol ip = null; - try { ip = (IdleProtocol) super.clone(); } - catch( CloneNotSupportedException e ) {} // never happens - ip.neighbors = new Node[neighbors.length]; - System.arraycopy(neighbors, 0, ip.neighbors, 0, len); - ip.len = len; - return ip; -} - -// -------------------------------------------------------------------------- -// Methods -// -------------------------------------------------------------------------- - -public boolean contains(Node n) -{ - for (int i = 0; i < len; i++) { - if (neighbors[i] == n) - return true; - } - return false; -} - -// -------------------------------------------------------------------------- - -/** Adds given node if it is not already in the network. There is no limit -* to the number of nodes that can be added. */ -public boolean addNeighbor(Node n) -{ - for (int i = 0; i < len; i++) { - if (neighbors[i] == n) - return false; - } - if (len == neighbors.length) { - Node[] temp = new Node[3 * neighbors.length / 2]; - System.arraycopy(neighbors, 0, temp, 0, neighbors.length); - neighbors = temp; - } - neighbors[len] = n; - len++; - return true; -} - -// -------------------------------------------------------------------------- - -public Node getNeighbor(int i) -{ - return neighbors[i]; -} - -// -------------------------------------------------------------------------- - -public int degree() -{ - return len; -} - -// -------------------------------------------------------------------------- - -public void pack() -{ - if (len == neighbors.length) - return; - Node[] temp = new Node[len]; - System.arraycopy(neighbors, 0, temp, 0, len); - neighbors = temp; -} - -// -------------------------------------------------------------------------- - -public String toString() -{ - if( neighbors == null ) return "DEAD!"; - StringBuffer buffer = new StringBuffer(); - buffer.append("len=" + len + " maxlen=" + neighbors.length + " ["); - for (int i = 0; i < len; ++i) { - buffer.append(neighbors[i].getIndex() + " "); - } - return buffer.append("]").toString(); -} - -// -------------------------------------------------------------------------- - -public void onKill() -{ - neighbors = null; - len = 0; -} - -} diff --git a/contrib/psg/src/peersim/core/Linkable.java b/contrib/psg/src/peersim/core/Linkable.java deleted file mode 100644 index 962b427c26..0000000000 --- a/contrib/psg/src/peersim/core/Linkable.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - - -/** -* Instances of classes implementing this interface can form networks (graphs) -* in the simulator framework. -* The interface is similar to one of a container (containing neighbors), -* only the types of the contained elements have to be {@link Node}. -* The neighbor collection is defined in a random access list style, but -* it must follow the contract of a set too (elements must be unique). -*

-* Also note that there is no possibility to remove elements from the -* neighbor set. This is because removal is usually costly and it does not make -* sense in the context of our applications, -* where this interface is used for 1) initialization and 2) -* providing an interface for other protocols for accessing the neighbor list. -* Protocols that manage links remove, refresh, etc their link set internally -* or through custom methods. -* Therefore it would only put an unnecessary burden on implementors. -*/ -public interface Linkable extends Cleanable { - - - /** - * Returns the size of the neighbor list. - */ - public int degree(); - - /** - * Returns the neighbor with the given index. The contract is that - * listing the elements from index 0 to index degree()-1 should list - * each element exactly once if this object is not modified in the - * meantime. It throws an IndexOutOfBounds exception if i is negative - * or larger than or equal to {@link #degree}. - */ - public Node getNeighbor(int i); - - /** - * Add a neighbor to the current set of neighbors. If neighbor - * is not yet a neighbor but it cannot be added from other reasons, - * this method should not return normally, that is, it must throw - * a runtime exception. - * @return true if the neighbor has been inserted; false if the - * node is already a neighbor of this node - */ - public boolean addNeighbor(Node neighbour); - - /** - * Returns true if the given node is a member of the neighbor set. - */ - public boolean contains(Node neighbor); - - /** - * A possibility for optimization. An implementation should try to - * compress its internal representation. Normally this is called - * by initializers or other components when - * no increase in the expected size of the neighborhood can be - * expected. - */ - public void pack(); -} - diff --git a/contrib/psg/src/peersim/core/MaliciousProtocol.java b/contrib/psg/src/peersim/core/MaliciousProtocol.java deleted file mode 100644 index 26ed74f126..0000000000 --- a/contrib/psg/src/peersim/core/MaliciousProtocol.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -/** - * Tag interface to identify protocols that are malicious. - * - * @author Alberto Montresor - * @version $Revision: 1.2 $ - */ -public interface MaliciousProtocol -extends Protocol -{ -} - diff --git a/contrib/psg/src/peersim/core/ModifiableNode.java b/contrib/psg/src/peersim/core/ModifiableNode.java deleted file mode 100644 index 7ce80a3acd..0000000000 --- a/contrib/psg/src/peersim/core/ModifiableNode.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - - -/** - * This class extends GeneralNode by allowing to modify single - * protocol instances at nodes. - * - * @author Alberto Montresor - * @version $Revision: 1.3 $ - */ -public class ModifiableNode extends GeneralNode -{ - -/** - * Invokes the super constructor. - */ -public ModifiableNode(String prefix) -{ - super(prefix); -} - -/** - * Substitutes the specified protocol at this node. - * - * @param pid protocol identifier - * @param prot the protocol object - */ -public void setProtocol(int pid, Protocol prot) -{ - protocol[pid] = prot; -} - -} diff --git a/contrib/psg/src/peersim/core/Network.java b/contrib/psg/src/peersim/core/Network.java deleted file mode 100644 index da9c54531e..0000000000 --- a/contrib/psg/src/peersim/core/Network.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -import peersim.Simulator; -import peersim.config.Configuration; -import psgsim.PSGDynamicNetwork; - -import java.util.Comparator; -import java.util.Arrays; - -import org.simgrid.msg.HostNotFoundException; -import org.simgrid.msg.MsgException; - -/** - * This class forms the basic framework of all simulations. This is a static - * singleton which is based on the assumption that we will simulate only one - * overlay network at a time. This allows us to reduce memory usage in many - * cases by allowing all the components to directly reach the fields of this - * class without having to store a reference. - *

- * The network is a set of nodes implemented via an array list for the sake of - * efficiency. Each node has an array of protocols. The protocols within a node - * can interact directly as defined by their implementation, and can be imagined - * as processes running in a common local environment (i.e. the node). This - * class is called a "network" because, although it is only a set of nodes, in - * most simulations there is at least one {@link Linkable} protocol that defines - * connections between nodes. In fact, such a {@link Linkable} protocol layer - * can be accessed through a {@link peersim.graph.Graph} view using - * {@link OverlayGraph}. - */ -public class Network { - - // ========================= fields ================================= - // ================================================================== - - /** - * This config property defines the node class to be used. If not set, then - * {@link GeneralNode} will be used. - * - * @config - */ - private static final String PAR_NODE = "network.node"; - - /** - * This config property defines the initial capacity of the overlay network. - * If not set then the value of {@value #PAR_SIZE} will be used. The main - * purpose of this parameter is that it allows for optimization. In the case - * of scenarios when the network needs to grow, setting this to the maximal - * expected size of the network avoids reallocation of memory during the - * growth of the network. - * - * @see #getCapacity - * @config - */ - private static final String PAR_MAXSIZE = "network.initialCapacity"; - - /** - * This config property defines the initial size of the overlay network. - * This property is required. - * - * @config - */ - private static final String PAR_SIZE = "network.size"; - - /** - * The node array. This is not a private array which is not nice but - * efficiency has the highest priority here. The main purpose is to allow - * the package quick reading of the contents in a maximally flexible way. - * Nevertheless, methods of this class should be used instead of the array - * when modifying the contents. Because this array is not private, it is - * necessary to know that the actual node set is only the first - * {@link #size()} items of the array. - */ - static Node[] node = null; - - /** - * Actual size of the network. - */ - private static int len; - - /** - * The prototype node which is used to populate the simulation via cloning. - * After all the nodes have been cloned, {@link Control} components can be - * applied to perform any further initialization. - */ - public static Node prototype = null; - - // ====================== initialization =========================== - // ================================================================= - - /** - * Reads configuration parameters, constructs the prototype node, and - * populates the network by cloning the prototype. - */ - public static void reset() { - - if (prototype != null) { - // not first experiment - while (len > 0) - remove(); // this is to call onKill on all nodes - prototype = null; - node = null; - } - - len = Configuration.getInt(PAR_SIZE); - int maxlen = Configuration.getInt(PAR_MAXSIZE, len); - if (maxlen < len) - throw new IllegalArgumentException(PAR_MAXSIZE + " is less than " - + PAR_SIZE); - - node = new Node[maxlen]; - - // creating prototype node - Node tmp = null; - if (!Configuration.contains(PAR_NODE)) { - System.err.println("Network: no node defined, using GeneralNode"); - tmp = new GeneralNode(""); - } else { - tmp = (Node) Configuration.getInstance(PAR_NODE); - } - prototype = tmp; - prototype.setIndex(-1); - - // cloning the nodes - if (len > 0) { - for (int i = 0; i < len; ++i) { - node[i] = (Node) prototype.clone(); - node[i].setIndex(i); - } - } - } - - /** Disable instance construction */ - private Network() { - } - - // =============== public methods =================================== - // ================================================================== - - /** Number of nodes currently in the network */ - public static int size() { - return len; - } - - // ------------------------------------------------------------------ - - /** - * Sets the capacity of the internal array storing the nodes. The nodes will - * remain the same in the same order. If the new capacity is less than the - * old size of the node list, than the end of the list is cut. The nodes - * that get removed via this cutting are removed through {@link #remove()}. - */ - public static void setCapacity(int newSize) { - - if (node == null || newSize != node.length) { - for (int i = newSize; i < len; ++i) - remove(); - Node[] newnodes = new Node[newSize]; - final int l = Math.min(node.length, newSize); - System.arraycopy(node, 0, newnodes, 0, l); - node = newnodes; - if (len > newSize) - len = newSize; - } - } - - // ------------------------------------------------------------------ - - /** - * Returns the maximal number of nodes that can be stored without - * reallocating the underlying array to increase capacity. - */ - public static int getCapacity() { - return node.length; - } - - // ------------------------------------------------------------------ - - /** - * The node will be appended to the end of the list. If necessary, the - * capacity of the internal array is increased. - */ - public static void add(Node n) { - if (len == node.length) - setCapacity(3 * node.length / 2 + 1); - node[len] = n; - n.setIndex(len); - len++; - if (Simulator.getSimID() == 2) - try { - PSGDynamicNetwork.add(n); - } catch (HostNotFoundException e) { - System.err.println("Host not found in platform file"); - } - System.err.println("node " + n.getID() + " with index " + n.getIndex() - + " was added at time " + CommonState.getTime()); - } - - // ------------------------------------------------------------------ - - /** - * Returns node with the given index. Note that the same node will normally - * have a different index in different times. This can be used as a random - * access iterator. This method does not perform range checks to increase - * efficiency. The maximal valid index is {@link #size()}. - */ - public static Node get(int index) { - return node[index]; - } - - // ------------------------------------------------------------------ - - /** - * The node at the end of the list is removed. Returns the removed node. It - * also sets the fail state of the node to {@link Fallible#DEAD}. - */ - public static Node remove() { - Node n = node[len - 1]; // if len was zero this throws and exception - node[len - 1] = null; - len--; - System.err.println("node " + n.getID() + " with index " + n.getIndex() - + " was removed at time " + CommonState.getTime()); - n.setFailState(Fallible.DEAD); - if (Simulator.getSimID() == 2) - PSGDynamicNetwork.remove(n); - return n; - } - - // ------------------------------------------------------------------ - - /** - * The node with the given index is removed. Returns the removed node. It - * also sets the fail state of the node to {@link Fallible#DEAD}. - *

- * Look out: the index of the other nodes will not change (the right hand - * side of the list is not shifted to the left) except that of the last - * node. Only the last node is moved to the given position and will get - * index i. - */ - public static Node remove(int i) { - - if (i < 0 || i >= len) - throw new IndexOutOfBoundsException("" + i); - swap(i, len - 1); - return remove(); - } - - // ------------------------------------------------------------------ - - /** - * Swaps the two nodes at the given indexes. - */ - public static void swap(int i, int j) { - - Node n = node[i]; - node[i] = node[j]; - node[j] = n; - node[j].setIndex(j); - node[i].setIndex(i); - } - - // ------------------------------------------------------------------ - - /** - * Shuffles the node array. The index of each node is updated accordingly. - */ - public static void shuffle() { - - for (int i = len; i > 1; i--) - swap(i - 1, CommonState.r.nextInt(i)); - - } - - // ------------------------------------------------------------------ - - /** - * Sorts the node array. The index of each node is updated accordingly. - * - * @param c - * The comparator to be used for sorting the nodes. If null, the - * natural order of the nodes is used. - */ - public static void sort(Comparator c) { - - Arrays.sort(node, 0, len, c); - for (int i = 0; i < len; i++) - node[i].setIndex(i); - } - - // ------------------------------------------------------------------ - - public static void test() { - - System.err.println("number of nodes = " + len); - System.err.println("capacity (max number of nodes) = " + node.length); - for (int i = 0; i < len; ++i) { - System.err.println("node[" + i + "]"); - System.err.println(node[i].toString()); - } - - if (prototype == null) - return; - for (int i = 0; i < prototype.protocolSize(); ++i) { - if (prototype.getProtocol(i) instanceof Linkable) - peersim.graph.GraphIO.writeUCINET_DL(new OverlayGraph(i), - System.err); - } - } - -} diff --git a/contrib/psg/src/peersim/core/Node.java b/contrib/psg/src/peersim/core/Node.java deleted file mode 100644 index a64e3a23b9..0000000000 --- a/contrib/psg/src/peersim/core/Node.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -/** - * Class that represents one node with a network address. An {@link Network} is - * made of a set of nodes. The functionality of this class is thin: it must be - * able to represent failure states and store a list of protocols. It is the - * protocols that do the interesting job. - */ -public interface Node extends Fallible, Cloneable -{ - -/** - * Prefix of the parameters that defines protocols. - * @config - */ -public static final String PAR_PROT = "protocol"; - -/** - * Returns the i-th protocol in this node. If i - * is not a valid protocol id - * (negative or larger than or equal to the number of protocols), then it throws - * IndexOutOfBoundsException. - */ -public Protocol getProtocol(int i); - -/** - * Returns the number of protocols included in this node. - */ -public int protocolSize(); - -/** - * Sets the index of this node in the internal representation of the node list. - * Applications should not use this method. It is defined as public simply - * because it is not possible to define it otherwise. - * Using this method will result in - * undefined behavior. It is provided for the core system. - */ -public void setIndex(int index); - -/** - * Returns the index of this node. It is such that - * Network.get(n.getIndex()) returns n. This index can - * change during a simulation, it is not a fixed id. If you need that, use - * {@link #getID}. - * @see Network#get - */ -public int getIndex(); - -/** -* Returns the unique ID of the node. It is guaranteed that the ID is unique -* during the entire simulation, that is, there will be no different Node -* objects with the same ID in the system during one invocation of the JVM. -* Preferably nodes -* should implement hashCode() based on this ID. -*/ -public long getID(); - -/** - * Clones the node. It is defined as part of the interface - * to change the access right to public and to get rid of the - * throws clause. - */ -public Object clone(); - -} diff --git a/contrib/psg/src/peersim/core/OracleIdleProtocol.java b/contrib/psg/src/peersim/core/OracleIdleProtocol.java deleted file mode 100644 index 4d1896ff15..0000000000 --- a/contrib/psg/src/peersim/core/OracleIdleProtocol.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -/** -* A protocol that does nothing but knows everything. -* It provides an interface which models a protocol that knows all nodes -* in the network, i.e. the neighborhood set of this protocol is always the -* whole node set. this protocol is also extremely cheap, in fact it -* has no data fields. -*/ -public final class OracleIdleProtocol implements Protocol, Linkable { - -// =================== initialization, creation ====================== -// =================================================================== - - -/** Does nothing */ -public OracleIdleProtocol(String prefix) {} - -// -------------------------------------------------------------------- - -/** Returns this to maximize memory saving. It contains no fields.*/ -public Object clone() { return this; } - - -// ===================== public methods =============================== -// ==================================================================== - - -/** This is an expensive operation, should not be used at all. -* It returns false only if the given node is not in the current network. -*/ -public boolean contains(Node n) { - - final int len = Network.size(); - for (int i=0; i < len; i++) - { - if (Network.node[i] == n) - return true; - } - return false; -} - -// -------------------------------------------------------------------- - -/** Unsupported operation */ -public boolean addNeighbor(Node n) { - - throw new UnsupportedOperationException(); -} - -// -------------------------------------------------------------------- - -/** -* The neighborhood contains the node itself, ie it contains the loop -* edge. -*/ -public Node getNeighbor(int i) { - - return Network.node[i]; -} - -// -------------------------------------------------------------------- - -public int degree() { - - return Network.size(); -} - -// -------------------------------------------------------------------- - -public void pack() {} - -// -------------------------------------------------------------------- - -public void onKill() {} - -// -------------------------------------------------------------------- - -public String toString() { - - return degree()+" [all the nodes of the overlay network]"; -} - -} - diff --git a/contrib/psg/src/peersim/core/OverlayGraph.java b/contrib/psg/src/peersim/core/OverlayGraph.java deleted file mode 100644 index 000945917c..0000000000 --- a/contrib/psg/src/peersim/core/OverlayGraph.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.core; - -import peersim.graph.Graph; -import java.util.Collection; -import java.util.ArrayList; -import java.util.Collections; - -/** -* This class is an adaptor which makes a {@link Linkable} protocol layer -* look like a graph. It is useful because it allows the application of many -* graph algorithms and graph topology initialization methods. -* If the overlay network changes after creating this object, the changes -* will be reflected. However, if the nodes are reshuffled (see -* {@link Network#shuffle}), or if the node list changes (addition/removal), -* then the behaviour becomes unspecified. -* -* The indices of nodes are from 0 to Network.size()-1. -* -* The fail state of nodes has an effect on the graph: all nodes are included -* but edges are included only if both ends are up. This expresses the fact -* that this graph is in fact defined by the "can communicate with" relation. -*/ -public class OverlayGraph implements Graph { - - -// ====================== fields ================================ -// ============================================================== - -/** -* The protocol ID that selects the Linkable protocol to convert to a graph. -*/ -public final int protocolID; - -/** -* Tells if the graph should be wired in an undirected way. -* Method {@link #directed} returns true always, this affects only -* method {@link #setEdge}: if false, then the opposite edge is set too. -*/ -public final boolean wireDirected; - -// ====================== public constructors =================== -// ============================================================== - -/** -* @param protocolID The protocol on which this adaptor is supposed -* to operate. -*/ -public OverlayGraph( int protocolID ) { - - this.protocolID = protocolID; - wireDirected = true; -} - -// -------------------------------------------------------------- - -/** -* @param protocolID The protocol on which this adaptor is supposed -* to operate. -* @param wireDirected specifies if {@link #setEdge} would wire the -* opposite edge too. -*/ -public OverlayGraph( int protocolID, boolean wireDirected ) { - - this.protocolID = protocolID; - this.wireDirected = wireDirected; -} - - -// ======================= Graph implementations ================ -// ============================================================== - - -public boolean isEdge(int i, int j) { - - return - ((Linkable)Network.node[i].getProtocol(protocolID) - ).contains(Network.node[j]) && - Network.node[j].isUp() && - Network.node[i].isUp(); -} - -// --------------------------------------------------------------- - -/** -* Returns those neighbors that are up. If node i is not up, it returns -* an empty list. -*/ -public Collection getNeighbours(int i) { - - Linkable lble=(Linkable)Network.node[i].getProtocol(protocolID); - ArrayList al = new ArrayList(lble.degree()); - if( Network.node[i].isUp() ) - { - for(int j=0; jNetwork.node[i] */ -public Object getNode(int i) { return Network.node[i]; } - -// --------------------------------------------------------------- - -/** -* Returns null always -*/ -public Object getEdge(int i, int j) { return null; } - -// --------------------------------------------------------------- - -/** Returns Network.size() */ -public int size() { return Network.size(); } - -// -------------------------------------------------------------------- - -/** Returns always true */ -public boolean directed() { return true; } - -// -------------------------------------------------------------------- - -/** -* Sets given edge. -* In some cases this behaves strangely. Namely, when node i or j is not up, -* but is not dead (e.g. it can be down temporarily). -* In such situations the relevant link is made, but afterwards -* getEdge(i,j) will NOT return true, only when the fail state has changed back -* to OK. -* -*

Conceptually one can think of it as a successful operation which is -* immediately overruled by the dynamics of the underlying overlay network. -* Let's not forget that this class is an adaptor only. -* -*

-* The behaviour of this method is affected by parameter {@link #wireDirected}. -* If it is false, then the opposite edge is set too. -*/ -public boolean setEdge( int i, int j ) { -// XXX slightly unintuitive behavior but makes sense when understood - - if( !wireDirected ) - ((Linkable)Network.node[j].getProtocol(protocolID) - ).addNeighbor(Network.node[i]); - - - return - ((Linkable)Network.node[i].getProtocol(protocolID) - ).addNeighbor(Network.node[j]); -} - -// --------------------------------------------------------------- - -/** Not supported */ -public boolean clearEdge( int i, int j ) { - - throw new UnsupportedOperationException(); -} - -// --------------------------------------------------------------- - -/** -* Returns number of neighbors that are up. If node i is down, returns 0. -*/ -public int degree(int i) { - - if( !Network.node[i].isUp() ) return 0; - Linkable lble=(Linkable)Network.node[i].getProtocol(protocolID); - int numNeighbours = 0; - for(int j=0; jIn this simple implementation the valid times will be -* from, from+step, from+2*step, etc, -* where the last element is strictly less than until. -* Alternatively, if at is defined, then the schedule will be a single -* time point. If FINAL is -* defined, it is also added to the set of active time points. -* It refers to the time after the simulation has finished (see -* {@link CommonState#getPhase}). -*/ -public class Scheduler { - - -// ========================= fields ================================= -// ================================================================== - - -/** -* Defaults to 1. -* @config -*/ -private static final String PAR_STEP = "step"; - -/** -* Defaults to -1. That is, defaults to be ineffective. -* @config -*/ -private static final String PAR_AT = "at"; - - -/** -* Defaults to 0. -* @config -*/ -private static final String PAR_FROM = "from"; - -/** -* Defaults to Long.MAX_VALUE. -* @config -*/ -private static final String PAR_UNTIL = "until"; - -/** -* Defines if component is active after the simulation has finished. -* Note that the exact time the simulation finishes is not know in advance -* because other components can stop the simulation at any time. -* By default not set. -* @see CommonState#getPhase -* @config -*/ -private static final String PAR_FINAL = "FINAL"; - -public final long step; - -public final long from; - -public final long until; - -public final boolean fin; - -/** The next scheduled time point.*/ -protected long next = -1; - -// ==================== initialization ============================== -// ================================================================== - - -/** Reads configuration parameters from the component defined by -* prefix. {@value #PAR_STEP} defaults to 1. -*/ -public Scheduler(String prefix) { - - this(prefix, true); -} - -// ------------------------------------------------------------------ - -/** Reads configuration parameters from the component defined by -* prefix. If useDefault is false, then at least parameter -* {@value #PAR_STEP} must be explicitly defined. Otherwise {@value #PAR_STEP} -* defaults to 1. -*/ -public Scheduler(String prefix, boolean useDefault) -{ - if (Configuration.contains(prefix+"."+PAR_AT)) { - // FROM, UNTIL, and STEP should *not* be defined - if (Configuration.contains(prefix+"."+PAR_FROM) || - Configuration.contains(prefix+"."+PAR_UNTIL) || - Configuration.contains(prefix+"."+PAR_STEP)) - throw new IllegalParameterException(prefix, - "Cannot use \""+PAR_AT+"\" together with \"" - +PAR_FROM+"\", \""+PAR_UNTIL+"\", or \""+ - PAR_STEP+"\""); - - from = Configuration.getLong(prefix+"."+PAR_AT); - until = from+1; - step = 1; - } else { - if (useDefault) - step = Configuration.getLong(prefix+"."+PAR_STEP,1); - else - step = Configuration.getLong(prefix+"."+PAR_STEP); - if( step < 1 ) - throw new IllegalParameterException(prefix, - "\""+PAR_STEP+"\" must be >= 1"); - - from = Configuration.getLong(prefix+"."+PAR_FROM,0); - until = Configuration.getLong(prefix+"."+PAR_UNTIL,Long.MAX_VALUE); - } - - if( from < until ) next = from; - else next = -1; - - fin = Configuration.contains(prefix+"."+PAR_FINAL); -} - - -// ===================== public methods ============================== -// =================================================================== - -/** true if given time point is covered by this scheduler */ -public boolean active(long time) { - - if( time < from || time >= until ) return false; - return (time - from)%step == 0; -} - -// ------------------------------------------------------------------- - -/** true if current time point is covered by this scheduler */ -public boolean active() { - - return active( CommonState.getTime() ); -} - -//------------------------------------------------------------------- - -/** -* Returns the next time point. If the returned value is negative, there are -* no more time points. As a side effect, it also updates the next time point, -* so repeated calls to this method return the scheduled times. -*/ -public long getNext() -{ - long ret = next; - // check like this to prevent integer overflow of "next" - if( until-next > step ) next += step; - else next = -1; - return ret; -} - -} - - diff --git a/contrib/psg/src/peersim/dynamics/DynamicNetwork.java b/contrib/psg/src/peersim/dynamics/DynamicNetwork.java deleted file mode 100644 index a581a86ffe..0000000000 --- a/contrib/psg/src/peersim/dynamics/DynamicNetwork.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import java.util.Map; - -import org.simgrid.msg.Host; -import org.simgrid.msg.MsgException; - -import peersim.Simulator; -import peersim.config.Configuration; -import peersim.core.*; -import psgsim.NodeHost; -import psgsim.PSGDynamicNetwork; - -/** - * This {@link Control} can change the size of networks by adding and removing - * nodes. Can be used to model churn. This class supports only permanent removal - * of nodes and the addition of brand new nodes. That is, temporary downtime is - * not supported by this class. - */ -public class DynamicNetwork implements Control { - - // -------------------------------------------------------------------------- - // Parameters - // -------------------------------------------------------------------------- - - /** - * Config parameter which gives the prefix of node initializers. An - * arbitrary number of node initializers can be specified (Along with their - * parameters). These will be applied on the newly created nodes. The - * initializers are ordered according to alphabetical order if their ID. - * Example: - * - *

-	 * control.0 DynamicNetwork
-	 * control.0.init.0 RandNI
-	 * control.0.init.0.k 5
-	 * control.0.init.0.protocol somelinkable
-	 * ...
-	 * 
- * - * @config - */ - private static final String PAR_INIT = "init"; - - /** - * If defined, nodes are substituted (an existing node is removed, a new one - * is added. That is, first the number of nodes to add (or remove if - * {@value #PAR_ADD} is negative) is calculated, and then exactly the same - * number of nodes are removed (or added) immediately so that the network - * size remains constant. Not set by default. - * - * @config - */ - private static final String PAR_SUBST = "substitute"; - - /** - * Specifies the number of nodes to add or remove. It can be negative in - * which case nodes are removed. If its absolute value is less than one, - * then it is interpreted as a proportion of current network size, that is, - * its value is substituted with add*networksize. Its value is - * rounded to an integer. - * - * @config - */ - private static final String PAR_ADD = "add"; - - /** - * Nodes are added until the size specified by this parameter is reached. - * The network will never exceed this size as a result of this class. If not - * set, there will be no limit on the size of the network. - * - * @config - */ - private static final String PAR_MAX = "maxsize"; - - /** - * Nodes are removed until the size specified by this parameter is reached. - * The network will never go below this size as a result of this class. - * Defaults to 0. - * - * @config - */ - private static final String PAR_MIN = "minsize"; - - // -------------------------------------------------------------------------- - // Fields - // -------------------------------------------------------------------------- - - /** value of {@value #PAR_ADD} */ - protected final double add; - - /** value of {@value #PAR_SUBST} */ - protected final boolean substitute; - - /** value of {@value #PAR_MIN} */ - protected final int minsize; - - /** value of {@value #PAR_MAX} */ - protected final int maxsize; - - /** node initializers to apply on the newly added nodes */ - protected final NodeInitializer[] inits; - - // -------------------------------------------------------------------------- - // Protected methods - // -------------------------------------------------------------------------- - - /** - * Adds n nodes to the network. Extending classes can implement any - * algorithm to do that. The default algorithm adds the given number of - * nodes after calling all the configured initializers on them. - * - * @param n - * the number of nodes to add, must be non-negative. - */ - protected void add(int n) { - for (int i = 0; i < n; ++i) { - Node newnode = (Node) Network.prototype.clone(); - for (int j = 0; j < inits.length; ++j) { - inits[j].initialize(newnode); - } - Network.add(newnode); - - } - } - - // ------------------------------------------------------------------ - - /** - * Removes n nodes from the network. Extending classes can implement any - * algorithm to do that. The default algorithm removes random nodes - * permanently simply by calling {@link Network#remove(int)}. - * - * @param n - * the number of nodes to remove - */ - protected void remove(int n) { - for (int i = 0; i < n; ++i) { - int nr = CommonState.r.nextInt(Network.size()); - Network.remove(nr); - - } - } - - // -------------------------------------------------------------------------- - // Initialization - // -------------------------------------------------------------------------- - - /** - * Standard constructor that reads the configuration parameters. Invoked by - * the simulation engine. - * - * @param prefix - * the configuration prefix for this class - */ - public DynamicNetwork(String prefix) { - add = Configuration.getDouble(prefix + "." + PAR_ADD); - substitute = Configuration.contains(prefix + "." + PAR_SUBST); - Object[] tmp = Configuration.getInstanceArray(prefix + "." + PAR_INIT); - inits = new NodeInitializer[tmp.length]; - for (int i = 0; i < tmp.length; ++i) { - // System.out.println("Inits " + tmp[i]); - inits[i] = (NodeInitializer) tmp[i]; - } - maxsize = Configuration.getInt(prefix + "." + PAR_MAX, - Integer.MAX_VALUE); - minsize = Configuration.getInt(prefix + "." + PAR_MIN, 0); - } - - // -------------------------------------------------------------------------- - // Public methods - // -------------------------------------------------------------------------- - - /** - * Calls {@link #add(int)} or {@link #remove} with the parameters defined by - * the configuration. - * - * @return always false - */ - public final boolean execute() { - if (add == 0) - return false; - if (!substitute) { - if ((maxsize <= Network.size() && add > 0) - || (minsize >= Network.size() && add < 0)) - return false; - } - int toadd = 0; - int toremove = 0; - if (add > 0) { - toadd = (int) Math.round(add < 1 ? add * Network.size() : add); - if (!substitute && toadd > maxsize - Network.size()) - toadd = maxsize - Network.size(); - if (substitute) - toremove = toadd; - } else if (add < 0) { - toremove = (int) Math - .round(add > -1 ? -add * Network.size() : -add); - if (!substitute && toremove > Network.size() - minsize) - toremove = Network.size() - minsize; - if (substitute) - toadd = toremove; - } - remove(toremove); - add(toadd); - return false; - } - - // -------------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/dynamics/MethodInvoker.java b/contrib/psg/src/peersim/dynamics/MethodInvoker.java deleted file mode 100644 index 5e9e5fce73..0000000000 --- a/contrib/psg/src/peersim/dynamics/MethodInvoker.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import java.lang.reflect.*; -import peersim.config.*; -import peersim.core.*; -import java.util.ArrayList; - -/** - * This {@link Control} invokes a specified method on a protocol. - * The method is defined by config parameter {@value #PAR_METHOD} and - * the protocol is by {@value #PAR_PROT}. The method must not have any - * parameters and must return void. If no protocol is specified, then the - * method will be invoked on all protocol in the protocol stack that define - * it. - *

- * Although the method cannot have any parameters, it can of course read - * {@link CommonState}. It is guaranteed that the state is up-to-date, - * inlcuding eg method {@link CommonState#getNode}. - */ -public class MethodInvoker implements Control, NodeInitializer { - - -// -------------------------------------------------------------------------- -// Parameter names -// -------------------------------------------------------------------------- - -/** - * The protocol to operate on. - * If not defined, the given method will be invoked on all protocols that - * define it. In all cases, at least one protocol has to define it. - * @config - */ -private static final String PAR_PROT = "protocol"; - -/** - * The method to be invoked. It must return void and should not have any - * parameters specified. - * @config - */ -private static final String PAR_METHOD = "method"; - - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** Identifiers of the protocols to be initialized */ -private final int pid[]; - -/** Method name */ -private final String methodName; - -/** Methods corresponding to the protocols in {@link #pid}. */ -private final Method method[]; - - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public MethodInvoker(String prefix) { - - methodName = Configuration.getString(prefix+"."+PAR_METHOD); - if(!Configuration.contains(prefix+"."+PAR_PROT)) - { - // find protocols that implement method - ArrayList pids = new ArrayList(); - ArrayList methods = new ArrayList(); - for(int i=0; i list = new ArrayList(); - for(Method m: methods) - { - if(m.getName().equals(methodName)) - { - Class[] pars = m.getParameterTypes(); - Class ret = m.getReturnType(); - if( pars.length == 0 && ret==void.class ) - list.add(m); - } - } - - if(list.size() == 0) - { - throw new NoSuchMethodException("Method " - + methodName + " in class " + cl.getName()); - } - - return list.get(0); -} - -//-------------------------------------------------------------------------- - -/** Invokes method on all the nodes. */ -public boolean execute() { - - for(int i=0; ibefore inserting the node into the network. - */ -public void initialize(Node n); - -} diff --git a/contrib/psg/src/peersim/dynamics/OscillatingNetwork.java b/contrib/psg/src/peersim/dynamics/OscillatingNetwork.java deleted file mode 100644 index 4c10f2d59a..0000000000 --- a/contrib/psg/src/peersim/dynamics/OscillatingNetwork.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.config.Configuration; -import peersim.core.*; - -/** - * Makes the network size oscillate. - * The network size will be the function of time, parameterized by this - * parameter. The size function is - * avg+sin(time*pi/{@value #PAR_PERIOD})*ampl where - * avg=({@value #PAR_MAX}+{@value #PAR_MIN})/2 and - * ampl=({@value #PAR_MAX}-{@value #PAR_MIN})/2. - * This function is independent of how many times this class is executed, that - * is, whenever it is executed, it takes the current time and sets the network - * size accordingly. - */ -public class OscillatingNetwork implements Control -{ - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * Config parameter which gives the prefix of node initializers. An arbitrary - * number of node initializers can be specified (Along with their parameters). - * These will be applied - * on the newly created nodes. The initializers are ordered according to - * alphabetical order if their ID. - * Example: - *

-control.0 DynamicNetwork
-control.0.init.0 RandNI
-control.0.init.0.k 5
-control.0.init.0.protocol somelinkable
-...
- * 
- * @config - */ -private static final String PAR_INIT = "init"; - -/** - * Nodes are added until the size specified by this parameter is reached. The - * network will never exceed this size as a result of this class. - * If not set, there will be no limit on the size of the network. - * @config - */ -private static final String PAR_MAX = "maxsize"; - -/** - * Nodes are removed until the size specified by this parameter is reached. The - * network will never go below this size as a result of this class. - * Defaults to 0. - * @config - */ -private static final String PAR_MIN = "minsize"; - -/** - * Config parameter used to define the length of one period of the oscillation. - * The network size will be the function of time, parameterized by this - * parameter. The size function is - * avg+sin(time*pi/{@value #PAR_PERIOD})*ampl where - * avg=({@value #PAR_MAX}+{@value #PAR_MIN})/2 and - * ampl=({@value #PAR_MAX}-{@value #PAR_MIN})/2. - * @config - */ -private static final String PAR_PERIOD = "period"; - - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -/** Period */ -private final int period; - -/** Maximum size */ -private final int minsize; - -/** Minimum size */ -private final int maxsize; - -/** New nodes initializers */ -private final NodeInitializer[] inits; - - -//-------------------------------------------------------------------------- -// Initialization -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. Invoked by the - * simulation engine. - * @param prefix - * the configuration prefix for this class - */ -public OscillatingNetwork(String prefix) -{ - - period = Configuration.getInt(prefix + "." + PAR_PERIOD); - maxsize = - Configuration.getInt( - prefix + "." + PAR_MAX, - Integer.MAX_VALUE); - minsize = Configuration.getInt(prefix + "." + PAR_MIN, 0); - - Object[] tmp = Configuration.getInstanceArray(prefix + "." + PAR_INIT); - inits = new NodeInitializer[tmp.length]; - for (int i = 0; i < tmp.length; ++i) - { - inits[i] = (NodeInitializer) tmp[i]; - } -} - -//-------------------------------------------------------------------------- -// Methods -//-------------------------------------------------------------------------- - -/** - * Adds n nodes to the network. Extending classes can implement any algorithm to - * do that. The default algorithm adds the given number of nodes after calling - * all the configured initializers on them. - * - * @param n - * the number of nodes to add, must be non-negative. - */ -protected void add(int n) -{ - for (int i = 0; i < n; ++i) { - Node newnode = (Node) Network.prototype.clone(); - for (int j = 0; j < inits.length; ++j) { - inits[j].initialize(newnode); - } - Network.add(newnode); - } -} - -// ------------------------------------------------------------------ - -/** - * Removes n nodes from the network. Extending classes can implement any - * algorithm to do that. The default algorithm removes random - * nodes permanently simply by calling {@link Network#remove(int)}. - * @param n the number of nodes to remove - */ -protected void remove(int n) -{ - for (int i = 0; i < n; ++i) { - Network.remove(CommonState.r.nextInt(Network.size())); - } -} - -// ------------------------------------------------------------------ - -/** - * Takes the current time and sets the network size according to a periodic - * function of time. - * The size function is - * avg+sin(time*pi/{@value #PAR_PERIOD})*ampl where - * avg=({@value #PAR_MAX}+{@value #PAR_MIN})/2 and - * ampl=({@value #PAR_MAX}-{@value #PAR_MIN})/2. - * Calls {@link #add(int)} or {@link #remove} depending on whether the size - * needs to be increased or decreased to get the desired size. - * @return always false - */ -public boolean execute() -{ - long time = CommonState.getTime(); - int amplitude = (maxsize - minsize) / 2; - int newsize = (maxsize + minsize) / 2 + - (int) (Math.sin(((double) time) / period * Math.PI) * - amplitude); - int diff = newsize - Network.size(); - if (diff < 0) - remove(-diff); - else - add(diff); - - return false; -} - -} diff --git a/contrib/psg/src/peersim/dynamics/RandNI.java b/contrib/psg/src/peersim/dynamics/RandNI.java deleted file mode 100644 index 7a4d5c749c..0000000000 --- a/contrib/psg/src/peersim/dynamics/RandNI.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.core.*; -import peersim.config.Configuration; - -/** - * Initializes the neighbor list of a node with random links. - */ -public class RandNI implements NodeInitializer { - - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * The protocol to operate on. - * @config - */ -private static final String PAR_PROT = "protocol"; - -/** - * The number of samples (with replacement) to draw to initialize the - * neighbor list of the node. - * @config - */ -private static final String PAR_DEGREE = "k"; - -/** - * If this config property is defined, method {@link Linkable#pack()} is - * invoked on the specified protocol at the end of the wiring phase. - * Default to false. - * @config - */ -private static final String PAR_PACK = "pack"; - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -/** - * The protocol we want to wire - */ -private final int pid; - -/** - * The degree of the regular graph - */ -private final int k; - -/** - * If true, method pack() is invoked on the initialized protocol - */ -private final boolean pack; - - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. Invoked by the - * simulation engine. - * @param prefix the configuration prefix for this class - */ -public RandNI(String prefix) -{ - pid = Configuration.getPid(prefix + "." + PAR_PROT); - k = Configuration.getInt(prefix + "." + PAR_DEGREE); - pack = Configuration.contains(prefix + "." + PAR_PACK); -} - -//-------------------------------------------------------------------------- -//Methods -//-------------------------------------------------------------------------- - -/** - * Takes {@value #PAR_DEGREE} random samples with replacement from the nodes of - * the overlay network. No loop edges are added. - */ -public void initialize(Node n) -{ - if (Network.size() == 0) return; - - Linkable linkable = (Linkable) n.getProtocol(pid); - for (int j = 0; j < k; ++j) - { - int r = CommonState.r.nextInt(Network.size()); - linkable.addNeighbor(Network.get(r)); - } - - if (pack) linkable.pack(); -} - -} - diff --git a/contrib/psg/src/peersim/dynamics/StarNI.java b/contrib/psg/src/peersim/dynamics/StarNI.java deleted file mode 100644 index 4dbd8664df..0000000000 --- a/contrib/psg/src/peersim/dynamics/StarNI.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.core.*; -import peersim.config.Configuration; - -/** - * Initializes a node's neighbor list with a fixed center. - */ -public class StarNI implements NodeInitializer { - - -// ========================= fields ================================= -// ================================================================== - - -/** - * The protocol to operate on. - * @config - */ -private static final String PAR_PROT = "protocol"; - -/** - * If this config property is defined, method {@link Linkable#pack()} is - * invoked on the specified protocol at the end of the wiring phase. - * Default to false. - * @config - */ -private static final String PAR_PACK = "pack"; - -/** - * The protocol we want to wire - */ -protected final int pid; - -/** If true, method pack() is invoked on the initialized protocol */ -protected final boolean pack; - -/** - * Used as center: nodes will link to this node. - */ -protected Node center = null; - - -// ==================== initialization ============================== -//=================================================================== - - -public StarNI(String prefix) { - - pid = Configuration.getPid(prefix+"."+PAR_PROT); - pack = Configuration.contains(prefix+"."+PAR_PACK); -} - - -// ===================== public methods ============================== -// =================================================================== - - -/** - * Adds a link to a fixed node, the center. This fixed node remains the same - * throughout consecutive calls to this method. If the center fails in the - * meantime, a new one is chosen so care should be taken. The center is the - * first node that is not down (starting from node 0, 1, etc) - * at the time of the first call to the function. When a new center needs to - * be chosen (the current one is down), the new center is again the first - * one which is up. If no nodes are up, the node with the last index is set - * as center, and selection of a new center is always attempted when this - * method is called again. - */ -public void initialize(Node n) { - - if( Network.size() == 0 ) return; - - for(int i=0; (center==null || !center.isUp()) && i -
  • It MUST be static
  • -
  • It MUST have a first argument that can be assigned from a class - that implements {@link Graph}.
  • -
  • It MAY contain zero or more arguments following the first one.
  • -
  • All the arguments after the first one MUST be of primitive type int, - long or double, except - the last one, which MAY be of type that can be assigned from - java.util.Random
  • - - The arguments are initialized using the configuration as follows. -
      -
    • The first argument is the {@link Graph} that is passed to - {@link #wire}.
    • -
    • The arguments after the first one (indexed as 1,2,etc) are initialized - from configuration parameters of the form {@value #PAR_ARG}i, where i is the - index. -
    • If the last argument can be assigned from - java.util.Random then it is initialized with - {@link CommonState#r}, the central source of randomness for the - simulator.
    • -
    - For example, the class {@link WireWS} can be emulated by configuring -
    - init.0 WireByMethod
    - init.0.class GraphFactory
    - init.0.method wireWS
    - init.0.arg1 10
    - init.0.arg2 0.1
    - ...
    - 
    - Note that the {@value #PAR_CLASS} parameter defaults to {@link GraphFactory}, - and {@value #PAR_METHOD} defaults to "wire". - */ -public class WireByMethod extends WireGraph { - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * The prefix for the configuration properties that describe parameters. - * @config - */ -private static final String PAR_ARG = "arg"; - -/** -* The class that has the method we want to use. Defaults to -* {@link GraphFactory}. -* @config -*/ -private static final String PAR_CLASS = "class"; - -/** -* The name of the method for wiring the graph. Defaults to wire. -* @config -*/ -private static final String PAR_METHOD = "method"; - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -private final Object[] args; - -private final Method method; - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Loads configuration. It verifies the constraints defined - * in {@link WireByMethod}. - * @param prefix the configuration prefix for this class - */ -public WireByMethod(String prefix) -{ - super(prefix); - - // get the method - try - { - final Class wire = - Configuration.getClass(prefix + "." + PAR_CLASS, - Class.forName("peersim.graph.GraphFactory")); - method = WireByMethod.getMethod( - wire, - Configuration.getString(prefix+"."+PAR_METHOD,"wire")); - } - catch( Exception e ) - { - throw new RuntimeException(e); - } - - // set the constant args (those other than 0th) - Class[] argt = method.getParameterTypes(); - args = new Object[argt.length]; - for(int i=1; i list = new ArrayList(); - for (Method m: methods) { - if (m.getName().equals(methodName)) { - list.add(m); - } - } - - if (list.size() == 0) { - throw new NoSuchMethodException("No method " - + methodName + " in class " + cl.getSimpleName()); - } else if (list.size() > 1) { - throw new NoSuchMethodException("Multiple methods called " - + methodName + " in class " + cl.getSimpleName()); - } - - // Found a single method with the right name; check if - // it is a setter. - final Class graphClass = Class.forName("peersim.graph.Graph"); - final Class randomClass = Class.forName("java.util.Random"); - Method method = list.get(0); - Class[] pars = method.getParameterTypes(); - if( pars.length < 1 || !pars[0].isAssignableFrom(graphClass) ) - throw new NoSuchMethodException(method.getName() + " of class " - + cl.getSimpleName() + " is not a valid graph wiring method,"+ - " it has to have peersim.graph.Graph as first argument type"); - for(int i=1; i= Network.size() ) - { - wasOutOfRange = true; - continue; - } - - for(int i=0; i= Network.size() ) - wasOutOfRange = true; - else - g.setEdge(from,to); - } - } - - if( wasOutOfRange ) - System.err.println("WireFromFile warning: in "+file+" "+ - "some nodes were out of range and so ignored."); - lnr.close(); -} -catch( IOException e ) -{ - throw new RuntimeException(e); -} -} - -} diff --git a/contrib/psg/src/peersim/dynamics/WireGraph.java b/contrib/psg/src/peersim/dynamics/WireGraph.java deleted file mode 100644 index 4c8af15794..0000000000 --- a/contrib/psg/src/peersim/dynamics/WireGraph.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.graph.Graph; -import peersim.core.*; -import peersim.config.Configuration; - -/** - * This class is the superclass of classes that - * takes a {@link Linkable} protocol or a graph and add edges that define a - * certain topology. - * Note that no connections are removed, they are only added. So it can be used - * in combination with other initializers. - */ -public abstract class WireGraph implements Control -{ - -// -------------------------------------------------------------------------- -// Parameters -// -------------------------------------------------------------------------- - -/** - * The {@link Linkable} protocol to operate on. If it is not specified, - * then operates on {@link #g}. If {@link #g} is null, {@link #execute} throws - * an Exception. Note that if {@link #g} is set, it will be used irrespective - * of the setting of the protocol in this field. - * @config - */ -private static final String PAR_PROT = "protocol"; - -/** - * If this config property is defined, method {@link Linkable#pack()} is - * invoked on the specified protocol at the end of the wiring phase. - * Default to false. - * @config - */ -private static final String PAR_PACK = "pack"; - -/** - * If set, the generated graph is undirected. In other words, for each link - * (i,j) a link (j,i) will also be added. Defaults to false. - * @config - */ -private static final String PAR_UNDIR = "undir"; - -/** -* Alias for {@value #PAR_UNDIR}. -* @config -*/ -private static final String PAR_UNDIR_ALT = "undirected"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** - * The protocol we want to wire. It is negative if no protocol was set - * (in that case, a graph must be specified, see {@link #g}). - */ -protected final int pid; - -/** If true, method pack() is invoked on the initialized protocol */ -private final boolean pack; - -/** If true, edges are added in an undirected fashion.*/ -public final boolean undir; - -/** -* If set (not null), this is the graph to wire. If null, the current overlay -* is wired each time {@link #execute} is called, as specified by {@value -* #PAR_PROT}. -*/ -public Graph g=null; - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. Normally - * invoked by the simulation engine. - * @param prefix - * the configuration prefix for this class - */ -protected WireGraph(String prefix) { - - if( Configuration.contains(prefix + "." + PAR_PROT) ) - pid = Configuration.getPid(prefix + "." + PAR_PROT); - else - pid = -10; - pack = Configuration.contains(prefix + "." + PAR_PACK); - undir = (Configuration.contains(prefix + "." + PAR_UNDIR) | - Configuration.contains(prefix + "." + PAR_UNDIR_ALT)); -} - - -//-------------------------------------------------------------------------- -//Public methods -//-------------------------------------------------------------------------- - -/** -* Calls method {@link #wire} with the graph {@link #g}, -* or if null, on the overlay specified by the protocol given by config -* parameter {@value #PAR_PROT}. If neither {@link #g}, nor {@value #PAR_PROT} -* is set, throws a RuntimException. -*/ -public final boolean execute() { - - Graph gr; - if(g==null && pid==-10) - { - throw new RuntimeException( - "Neither a protocol, nor a graph is specified."); - } - if(g==null) gr = new OverlayGraph(pid,!undir); - else gr=g; - - if(gr.size()==0) return false; - wire(gr); - - if( g==null && pack) - { - int size = Network.size(); - for (int i = 0; i < size; i++) - { - Linkable link = - (Linkable) Network.get(i).getProtocol(pid); - link.pack(); - } - } - return false; -} - -//-------------------------------------------------------------------------- - -/** The method that should wire (add edges to) the given graph. Has to -* be implemented by extending classes */ -public abstract void wire(Graph g); - -} - diff --git a/contrib/psg/src/peersim/dynamics/WireKOut.java b/contrib/psg/src/peersim/dynamics/WireKOut.java deleted file mode 100644 index 927ddbd1ea..0000000000 --- a/contrib/psg/src/peersim/dynamics/WireKOut.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.graph.*; -import peersim.core.*; -import peersim.config.*; - -/** - * Takes a {@link Linkable} protocol and adds random connections. Note that no - * connections are removed, they are only added. So it can be used in - * combination with other initializers. - * @see GraphFactory#wireKOut - */ -public class WireKOut extends WireGraph { - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * The number of outgoing edges to generate from each node. - * Passed to {@link GraphFactory#wireKOut}. - * No loop edges are generated. - * In the undirected case, the degree - * of nodes will be on average almost twice as much because the incoming links - * also become links out of each node. - * @config - */ -private static final String PAR_DEGREE = "k"; - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -/** - * The number of outgoing edges to generate from each node. - */ -private final int k; - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public WireKOut(String prefix) -{ - super(prefix); - k = Configuration.getInt(prefix + "." + PAR_DEGREE); -} - -//-------------------------------------------------------------------------- -//Methods -//-------------------------------------------------------------------------- - -/** Calls {@link GraphFactory#wireKOut}. */ -public void wire(Graph g) { - - GraphFactory.wireKOut(g,k,CommonState.r); -} - -} diff --git a/contrib/psg/src/peersim/dynamics/WireRegRootedTree.java b/contrib/psg/src/peersim/dynamics/WireRegRootedTree.java deleted file mode 100644 index e8e095231b..0000000000 --- a/contrib/psg/src/peersim/dynamics/WireRegRootedTree.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.graph.*; -import peersim.config.*; - -/** - * Takes a {@link peersim.core.Linkable} protocol and adds connections that - * define a regular - * rooted tree. Note that no - * connections are removed, they are only added. So it can be used in - * combination with other initializers. - * @see #wire - * @see GraphFactory#wireRegRootedTree - */ -public class WireRegRootedTree extends WireGraph { - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * The parameter of the tree wiring method. - * It is passed to {@link GraphFactory#wireRegRootedTree}. - * @config - */ -private static final String PAR_DEGREE = "k"; - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -private final int k; - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public WireRegRootedTree(String prefix) -{ - super(prefix); - k = Configuration.getInt(prefix + "." + PAR_DEGREE); -} - -//-------------------------------------------------------------------------- -//Methods -//-------------------------------------------------------------------------- - -/** Calls {@link GraphFactory#wireRegRootedTree}. */ -public void wire(Graph g) { - - GraphFactory.wireRegRootedTree(g,k); -} - -} diff --git a/contrib/psg/src/peersim/dynamics/WireRingLattice.java b/contrib/psg/src/peersim/dynamics/WireRingLattice.java deleted file mode 100644 index a23822ed7f..0000000000 --- a/contrib/psg/src/peersim/dynamics/WireRingLattice.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.graph.*; -import peersim.config.Configuration; - -/** - * Takes a {@link peersim.core.Linkable} protocol and adds edges that - * define a ring lattice. - * Note that no connections are removed, they are only added. So it can be used - * in combination with other initializers. - * @see GraphFactory#wireRingLattice - */ -public class WireRingLattice extends WireGraph { - -// -------------------------------------------------------------------------- -// Parameters -// -------------------------------------------------------------------------- - -/** - * The "lattice parameter" of the graph. The out-degree of the graph is equal to - * 2k. See {@link GraphFactory#wireRingLattice} (to which this parameter is - * passed) for further details. - * @config - */ -private static final String PAR_K = "k"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** - */ -private final int k; - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public WireRingLattice(String prefix) -{ - super(prefix); - k = Configuration.getInt(prefix + "." + PAR_K); -} - -//-------------------------------------------------------------------------- -//Public methods -//-------------------------------------------------------------------------- - -/** calls {@link GraphFactory#wireRingLattice}. */ -public void wire(Graph g) -{ - GraphFactory.wireRingLattice(g, k); -} - -//-------------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/dynamics/WireScaleFreeBA.java b/contrib/psg/src/peersim/dynamics/WireScaleFreeBA.java deleted file mode 100644 index 3b6ca30cad..0000000000 --- a/contrib/psg/src/peersim/dynamics/WireScaleFreeBA.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.config.*; -import peersim.core.*; -import peersim.graph.*; - -/** -* This class contains the implementation of the Barabasi-Albert model -* of growing scale free networks. The original model is described in -* http://arxiv.org/abs/cond-mat/0106096. It also contains the option of building -* a directed network, in which case the model is a variation of the BA model -* described in -http://arxiv.org/pdf/cond-mat/0408391. In both cases, the number of the -* initial set of nodes is the same as the degree parameter, and no links are -* added. The first added node is connected to all of the initial nodes, -* and after that the BA model is used normally. -* @see GraphFactory#wireScaleFreeBA -*/ -public class WireScaleFreeBA extends WireGraph { - - -// ================ constants ============================================ -// ======================================================================= - -/** - * The number of edges added to each new node (apart from those forming the - * initial network). - * Passed to {@link GraphFactory#wireScaleFreeBA}. - * @config - */ -private static final String PAR_DEGREE = "k"; - - -// =================== fields ============================================ -// ======================================================================= - -/** Parameter of the BA model. */ -private int k; - -// ===================== initialization ================================== -// ======================================================================= - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class -*/ -public WireScaleFreeBA(String prefix) -{ - super(prefix); - k = Configuration.getInt(prefix + "." + PAR_DEGREE); -} - - -// ======================== methods ======================================= -// ======================================================================== - - -/** calls {@link GraphFactory#wireScaleFreeBA}.*/ -public void wire(Graph g) { - - GraphFactory.wireScaleFreeBA(g,k,CommonState.r ); -} - -} - diff --git a/contrib/psg/src/peersim/dynamics/WireScaleFreeDM.java b/contrib/psg/src/peersim/dynamics/WireScaleFreeDM.java deleted file mode 100644 index 06ae97343e..0000000000 --- a/contrib/psg/src/peersim/dynamics/WireScaleFreeDM.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.graph.Graph; -import peersim.config.*; -import peersim.core.*; - -/** - * Wires a scale free graph using a method described in - * this paper. - * It is an incremental technique, where the new nodes are connected to - * the two ends of an edge that is already in the network. - * This model always wires undirected links. - */ -public class WireScaleFreeDM extends WireGraph { - - -//-------------------------------------------------------------------------- -// Constants -//-------------------------------------------------------------------------- - -/** - * The number of edges added to each new - * node (apart from those forming the initial network) is twice this - * value. - * @config - */ -private static final String PAR_EDGES = "k"; - - -//-------------------------------------------------------------------------- -// Fields -//-------------------------------------------------------------------------- - - -/** The number of edges created for a new node is 2*k. */ -private final int k; - - -//-------------------------------------------------------------------------- -// Constructor -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public WireScaleFreeDM(String prefix) -{ - super(prefix); - k = Configuration.getInt(prefix + "." + PAR_EDGES); -} - - -//-------------------------------------------------------------------------- -// Methods -//-------------------------------------------------------------------------- - -/** - * Wires a scale free graph using a method described in - * this paper. - * It is an incremental technique, where the new nodes are connected to - * the two ends of an edge that is already in the network. - * This model always wires undirected links. -*/ -public void wire(Graph g) { - - int nodes=g.size(); - int[] links = new int[4*k*nodes]; - - // Initial number of nodes connected as a clique - int clique = (k > 3 ? k : 3); - - // Add initial edges, to form a clique - int len=0; - for (int i=0; i < clique; i++) - for (int j=0; j < clique; j++) - { - if (i != j) - { - g.setEdge(i,j); - g.setEdge(j,i); - links[len*2] = i; - links[len*2+1] = j; - len++; - } - } - - for (int i=clique; i < nodes; i++) - for (int l=0; l < k; l++) - { - int edge = CommonState.r.nextInt(len); - int m = links[edge*2]; - int j = links[edge*2+1]; - g.setEdge(i, m); - g.setEdge(m, i); - g.setEdge(j, m); - g.setEdge(m, j); - links[len*2] = i; - links[len*2+1] = m; - len++; - links[len*2] = j; - links[len*2+1] = m; - len++; - } -} - -} diff --git a/contrib/psg/src/peersim/dynamics/WireStar.java b/contrib/psg/src/peersim/dynamics/WireStar.java deleted file mode 100644 index 0f11b64c77..0000000000 --- a/contrib/psg/src/peersim/dynamics/WireStar.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.graph.*; - -/** - * Takes a {@link peersim.core.Linkable} protocol and adds connection - * which for a star - * topology. No connections are removed, they are only added. So it can be used - * in combination with other initializers. - * @see GraphFactory#wireStar - */ -public class WireStar extends WireGraph { - -// ===================== initialization ============================== -// =================================================================== - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public WireStar(String prefix) { super(prefix); } - -// ===================== public methods ============================== -// =================================================================== - - -/** Calls {@link GraphFactory#wireStar}.*/ -public void wire(Graph g) { - - GraphFactory.wireStar(g); -} - - -} - diff --git a/contrib/psg/src/peersim/dynamics/WireWS.java b/contrib/psg/src/peersim/dynamics/WireWS.java deleted file mode 100644 index 65cefed685..0000000000 --- a/contrib/psg/src/peersim/dynamics/WireWS.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.dynamics; - -import peersim.graph.*; -import peersim.core.*; -import peersim.config.Configuration; - -/** -* Takes a {@link Linkable} protocol and adds connections following the -* small-world model of Watts and Strogatz. Note that no -* connections are removed, they are only added. So it can be used in -* combination with other initializers. -* @see GraphFactory#wireWS -*/ -public class WireWS extends WireGraph { - - -// ========================= fields ================================= -// ================================================================== - -/** - * The beta parameter of a Watts-Strogatz graph represents the probability for a - * node to be re-wired. - * Passed to {@link GraphFactory#wireWS}. - * @config - */ -private static final String PAR_BETA = "beta"; - -/** - * The degree of the graph. See {@link GraphFactory#wireRingLattice}. - * Passed to {@link GraphFactory#wireWS}. - * @config - */ -private static final String PAR_DEGREE = "k"; - -/** - * The degree of the regular graph - */ -private final int k; - -/** - * The degree of the regular graph - */ -private final double beta; - - -// ==================== initialization ============================== -//=================================================================== - - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public WireWS(String prefix) { - - super(prefix); - k = Configuration.getInt(prefix+"."+PAR_DEGREE); - beta = Configuration.getDouble(prefix+"."+PAR_BETA); -} - - -// ===================== public methods ============================== -// =================================================================== - - -/** calls {@link GraphFactory#wireWS}.*/ -public void wire(Graph g) { - - GraphFactory.wireWS(g,k,beta,CommonState.r); -} - -} - diff --git a/contrib/psg/src/peersim/edsim/CDScheduler.java b/contrib/psg/src/peersim/edsim/CDScheduler.java deleted file mode 100644 index f864ff55b5..0000000000 --- a/contrib/psg/src/peersim/edsim/CDScheduler.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.edsim; - -import peersim.core.*; -import peersim.cdsim.CDProtocol; -import peersim.config.*; -import peersim.dynamics.NodeInitializer; - -/** - * Schedules the first execution of the cycle based protocol instances in the - * event driven engine. It implements {@link Control} but it will most often be - * invoked only once for each protocol as an initializer, since the scheduled - * events schedule themselves for the consecutive executions (see - * {@link NextCycleEvent}). - * - *

    - * All {@link CDProtocol} specifications in the configuration need to contain a - * {@link Scheduler} specification at least for the step size (see config - * parameter {@value peersim.core.Scheduler#PAR_STEP} of {@link Scheduler}). - * This value is used as the cycle length for the corresponding protocol. - * - * @see NextCycleEvent - */ -public class CDScheduler implements Control, NodeInitializer { - - // ============================== fields ============================== - // ==================================================================== - - /** - * Parameter that is used to define the class that is used to schedule the - * next cycle. Its type is (or extends) {@link NextCycleEvent}. Defaults to - * {@link NextCycleEvent}. - * - * @config - */ - private static final String PAR_NEXTC = "nextcycle"; - - /** - * The protocols that this scheduler schedules for the first execution. It - * might contain several protocol names, separated by whitespace. All - * protocols will be scheduled based on the common parameter set for this - * scheduler and the parameters of the protocol (cycle length). Protocols - * are scheduled independently of each other. - * - * @config - */ - private static final String PAR_PROTOCOL = "protocol"; - - /** - * If set, it means that the initial execution of the given protocol is - * scheduled for a different random time for all nodes. The random time is a - * sample between the current time (inclusive) and the cycle length - * (exclusive), the latter being specified by the step parameter (see - * {@link Scheduler}) of the assigned protocol. - * - * @see #execute - * @config - */ - private static final String PAR_RNDSTART = "randstart"; - - /** - * Contains the scheduler objects for all {@link CDProtocol}s defined in the - * configuration. The length of the array is the number of protocols - * defined, but those entries that belong to protocols that are not - * {@link CDProtocol}s are null. - */ - public static final Scheduler[] sch; - - private final NextCycleEvent[] nce; - - private final int[] pid; - - private final boolean randstart; - - // =============================== initialization ====================== - // ===================================================================== - - /** - * Loads protocol schedulers for all protocols. - */ - static { - - String[] names = Configuration.getNames(Node.PAR_PROT); - sch = new Scheduler[names.length]; - for (int i = 0; i < names.length; ++i) { - if (Network.prototype.getProtocol(i) instanceof CDProtocol) - // with no default values for step to avoid - // "overscheduling" due to lack of step option. - sch[i] = new Scheduler(names[i], false); - } - } - - // -------------------------------------------------------------------- - - /** - * Initialization based on configuration parameters. - */ - public CDScheduler(String n) { - String[] prots = Configuration.getString(n + "." + PAR_PROTOCOL).split("\\s"); - pid = new int[prots.length]; - nce = new NextCycleEvent[prots.length]; - for (int i = 0; i < prots.length; ++i) { - pid[i] = Configuration.lookupPid(prots[i]); - if (!(Network.prototype.getProtocol(pid[i]) instanceof CDProtocol)) { - throw new IllegalParameterException(n + "." + PAR_PROTOCOL, - "Only CDProtocols are accepted here"); - } - nce[i] = (NextCycleEvent) Configuration.getInstance(n + "." - + PAR_NEXTC, new NextCycleEvent(null)); - } - randstart = Configuration.contains(n + "." + PAR_RNDSTART); - } - - // ========================== methods ================================== - // ===================================================================== - - /** - * Schedules the protocol at all nodes for the first execution adding it to - * the priority queue of the event driven simulation. The time of the first - * execution is determined by {@link #firstDelay}. The implementation calls - * {@link #initialize} for all nodes. - * - * @see #initialize - */ - public boolean execute() { - - for (int i = 0; i < Network.size(); ++i) { - initialize(Network.get(i)); - } - - return false; - } - - // -------------------------------------------------------------------- - - /** - * Schedules the protocol at given node for the first execution adding it to - * the priority queue of the event driven simulation. The time of the first - * execution is determined by a reference point in time and - * {@link #firstDelay}, which defines the delay from the reference point. - * The reference point is the maximum of the current time, and the value of - * parameter {@value peersim.core.Scheduler#PAR_FROM} of the protocol being - * scheduled. If the calculated time of the first execution is not valid - * according to the schedule of the protocol then no execution is scheduled - * for that protocol. - *

    - * A final note: for performance reasons, the recommended practice is not to - * use parameter {@value peersim.core.Scheduler#PAR_FROM} in protocols, but - * to schedule {@link CDScheduler} itself for the desired time, whenever - * possible (e.g., it is not possible if {@link CDScheduler} is used as a - * {@link NodeInitializer}). - */ - public void initialize(Node n) { - /* - * XXX If "from" is not the current time and this is used as a control - * (not node initializer) then we dump _lots_ of events in the queue - * that are just stored there until "from" comes. This reduces - * performance, and should be fixed. When fixed, the final comment can - * be removed from the docs. - */ - - final long time = CommonState.getTime(); - for (int i = 0; i < pid.length; ++i) { - Object nceclone = null; - try { - nceclone = nce[i].clone(); - } catch (CloneNotSupportedException e) { - } // cannot possibly happen - - final long delay = firstDelay(sch[pid[i]].step); - final long nexttime = Math.max(time, sch[pid[i]].from) + delay; - if (nexttime < sch[pid[i]].until) - EDSimulator.add(nexttime - time, nceclone, n, pid[i]); - } - } - - // -------------------------------------------------------------------- - - /** - * Returns the time (through giving the delay from the current time) when - * this even is first executed. If {@value #PAR_RNDSTART} is not set, it - * returns zero, otherwise a random value between 0, inclusive, and - * cyclelength, exclusive. - * - * @param cyclelength - * The cycle length of the cycle based protocol for which this - * method is called - */ - protected long firstDelay(long cyclelength) { - - if (randstart) - return CommonState.r.nextLong(cyclelength); - else - return 0; - } -} diff --git a/contrib/psg/src/peersim/edsim/ControlEvent.java b/contrib/psg/src/peersim/edsim/ControlEvent.java deleted file mode 100644 index 8c12d3a330..0000000000 --- a/contrib/psg/src/peersim/edsim/ControlEvent.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.edsim; - -import peersim.core.Control; -import peersim.core.Scheduler; - - -/** - * Wrapper for {@link Control}s to be executed in an event driven simulation. - * - * @author Alberto Montresor - * @version $Revision: 1.5 $ - */ -class ControlEvent -{ - -//--------------------------------------------------------------------- -//Fields -//--------------------------------------------------------------------- - -/** - * The reference to the dynamics to be executed; null if this cycle event - * refers to an observer. - */ -private Control control; - -/** Order index used to maintain order between cycle-based events */ -private int order; - - -//--------------------------------------------------------------------- -//Initialization -//--------------------------------------------------------------------- - -/** - * Scheduler object to obtain the next schedule time of this event - */ -private Scheduler scheduler; - -/** - * Creates a cycle event for a control object. It also schedules the object - * for the first execution adding it to the priority queue of the event driven - * simulation. - */ -public ControlEvent(Control control, Scheduler scheduler, int order) -{ - this.control = control; - this.order = order; - this.scheduler = scheduler; - long next = scheduler.getNext(); - if( next>=0 ) EDSimulator.addControlEvent(next, order, this); -} - -//--------------------------------------------------------------------- -//Methods -//--------------------------------------------------------------------- - -/** -* Executes the control object, and schedules the object for the next execution -* adding it to the priority queue of the event driven simulation. -*/ -public boolean execute() { - - boolean ret = control.execute(); - long next = scheduler.getNext(); - if( next>=0 ) EDSimulator.addControlEvent(next, order, this); - return ret; -} - -} - - diff --git a/contrib/psg/src/peersim/edsim/EDProtocol.java b/contrib/psg/src/peersim/edsim/EDProtocol.java deleted file mode 100644 index 60c83a2e45..0000000000 --- a/contrib/psg/src/peersim/edsim/EDProtocol.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.edsim; - -import peersim.core.*; - -/** - * The interface to be implemented by protocols run under the event-driven - * model. A single method is provided, to deliver events to the protocol. - * - * @author Alberto Montresor - * @version $Revision: 1.5 $ - */ -public interface EDProtocol -extends Protocol -{ - - /** - * This method is invoked by the scheduler to deliver events to the - * protocol. Apart from the event object, information about the node - * and the protocol identifier are also provided. Additional information - * can be accessed through the {@link CommonState} class. - * - * @param node the local node - * @param pid the identifier of this protocol - * @param event the delivered event - */ - public void processEvent( Node node, int pid, Object event ); - -} - diff --git a/contrib/psg/src/peersim/edsim/EDSimulator.java b/contrib/psg/src/peersim/edsim/EDSimulator.java deleted file mode 100644 index e56d021833..0000000000 --- a/contrib/psg/src/peersim/edsim/EDSimulator.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.edsim; - -import java.util.Arrays; - -import peersim.Simulator; -import peersim.config.*; -import peersim.core.*; -import psgsim.PSGSimulator; - -/** - * Event-driven simulator engine. It is a fully static singleton class. For an - * event driven simulation the configuration has to describe a set of - * {@link Protocol}s, a set of {@link Control}s and their ordering and a set of - * initializers and their ordering. See parameters {@value #PAR_INIT}, - * {@value #PAR_CTRL}. - *

    - * One experiment run by {@link #nextExperiment} works as follows. First the - * initializers are run in the specified order. Then the first execution of all - * specified controls is scheduled in the event queue. This scheduling is - * defined by the {@link Scheduler} parameters of each control component. After - * this, the first event is taken from the event queue. If the event wraps a - * control, the control is executed, otherwise the event is delivered to the - * destination protocol, that must implement {@link EDProtocol}. This is - * iterated while the current time is less than {@value #PAR_ENDTIME} or the - * queue becomes empty. If more control events fall at the same time point, then - * the order given in the configuration is respected. If more non-control events - * fall at the same time point, they are processed in a random order. - *

    - * The engine also provides the interface to add events to the queue. Note that - * this engine does not explicitly run the protocols. In all cases at least one - * control or initializer has to be defined that sends event(s) to protocols. - *

    - * Controls can be scheduled (using the {@link Scheduler} parameters in the - * configuration) to run after the experiment has finished. That is, each - * experiment is finished by running the controls that are scheduled to be run - * after the experiment. - *

    - * Any control can interrupt an experiment at any time it is executed by - * returning true in method {@link Control#execute}. However, the controls - * scheduled to run after the experiment are still executed completely, - * irrespective of their return value and even if the experiment was - * interrupted. - *

    - * {@link CDScheduler} has to be mentioned that is a control that can bridge the - * gap between {@link peersim.cdsim} and the event driven engine. It can wrap - * {@link peersim.cdsim.CDProtocol} appropriately so that the execution of the - * cycles are scheduled in configurable ways for each node individually. In some - * cases this can add a more fine-grained control and more realism to - * {@link peersim.cdsim.CDProtocol} simulations, at the cost of some loss in - * performance. - *

    - * When protocols at different nodes send messages to each other, they might - * want to use a model of the transport layer so that in the simulation message - * delay and message omissions can be modeled in a modular way. This - * functionality is implemented in package {@link peersim.transport}. - * - * @see Configuration - */ -public class EDSimulator { - - // --------------------------------------------------------------------- - // Parameters - // --------------------------------------------------------------------- - - /** - * The ending time for simulation. Only events that have a strictly smaller - * value are executed. It must be positive. Although in principle negative - * timestamps could be allowed, we assume time will be positive. - * - * @config - */ - public static final String PAR_ENDTIME = "simulation.endtime"; - - /** - * This parameter specifies how often the simulator should log the current - * time on the standard error. The time is logged only if there were events - * in the respective interval, and only the time of some actual event is - * printed. That is, the actual log is not guaranteed to happen in identical - * intervals of time. It is merely a way of seeing whether the simulation - * progresses and how fast... - * - * @config - */ - private static final String PAR_LOGTIME = "simulation.logtime"; - - /** - * This parameter specifies the event queue to be used. It must be an - * implementation of interface {@link PriorityQ}. If it is not defined, the - * internal implementation is used. - * - * @config - */ - private static final String PAR_PQ = "simulation.eventqueue"; - - /** - * This is the prefix for initializers. These have to be of type - * {@link Control}. They are run at the beginning of each experiment, in the - * order specified by the configuration. - * - * @see Configuration - * @config - * @config - */ - private static final String PAR_INIT = "init"; - - /** - * This is the prefix for {@link Control} components. They are run at the - * time points defined by the {@link Scheduler} associated to them. If some - * controls have to be executed at the same time point, they are executed in - * the order specified in the configuration. - * - * @see Configuration - * @config - */ - private static final String PAR_CTRL = "control"; - - // --------------------------------------------------------------------- - // Fields - // --------------------------------------------------------------------- - - /** Maximum time for simulation */ - private static long endtime; - - /** Log time */ - private static long logtime; - - /** holds the modifiers of this simulation */ - private static Control[] controls = null; - - /** Holds the control schedulers of this simulation */ - private static Scheduler[] ctrlSchedules = null; - - /** Ordered list of events (heap) */ - private static PriorityQ heap = null; - - private static long nextlog = 0; - - // =============== initialization ====================================== - // ===================================================================== - - /** to prevent construction */ - private EDSimulator() { - } - - // --------------------------------------------------------------------- - // Private methods - // --------------------------------------------------------------------- - - /** - * Load and run initializers. - */ - private static void runInitializers() { - - Object[] inits = Configuration.getInstanceArray(PAR_INIT); - String names[] = Configuration.getNames(PAR_INIT); - - for (int i = 0; i < inits.length; ++i) { - - System.err.println("- Running initializer " + names[i] + ": " - + inits[i].getClass()); - ((Control) inits[i]).execute(); - } - } - - // -------------------------------------------------------------------- - - private static void scheduleControls() { - // load controls - String[] names = Configuration.getNames(PAR_CTRL); - controls = new Control[names.length]; - ctrlSchedules = new Scheduler[names.length]; - for (int i = 0; i < names.length; ++i) { - controls[i] = (Control) Configuration.getInstance(names[i]); - ctrlSchedules[i] = new Scheduler(names[i], false); - } - System.err.println("EDSimulator: loaded controls " - + Arrays.asList(names)); - - // Schedule controls execution - if (controls.length > heap.maxPriority() + 1) - throw new IllegalArgumentException("Too many control objects"); - for (int i = 0; i < controls.length; i++) { - new ControlEvent(controls[i], ctrlSchedules[i], i); - } - } - - // --------------------------------------------------------------------- - - /** - * Adds a new event to be scheduled, specifying the number of time units of - * delay, and the execution order parameter. - * - * @param time - * The actual time at which the next event should be scheduled. - * @param order - * The index used to specify the order in which control events - * should be executed, if they happen to be at the same time, - * which is typically the case. - * @param event - * The control event - */ - static void addControlEvent(long time, int order, ControlEvent event) { - // we don't check whether time is negative or in the past: we trust - // the caller, which must be from this package - if (time >= endtime) - return; - heap.add(time, event, null, (byte) 0, order); - } - - // --------------------------------------------------------------------- - - /** - * This method is used to check whether the current configuration can be - * used for event driven simulations. It checks for the existence of config - * parameter {@value #PAR_ENDTIME}. - */ - public static final boolean isConfigurationEventDriven() { - return Configuration.contains(PAR_ENDTIME); - } - - // --------------------------------------------------------------------- - - /** - * Execute and remove the next event from the ordered event list. - * - * @return true if the execution should be stopped. - */ - private static boolean executeNext() { - PriorityQ.Event ev = heap.removeFirst(); - if (ev == null) { - System.err.println("EDSimulator: queue is empty, quitting" - + " at time " + CommonState.getTime()); - return true; - } - - long time = ev.time; - - if (time >= nextlog) { - // System.err.println("Current time: " + time); - // seemingly complicated: to prevent overflow - while (time - nextlog >= logtime) - nextlog += logtime; - if (endtime - nextlog >= logtime) - nextlog += logtime; - else - nextlog = endtime; - } - if (time >= endtime) { - System.err.println("EDSimulator: reached end time, quitting," - + " leaving " + heap.size() - + " unprocessed events in the queue"); - return true; - } - - CommonState.setTime(time); - int pid = ev.pid; - if (ev.node == null) { - // might be control event; handled through a special method - ControlEvent ctrl = null; - try { - ctrl = (ControlEvent) ev.event; - } catch (ClassCastException e) { - throw new RuntimeException( - "No destination specified (null) for event " + ev); - } - return ctrl.execute(); - } else if (ev.node != Network.prototype && ev.node.isUp()) { - CommonState.setPid(pid); - CommonState.setNode(ev.node); - if (ev.event instanceof NextCycleEvent) { - NextCycleEvent nce = (NextCycleEvent) ev.event; - nce.execute(); - } else { - EDProtocol prot = null; - try { - prot = (EDProtocol) ev.node.getProtocol(pid); - // System.out.println("prot "+prot.getClass().getName()); - } catch (ClassCastException e) { - e.printStackTrace(); - throw new IllegalArgumentException("Protocol " - + Configuration.lookupPid(pid) - + " does not implement EDProtocol; " - + ev.event.getClass()); - } - prot.processEvent(ev.node, pid, ev.event); - } - } - - return false; - } - - // --------------------------------------------------------------------- - // Public methods - // --------------------------------------------------------------------- - - /** - * Runs an experiment, resetting everything except the random seed. - */ - public static void nextExperiment() { - // Reading parameter - if (Configuration.contains(PAR_PQ)) - heap = (PriorityQ) Configuration.getInstance(PAR_PQ); - else - heap = new Heap(); - endtime = Configuration.getLong(PAR_ENDTIME); - if (CommonState.getEndTime() < 0) // not initialized yet - CommonState.setEndTime(endtime); - if (heap.maxTime() < endtime) - throw new IllegalParameterException(PAR_ENDTIME, - "End time is too large: configured event queue only" - + " supports " + heap.maxTime()); - logtime = Configuration.getLong(PAR_LOGTIME, Long.MAX_VALUE); - - // initialization - System.err.println("EDSimulator: resetting"); - CommonState.setPhase(CommonState.PHASE_UNKNOWN); - CommonState.setTime(0); // needed here - controls = null; - ctrlSchedules = null; - nextlog = 0; - Network.reset(); - System.err.println("EDSimulator: running initializers"); - runInitializers(); - scheduleControls(); - // Perform the actual simulation; executeNext() will tell when to - // stop. - boolean exit = false; - while (!exit) { - exit = executeNext(); - } - - // analysis after the simulation - CommonState.setPhase(CommonState.POST_SIMULATION); - for (int j = 0; j < controls.length; ++j) { - if (ctrlSchedules[j].fin) - controls[j].execute(); - } - - } - - // --------------------------------------------------------------------- - - /** - * Adds a new event to be scheduled, specifying the number of time units of - * delay, and the node and the protocol identifier to which the event will - * be delivered. - * - * @param delay - * The number of time units before the event is scheduled. Has to - * be non-negative. - * @param event - * The object associated to this event - * @param node - * The node associated to the event. - * @param pid - * The identifier of the protocol to which the event will be - * delivered - */ - public static void add(long delay, Object event, Node node, int pid) { - //if (event instanceof NextCycleEvent) - //System.err.println("************* edsim delay="+delay +" pid="+pid+" event="+event+" time="+CommonState.getTime()); - if (Simulator.getSimID() == 2){ - PSGSimulator.add(delay, event, node, pid); - } - - else { - if (delay < 0) - throw new IllegalArgumentException("Protocol " - + node.getProtocol(pid) + " is trying to add event " - + event + " with a negative delay: " + delay); - if (pid > Byte.MAX_VALUE) - throw new IllegalArgumentException( - "This version does not support more than " - + Byte.MAX_VALUE + " protocols"); - - long time = CommonState.getTime(); - if (endtime - time > delay) // check like this to deal with overflow - heap.add(time + delay, event, node, (byte) pid); - } - } - -} diff --git a/contrib/psg/src/peersim/edsim/Heap.java b/contrib/psg/src/peersim/edsim/Heap.java deleted file mode 100644 index eb123acd82..0000000000 --- a/contrib/psg/src/peersim/edsim/Heap.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (c) 2001 The Anthill Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.edsim; - -import peersim.core.Node; -import peersim.core.CommonState; -import peersim.config.Configuration; -import peersim.config.IllegalParameterException; - -/** - * The Heap data structure used to maintain events "sorted" by - * scheduled time and to obtain the next event to be executed. - * - * @author Alberto Montresor - * @version $Revision: 1.10 $ - */ -public class Heap implements PriorityQ { - -//-------------------------------------------------------------------------- -// Constants -//-------------------------------------------------------------------------- - -/** - * This parameter specifies how many - * bits are used to order events that occur at the same time. Defaults - * to 8. A value smaller than 8 causes an IllegalParameterException. - * Higher values allow for a better discrimination, but reduce - * the maximal time steps that can be simulated. - * @config - */ -private static final String PAR_PBITS = "pbits"; -private static final String PAR_PBITS_LEGACY = "simulation.timebits"; - -/** - * Specifies the initial capacity of the heap. Defaults to 65536. - * @config - */ -private static final String PAR_SIZE = "size"; - - -//-------------------------------------------------------------------------- -// Fields -//-------------------------------------------------------------------------- - -// The following arrays are four heaps ordered by time. The alternative -// approach (i.e. to store event objects) requires much more memory, -// and based on some tests that I've done is not really much faster. - -/** Event component of the heap */ -private Object[] events; - -/** Time component of the heap */ -private long[] times; - -/** Node component of the heap */ -private Node[] nodes; - -/** Pid component of the heap */ -private byte[] pids; - -/** Number of elements */ -private int size; - -/** Singleton event object used to return (event, time, node, pid) tuples */ -private final Event ev = new Event(); - -/** The number of bits reserved to order event with the same timestamp */ -private final int pbits; - -/** The mask to test whether the time value fits into the range we can -represent */ -private final long overflowMask; - -//-------------------------------------------------------------------------- -// Contructor -//-------------------------------------------------------------------------- - -/** - * Initializes a new heap using defaults. - */ -public Heap() { - this(""); // "" is not a valid prefix for a component -} - -//-------------------------------------------------------------------------- - -/** - * Initializes a new heap using the configuration. - */ -public Heap(String prefix) { - - int size = Configuration.getInt(prefix+"."+PAR_SIZE,65536); - - // some complex stuff to deal with legacy parameter names... - if( !Configuration.contains(PAR_PBITS_LEGACY) ) - pbits = Configuration.getInt(prefix+"."+PAR_PBITS,8); - else - { - pbits = Configuration.getInt(PAR_PBITS_LEGACY); - if( Configuration.contains(prefix+"."+PAR_PBITS) ) - throw new IllegalParameterException(PAR_PBITS_LEGACY, - "Your configuration file contains both "+ - prefix+"."+PAR_PBITS+ " and "+ - PAR_PBITS_LEGACY+"; please remove "+ - PAR_PBITS_LEGACY); - } - - if (pbits < 8 || pbits >= 31) { - throw new IllegalParameterException(prefix+"."+PAR_PBITS, - "This parameter should be >= 8 or < 31"); - } - overflowMask = ~maxTime(); - events = new Object[size]; - times = new long[size]; - nodes = new Node[size]; - pids = new byte[size]; -} - -//-------------------------------------------------------------------------- -// Methods -//-------------------------------------------------------------------------- - -/** - * Returns the current number of events in the system. - */ -public int size() -{ - return size; -} - -//-------------------------------------------------------------------------- - -/** - * Add a new event, to be scheduled at the specified time. - * - * @param time the time at which this event should be scheduled - * @param event the object describing the event - * @param node the node at which the event has to be delivered - * @param pid the protocol that handles the event - */ -public void add(long time, Object event, Node node, byte pid) -{ - add(time,event,node,pid,CommonState.r.nextInt(1 << pbits)); -} - -//-------------------------------------------------------------------------- - -/** - * Add a new event, to be scheduled at the specified time. - * - * @param time the time at which this event should be scheduled - * @param event the object describing the event - * @param node the node at which the event has to be delivered - * @param pid the protocol that handles the event - */ -public void add(long time, Object event, Node node, byte pid, long priority) -{ - if( (time&overflowMask) != 0 ) throw new - IllegalArgumentException("Time overflow: time="+time); -//XXX should we test priority overflow? How much does it cost? - - time = (time << pbits) | priority; - - size++; - int pos = size; - put(pos, time, event, node, pid); - while (pos > 1 && getTime(pos / 2) > time) { - swap(pos, pos / 2); - pos = pos / 2; - } -} - -//-------------------------------------------------------------------------- - -/** - * Removes the first event in the heap and returns it. - * Note that, to avoid garbage collection, a singleton instance of - * the Event class is used. This means that data contained in the - * returned event are overwritten when a new invocation of this - * method is performed. - * @return first event or null if size is zero - */ -public Event removeFirst() { - - if(size==0) return null; - - ev.time = times[0] >> pbits; - ev.event = events[0]; - ev.node = nodes[0]; - ev.pid = pids[0]; - swap(1, size); - size--; - minHeapify(1); - return ev; -} - -//-------------------------------------------------------------------------- - -public long maxTime() { return Long.MAX_VALUE >> pbits; } - -//-------------------------------------------------------------------------- - -public long maxPriority() { return (1L << pbits)-1; } - -//-------------------------------------------------------------------------- - -/** - * Prints the time values contained in the heap. - */ -public String toString() -{ - StringBuffer buffer = new StringBuffer(); - buffer.append("[Size: " + size + " Times: "); - for (int i=1; i <= size; i++) { - buffer.append(getTime(i)+","); - } - buffer.append("]"); - return buffer.toString(); -} - - -//-------------------------------------------------------------------------- -// Private methods -//-------------------------------------------------------------------------- - -/** - * - */ -private void minHeapify(int index) -{ - // The time to be placed of the current node - long time = getTime(index); - // Left, right children of the current index - int l,r; - // Their associated time - long lt, rt; - // The minimum time between val, lt, rt - long mintime; - // The index of the mininum time - int minindex = index; - do { - index = minindex; - mintime = time; - l = index << 1; - r = l + 1; - if (l <= size && (lt = getTime(l)) < mintime) { - minindex = l; - mintime = lt; - } - if (r <= size && (rt = getTime(r)) < mintime) { - minindex = r; - mintime = rt; - } - if (minindex != index) { - swap(minindex, index); - } - } while (minindex != index); -} - -//-------------------------------------------------------------------------- - -/** - * - */ -private void swap(int i1, int i2) { - - i1--; - i2--; - - Object te = events[i1]; - events[i1] = events[i2]; - events[i2] = te; - - long tt = times[i1]; - times[i1] = times[i2]; - times[i2] = tt; - - Node tn = nodes[i1]; - nodes[i1] = nodes[i2]; - nodes[i2] = tn; - - byte tp = pids[i1]; - pids[i1] = pids[i2]; - pids[i2] = tp; -} - -//-------------------------------------------------------------------------- - -/** - * - */ -private long getTime(int index) { - /* Compute first and second index, and return the value */ - index--; - return times[index]; -} - -//-------------------------------------------------------------------------- - -/** - * - */ -private void put(int index, long time, Object event, Node node, byte pid) { - - index--; - if (index >= events.length) { - doubleCapacity(); - } - events[index] = event; - times[index] = time; - nodes[index] = node; - pids[index] = pid; -} - -//-------------------------------------------------------------------------- - -/** - * - */ -private void doubleCapacity() { - int oldsize = events.length; - int newsize = oldsize*2; - Object[] te = new Object[newsize]; - System.arraycopy(events, 0, te, 0, oldsize); - events = te; - long[] tt = new long[newsize]; - System.arraycopy(times, 0, tt, 0, oldsize); - times = tt; - Node[] tn = new Node[newsize]; - System.arraycopy(nodes, 0, tn, 0, oldsize); - nodes = tn; - byte[] tp = new byte[newsize]; - System.arraycopy(pids, 0, tp, 0, oldsize); - pids = tp; -} - -//-------------------------------------------------------------------------- -// Testing -//-------------------------------------------------------------------------- - -/* -public static void main(String[] args) { - Random random = new Random(); - Heap heap = new Heap(); - int rep = 1000000; - if( args.length > 0 ) rep = Integer.parseInt(args[0]); - int[] values1 = new int[rep]; - long[] values2 = new long[rep]; - for (int i = 0; i < rep; i++) { - values1[i] = random.nextInt(1000000000); - } - - long time1 = System.currentTimeMillis(); - for (int i = 0; i < rep; i++) { - heap.add(values1[i], null, null, (byte) 1); - } - long time2 = System.currentTimeMillis(); - System.out.println("Inserting: " + (time2-time1)); - - time1 = System.currentTimeMillis(); - for (int i = 0; i < rep; i++) { - values2[i] = heap.removeFirst().time; - } - time2 = System.currentTimeMillis(); - System.out.println("Removing: " + (time2-time1)); - - Arrays.sort(values1); - for (int i=0; i - * Note that reimplementing method {@link #nextDelay} of this class allows for - * arbitrary scheduling, including adaptively changing or irregular cycle - * lengths, etc. - * - * @see CDScheduler - * @see CDProtocol - */ -public class NextCycleEvent implements Cloneable { - - // =============================== initialization ====================== - // ===================================================================== - - /** - * Reads configuration to initialize the object. Extending classes should - * have a constructor with the same signature, often as simple as - * super(n). - */ - public NextCycleEvent(String n) { - } - - // -------------------------------------------------------------------- - - /** - * Returns a clone of the object. Overriding this method is necessary and - * typically is as simple as return super.clone(). In general, - * always use super.clone() to obtain the object to be returned - * on which you can perform optional deep cloning operations (arrays, etc). - */ - public Object clone() throws CloneNotSupportedException { - - return super.clone(); - } - - // ========================== methods ================================== - // ===================================================================== - - /** - * Executes the nextCycle method of the protocol, and schedules the next - * call using the delay returned by {@link #nextDelay}. If the next - * execution time as defined by the delay is outside of the valid times as - * defined by {@link CDScheduler#sch}, then the next event is not scheduled. - * Note that this means that this protocol will no longer be scheduled - * because the next event after the next event is scheduled by the next - * event. - */ - public final void execute() { - - int pid = CommonState.getPid(); - Node node = CommonState.getNode(); - CDProtocol cdp = (CDProtocol) node.getProtocol(pid); - cdp.nextCycle(node, pid); - long delay = nextDelay(CDScheduler.sch[pid].step); - - if (CommonState.getTime() + delay < CDScheduler.sch[pid].until) - EDSimulator.add(delay, this, node, pid); - } - - // -------------------------------------------------------------------- - - /** - * Calculates the delay until the next execution of the protocol. This - * default implementation returns a constant delay equal to the step - * parameter (cycle length in this case) of the schedule of this event (as - * set in the config file). - */ - protected long nextDelay(long step) { - - return step; - } - -} diff --git a/contrib/psg/src/peersim/edsim/PriorityQ.java b/contrib/psg/src/peersim/edsim/PriorityQ.java deleted file mode 100644 index 5525768485..0000000000 --- a/contrib/psg/src/peersim/edsim/PriorityQ.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c)2008 The Peersim Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.edsim; - -import peersim.core.Node; - -/** - * The interface to be implemented by the event queue of the evend based - * engine. An implementation must also provide the standard cosntructor - * required by any peersim components: one that takes a String argument, - * the component name in the configuration. - */ -public interface PriorityQ { - - -/** - * Returns the current number of events in the queue. - */ -public int size(); - -/** - * Add a new event, to be scheduled at the specified time. If there are other - * events scheduled at the same time, then the time of execution if this event - * relative to the other events is unspecified. - * - * @param time The time at which this event should be scheduled. It is - * guaranteed to be non-negative (so no extra checks are needed) - * @param event the object describing the event - * @param node the node at which the event has to be delivered - * @param pid the protocol that handles the event - */ -public void add(long time, Object event, Node node, byte pid); - -/** - * Add a new event, to be scheduled at the specified time, specifying also - * the priority of the event, should there be other events scheduled at the - * same time. If both time and priority is the same for an event, then the - * scheduling order is unspecified. - * - * @param time The time at which this event should be scheduled. It is - * guaranteed to be non-negative (so no extra checks are needed) - * @param event the object describing the event - * @param node the node at which the event has to be delivered - * @param pid the protocol that handles the event - * @param priority if for two events the "time" value is the same, this - * value should be used to order them. Lower value means higher priority. - * Like with time, non-negativity as assumed. - */ -public void add(long time, Object event, Node node, byte pid, long priority); - -/** - * Removes the first event in the heap and returns it. - * The returned object is not guaranteed to be a freshly generated object, - * that is, we allow for an implementation that keeps one copy of an event - * object and always returns a reference to that copy. - * @return first event or null if size is zero - */ -public Event removeFirst(); - -/** -* Maximal value of time this interpretation can represent. -*/ -public long maxTime(); - -/** -* Maximal value of priority this interpretation can deal with. That is, -* the number of different priority levels is maxPriority()+1 because -* 0 is also a valid level. -* @see #add(long,Object,Node,byte,long) -*/ -public long maxPriority(); - -/** - * Return type of {@link #removeFirst()}. - */ -public class Event -{ - public Object event; - public long time; - public Node node; - public byte pid; - public String toString() { - return event+" to node "+node+"prot "+pid+"at "+time; } -} - -} diff --git a/contrib/psg/src/peersim/edsim/RandNextCycle.java b/contrib/psg/src/peersim/edsim/RandNextCycle.java deleted file mode 100644 index b74a4f409a..0000000000 --- a/contrib/psg/src/peersim/edsim/RandNextCycle.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.edsim; - -import peersim.core.*; - - -/** -* Implements random delay between calling the nextCycle method of the protocol. -* @see #nextDelay -*/ -public class RandNextCycle extends NextCycleEvent { - - -// =============================== initialization ====================== -// ===================================================================== - - -/** -* Calls super constructor. -*/ -public RandNextCycle(String n) { super(n); } - -// -------------------------------------------------------------------- - -/** -* Calls super.clone(). -*/ -public Object clone() throws CloneNotSupportedException { - - return super.clone(); -} - - -// ========================== methods ================================== -// ===================================================================== - - -/** -* Returns a random delay with uniform distribution between 1 (inclusive) and -* 2*step (exclusive) -* (expected value is therefore step). -*/ -protected long nextDelay(long step) { - - return 1+CommonState.r.nextLong((step<<1)-1); -} - - -} - - diff --git a/contrib/psg/src/peersim/edsim/RegRandNextCycle.java b/contrib/psg/src/peersim/edsim/RegRandNextCycle.java deleted file mode 100644 index dbc5edb675..0000000000 --- a/contrib/psg/src/peersim/edsim/RegRandNextCycle.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.edsim; - -import peersim.core.*; - - -/** -* Implements a random delay, but making sure there is exactly one call in each -* consecutive step time units. -*/ -public class RegRandNextCycle extends NextCycleEvent { - -// ============================== fields ============================== -// ==================================================================== - -/** -* Indicates the start of the next cycle for a particular protocol -* instance. If negative it means it has not been initialized yet. -*/ -private long nextCycleStart = -1; - -// =============================== initialization ====================== -// ===================================================================== - - -/** -* Calls super constructor. -*/ -public RegRandNextCycle(String n) { - - super(n); -} - -// -------------------------------------------------------------------- - -/** -* Calls super.clone(). -*/ -public Object clone() throws CloneNotSupportedException { - - return super.clone(); -} - - -// ========================== methods ================================== -// ===================================================================== - - -/** -* Returns a random delay but making sure there is exactly one invocation in each -* consecutive interval of length step. The beginning of these -* intervals is defined by the first invocation which is in turn defined by -* {@link CDScheduler} that initiates the protocol in question. -*/ -protected long nextDelay(long step) { - - // at this point nextCycleStart points to the start of the next cycle - // (the cycle after the one in which this execution is taking place) - // (note that the start of the cycle is included in the cycle) - - final long now = CommonState.getTime(); - if(nextCycleStart<0) - { - // not initialized - nextCycleStart=now+step; - } - - // to be on the safe side, we do the next while loop. - // although currently it never executes - while(nextCycleStart<=now) nextCycleStart+=step; - - // we increment nextCycleStart to point to the start of the cycle - // after the next cycle - nextCycleStart+=step; - - return nextCycleStart-now-CommonState.r.nextLong(step)-1; -} - -} - - diff --git a/contrib/psg/src/peersim/edsim/edsim_jsp.xmi b/contrib/psg/src/peersim/edsim/edsim_jsp.xmi deleted file mode 100644 index 5fba52dfcc..0000000000 --- a/contrib/psg/src/peersim/edsim/edsim_jsp.xmi +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/contrib/psg/src/peersim/edsim/edsim_kdm.xmi b/contrib/psg/src/peersim/edsim/edsim_kdm.xmi deleted file mode 100644 index db34498391..0000000000 --- a/contrib/psg/src/peersim/edsim/edsim_kdm.xmi +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/contrib/psg/src/peersim/graph/BitMatrixGraph.java b/contrib/psg/src/peersim/graph/BitMatrixGraph.java deleted file mode 100644 index 7e88fecd9d..0000000000 --- a/contrib/psg/src/peersim/graph/BitMatrixGraph.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.graph; - -import java.util.*; - -/** -* This class implements a graph which uses a bitmatrix as inner representation -* of edges. -*/ -public class BitMatrixGraph implements Graph { - - -// ====================== private fileds ======================== -// ============================================================== - -private final List sets; - -private final boolean directed; - -// ====================== public constructors =================== -// ============================================================== - - -/** -* Constructs a directed graph with the given number of nodes. -* The graph has no edges initially. The graph is directed. -* @param n size of graph -*/ -public BitMatrixGraph( int n ) { - - this(n,true); -} - -// --------------------------------------------------------------- - -/** -* Constructs an graph with the given number of nodes. -* The graph has no edges initially. -* @param n size of graph -* @param directed if true graph is directed -*/ -public BitMatrixGraph( int n, boolean directed ) { - - sets = new ArrayList(n); - for(int i=0; i getNeighbours(int i) { - - Set result = new HashSet(); - BitSet neighb = sets.get(i); - final int max = size(); - for(int j=0; j size() || j > size() || i<0 || j<0 ) throw new - IndexOutOfBoundsException(); - - BitSet neighb = sets.get(i); - boolean old = neighb.get(j); - neighb.set(j); - - if( !old && !directed ) - { - neighb = sets.get(j); - neighb.set(i); - } - - return !old; -} - -// -------------------------------------------------------------------- - -public boolean clearEdge(int i, int j) { - - if( i > size() || j > size() || i<0 || j<0 ) throw new - IndexOutOfBoundsException(); - - BitSet neighb = sets.get(i); - boolean old = neighb.get(j); - neighb.clear(j); - - if( old && !directed ) - { - neighb = sets.get(i); - neighb.clear(j); - } - - return old; -} - -// -------------------------------------------------------------------- - -public int degree(int i) { - - BitSet neighb = sets.get(i); - return neighb.cardinality(); // only from jdk 1.4 -} - -} - diff --git a/contrib/psg/src/peersim/graph/ConstUndirGraph.java b/contrib/psg/src/peersim/graph/ConstUndirGraph.java deleted file mode 100644 index 3aac06fdf9..0000000000 --- a/contrib/psg/src/peersim/graph/ConstUndirGraph.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.graph; - -import java.util.*; - -/** -* This class is an adaptor making any Graph an undirected graph -* by making its edges bidirectional. The graph to be made undirected -* is passed to the constructor. Only the reference is stored. -* However, at construction time the incoming edges are stored -* for each node, so if the graph -* passed to the constructor changes over time then -* methods {@link #getNeighbours(int)} and {@link #degree(int)} -* become inconsistent (but only those). -* The upside of this inconvenience is that {@link #getNeighbours} will have -* constant time complexity. -* @see UndirectedGraph -*/ -public class ConstUndirGraph implements Graph { - - -// ====================== private fileds ======================== -// ============================================================== - - -protected final Graph g; - -protected final List[] in; - -// ====================== public constructors =================== -// ============================================================== - -/** -* Initialization based on given graph. Stores the graph and if necessary -* (if the graph is directed) searches for the incoming edges and stores -* them too. The given graph is stored by reference (not cloned) so it should -* not be modified while this object is in use. -*/ -public ConstUndirGraph( Graph g ) { - - this.g = g; - if( !g.directed() ) - { - in = null; - } - else - { - in = new List[g.size()]; - } - - initGraph(); -} - -// -------------------------------------------------------------- - -/** Finds and stores incoming edges */ -protected void initGraph() { - - final int max = g.size(); - for(int i=0; i(); - for(int i=0; i getNeighbours(int i) { - - List result = new ArrayList(); - result.addAll(g.getNeighbours(i)); - if( in != null ) result.addAll(in[i]); - return Collections.unmodifiableCollection(result); -} - -// --------------------------------------------------------------- - -/** Returns the node from the underlying graph */ -public Object getNode(int i) { return g.getNode(i); } - -// --------------------------------------------------------------- - -/** -* If there is an (i,j) edge, returns that, otherwise if there is a (j,i) -* edge, returns that, otherwise returns null. -*/ -public Object getEdge(int i, int j) { - - if( g.isEdge(i,j) ) return g.getEdge(i,j); - if( g.isEdge(j,i) ) return g.getEdge(j,i); - return null; -} - -// --------------------------------------------------------------- - -public int size() { return g.size(); } - -// -------------------------------------------------------------------- - -public boolean directed() { return false; } - -// -------------------------------------------------------------------- - -/** not supported */ -public boolean setEdge( int i, int j ) { - - throw new UnsupportedOperationException(); -} - -// --------------------------------------------------------------- - -/** not supported */ -public boolean clearEdge( int i, int j ) { - - throw new UnsupportedOperationException(); -} - -// --------------------------------------------------------------- - -public int degree(int i) { return g.degree(i)+(in==null?0:in[i].size()); } - -// --------------------------------------------------------------- -/* -public static void main( String[] args ) { - - Graph net = new BitMatrixGraph(20); - GraphFactory.wireKOut(net,5,new Random()); - ConstUndirGraph ug = new ConstUndirGraph(net); - for(int i=0; i(); - triangle[i] = new BitSet(i); - } - - for(int i=0; ij) // make sure i>j - triangle[i].set(j); - else - triangle[j].set(i); - } - } -} - - -// ============================ Graph functions ==================== -// ================================================================= - - -public boolean isEdge(int i, int j) -{ - // make sure i>j - if (i getNeighbours(int i); - - /** - * Returns the node object associated with the index. Optional - * operation. - */ - Object getNode(int i); - - /** - * Returns the edge object associated with the index. Optional - * operation. - */ - Object getEdge(int i, int j); - - /** - * The number of nodes in the graph. - */ - int size(); - - /** - * Returns true if the graph is directed otherwise false. - */ - boolean directed(); - - /** - * Sets given edge, returns true if it did not exist before. - * If the graph is - * undirected, sets the edge (j,i) as well. Optional operation. - */ - public boolean setEdge(int i, int j); - - /** - * Removes given edge, returns true if it existed before. If the graph is - * undirected, removes the edge (j,i) as well. Optional operation. - */ - public boolean clearEdge(int i, int j); - - /** - * Returns the degree of the given node. If the graph is directed, - * returns out degree. - */ - public int degree(int i); -} diff --git a/contrib/psg/src/peersim/graph/GraphAlgorithms.java b/contrib/psg/src/peersim/graph/GraphAlgorithms.java deleted file mode 100644 index 6bbb3516ea..0000000000 --- a/contrib/psg/src/peersim/graph/GraphAlgorithms.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.graph; - -import java.util.*; - -/** -* Implements graph algorithms. The current implementation is NOT thread -* safe. Some algorithms are not static, many times the result of an -* algorithm can be read from non-static fields. -*/ -public class GraphAlgorithms { - -// =================== public fields ================================== -// ==================================================================== - -/** output of some algorithms is passed here */ -public int[] root = null; -private Stack stack = new Stack(); -private int counter=0; - -private Graph g=null; - -public final static int WHITE=0; -public final static int GREY=1; -public final static int BLACK=2; - -/** output of some algorithms is passed here */ -public int[] color = null; - -/** output of some algorithms is passed here */ -public Set cluster = null; - -/** output of some algorithms is passed here */ -public int[] d = null; - -// =================== private methods ================================ -// ==================================================================== - - -/** -* Collects nodes accessible from node "from" using depth-first search. -* Works on the array {@link #color} which must be of the same length as -* the size of the graph, and must contain values according to the -* following semantics: -* WHITE (0): not seen yet, GREY (1): currently worked upon. BLACK -* (other than 0 or 1): finished. -* If a negative color is met, it is saved in the {@link #cluster} set -* and is treated as black. This can be used to check if the currently -* visited cluster is weakly connected to another cluster. -* On exit no nodes are GREY. -* The result is the modified array {@link #color} and the modified set -* {@link #cluster}. -*/ -private void dfs( int from ) { - - color[from]=GREY; - - for(int j:g.getNeighbours(from)) - { - if( color[j]==WHITE ) - { - dfs(j); - } - else - { - if( color[j]<0 ) cluster.add(color[j]); - } - } - - color[from]=BLACK; -} - -// -------------------------------------------------------------------- - -/** -* Collects nodes accessible from node "from" using breadth-first search. -* Its parameters and side-effects are identical to those of dfs. -* In addition, it stores the shortest distances from "from" in {@link #d}, -* if it is not null. On return, d[i] contains the length of -* the shortest path from "from" to "i", if such a path exists, or it is -* unchanged (ie the original value of d[i] is kept, -* whatever that was. -* d must either be long enough or null. -*/ -private void bfs( int from ) { - - List q = new LinkedList(); - int u, du; - - q.add(from); - q.add(0); - if( d != null ) d[from] = 0; - - color[from]=GREY; - - while( ! q.isEmpty() ) - { - u = q.remove(0).intValue(); - du = q.remove(0).intValue(); - - for(int j:g.getNeighbours(u)) - { - if( color[j]==WHITE ) - { - color[j]=GREY; - - q.add(j); - q.add(du+1); - if( d != null ) d[j] = du+1; - } - else - { - if( color[j]<0 ) - cluster.add(color[j]); - } - } - color[u]=BLACK; - } -} - -// -------------------------------------------------------------------- - -/** The recursive part of the Tarjan algorithm. */ -private void tarjanVisit(int i) { - - color[i]=counter++; - root[i]=i; - stack.push(i); - - for(int j:g.getNeighbours(i)) - { - if( color[j]==WHITE ) - { - tarjanVisit(j); - } - if( color[j]>0 && color[root[j]](); - if( color==null || color.length ht = new Hashtable(); - for(j=0; j{@link #d}[j] returns the length of the shortest path between -* i and j. The value -1 indicates that j is not accessible from i. -*/ -public void dist( Graph g, int i ) { - - this.g=g; - if( d==null || d.lengthb[i]. -* The number of cycles performed is determined by b.length. -* In each cycle each node contacts a random neighbour and exchanges -* information. The simulation is generational: when a node contacts a neighbor -* in cycle i, it sees their state as in cycle i-1, besides, all nodes update -* their state at the same time point, synchronously. -*/ -public static void multicast( Graph g, int[] b, Random r ) { - - int c1[] = new int[g.size()]; - int c2[] = new int[g.size()]; - for(int i=0; i neighbours=null; - int black=1; - - int k=0; - for(; k it=neighbours.iterator(); - for(int j=r.nextInt(neighbours.size()); j>0; --j) - it.next(); - int randn = it.next(); - - // push pull exchane with random neighbour - if( c1[i]==BLACK ) //c2[i] is black too - { - if(c2[randn]==WHITE) ++black; - c2[randn]=BLACK; - } - else if( c1[randn]==BLACK ) - { - if(c2[i]==WHITE) ++black; - c2[i]=BLACK; - } - } - System.arraycopy(c2,0,c1,0,c1.length); - b[k]=black; - } - - for(; kb[i] contains the number of nodes -* reached in exactly i steps, and always b[0]=1. -* If the maximal distance from k is lower than b.length, -* then the remaining elements of b are zero. -*/ -public void flooding( Graph g, int[] b, int k ) { - - dist(g, k); - - for(int i=0; i= 0 && d[i] < b.length ) b[d[i]]++; - } -} - -// -------------------------------------------------------------------- - -/** Returns the strongly connected cluster roots with size as a value. -* Cluster membership can be seen from the content of the array {@link #root}; -* each node has the root of the strongly connected cluster it belongs to. -* A word of caution: for large graphs that have a large diameter and that -* are strongly connected (such as large rings) you can get stack overflow -* because of the large depth of recursion. -*/ -//XXX implement a non-recursive version ASAP!!! -public Map tarjan( Graph g ) { - - this.g=g; - stack.clear(); - if( root==null || root.length1): visited as the c-th node - // color is negative (c<1): inComponent true - for(int i=0; i ht = new Hashtable(); - for(int j=0; j0) - { - ht.put(j,color[j]); - } - } - - return ht; -} - -} - diff --git a/contrib/psg/src/peersim/graph/GraphFactory.java b/contrib/psg/src/peersim/graph/GraphFactory.java deleted file mode 100644 index 81857cc0e0..0000000000 --- a/contrib/psg/src/peersim/graph/GraphFactory.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.graph; - -import java.util.*; - -/** -* Contains static methods for wiring certain kinds of graphs. The general -* contract of all methods is that they accept any graph and add edges -* as specified in the documentation. -*/ -public class GraphFactory { - -/** Disable instance construction */ -private GraphFactory() {} - -// ===================== public static methods ====================== -// ================================================================== - -/** -* Wires a ring lattice. -* The added connections are defined as follows. If k is even, links to -* i-k/2, i-k/2+1, ..., i+k/2 are added (but not to i), thus adding an -* equal number of predecessors and successors. -* If k is odd, then we add one more successors than predecessors. -* For example, for k=4: 2 predecessors, 2 successors. -* For k=5: 2 predecessors, 3 successors. -* For k=1: each node is linked only to its successor. -* All values are understood mod n to make the lattice circular, where n is the -* number of nodes in g. -* @param g the graph to be wired -* @param k lattice parameter -* @return returns g for convenience -*/ -public static Graph wireRingLattice(Graph g, int k) { - - final int n = g.size(); - - int pred = k/2; - int succ = k-pred; - - for(int i=0; i -* Note that it is possible to pass an undirected graph as a parameter. In that -* case the output is the directed graph produced by the method, converted to -* an undirected graph by dropping directionality of the edges. This graph is -* still not from the original undirected WS model though. -* @param g the graph to be wired -* @param k lattice parameter: this is the out-degree of a node in the -* ring lattice before rewiring -* @param p the probability of rewiring each -* @param r source of randomness -* @return returns g for convenience -*/ -public static Graph wireWS( Graph g, int k, double p, Random r ) { -//XXX unintuitive to call it WS due to the slight mods - final int n = g.size(); - for(int i=0; i= i ) newedge++; // random _other_ node - } - g.setEdge(i,newedge); - } - return g; -} - -// ------------------------------------------------------------------- - -/** -* Random graph. Generates randomly k directed edges out of each node. -* The neighbors -* (edge targets) are chosen randomly without replacement from the nodes of the -* graph other than the source node (i.e. no loop edge is added). -* If k is larger than N-1 (where N is the number of nodes) then k is set to -* be N-1 and a complete graph is returned. -* @param g the graph to be wired -* @param k samples to be drawn for each node -* @param r source of randomness -* @return returns g for convenience -*/ -public static Graph wireKOut( Graph g, int k, Random r ) { - - final int n = g.size(); - if( n < 2 ) return g; - if( n <= k ) k=n-1; - int[] nodes = new int[n]; - for(int i=0; i0) - { - int j = i^mask; - if(j> 1; - } - - } - return g; -} - -// ------------------------------------------------------------------- - -/** -* This contains the implementation of the Barabasi-Albert model -* of growing scale free networks. The original model is described in -* -http://arxiv.org/abs/cond-mat/0106096. -* It also works if the graph is directed, in which case the model is a -* variation of the BA model -* described in -http://arxiv.org/pdf/cond-mat/0408391. In both cases, the number of the -* initial set of nodes is the same as the degree parameter, and no links are -* added. The first added node is connected to all of the initial nodes, -* and after that the BA model is used normally. -* @param k the number of edges that are generated for each new node, also -* the number of initial nodes (that have no edges). -* @param r the randomness to be used -* @return returns g for convenience -*/ -public static Graph wireScaleFreeBA( Graph g, int k, Random r ) { - - final int nodes = g.size(); - if( nodes <= k ) return g; - - // edge i has ends (ends[2*i],ends[2*i+1]) - int[] ends = new int[2*k*(nodes-k)]; - - // Add initial edges from k to 0,1,...,k-1 - for(int i=0; i < k; i++) - { - g.setEdge(k,i); - ends[2*i]=k; - ends[2*i+1]=i; - } - - int len = 2*k; // edges drawn so far is len/2 - for(int i=k+1; i < nodes; i++) // over the remaining nodes - { - for (int j=0; j < k; j++) // over the new edges - { - int target; - do - { - target = ends[r.nextInt(len)]; - int m=0; - while( m it=g.getNeighbours(i).iterator(); - while(it.hasNext()) - { - final int j = it.next(); - if(g.directed()) - out.println(i+" -> "+j+";"); - else if( i<=j ) - out.println(i+" -- "+j+";"); - } - } - - out.println("}"); -} - -// ------------------------------------------------------------------ - -/** -* Saves the given graph to -* the given stream in GML format. -*/ -public static void writeGML( Graph g, PrintStream out ) { - - out.println("graph [ directed "+(g.directed()?"1":"0")); - - for(int i=0; i -*

  • 1: Begins with cacheSize in binary format (int), followed by the -* numberOfNodes (int), and then a continuous series of exactly -* numberOfNodes records, where a record describes a node's -* neighbours and their timestamps. -* A record is a series of exactly cacheSize (int,long) pairs where -* the int is the node id, and the long is the timestamp. -* Node id-s start from 1. Node id 0 means no node and used if the parent -* node has less that cacheSize nodes.
  • -* -* @param file Filename to read -* @param direction If 0, the original directionality is preserved, if 1, -* than each edge is reversed, if 2 then directionality is dropped and the -* returned graph will be undirected. -*/ -public static Graph readNewscastGraph( String file, int direction ) -throws IOException { - - NeighbourListGraph gr = new NeighbourListGraph( direction != 2 ); - FileInputStream fis = new FileInputStream(file); - DataInputStream dis = new DataInputStream(fis); - - dis.readByte(); - dis.readByte(); - dis.readByte(); - - final int MODE = dis.readInt(); - if( MODE != 1 ) throw new IOException("Unknown mode "+MODE); - - final int CACHESIZE = dis.readInt(); - final int GRAPHSIZE = dis.readInt(); - -//System.out.println("header: "+MODE+" "+CACHESIZE+" "+GRAPHSIZE); - - for(int i=1; i<=GRAPHSIZE; ++i) - { - int iind = gr.addNode(i); - - for(int j=0; j nodes; - -/** -* Contains the indices of the nodes. The vector "nodes" contains this -* information implicitly but this way we can find indexes in log time at -* the cost of memory (node that the edge lists typically use much more memory -* than this anyway). Note that the nodes vector is still necessary to -* provide constant access to nodes based on indexes. -*/ -private final HashMap nodeindex; - -/** Contains sets of node indexes. If "nodes" is not null, indices are -* defined by "nodes", otherwise they correspond to 0,1,... */ -private final ArrayList> neighbors; - -/** Indicates if the graph is directed. */ -private final boolean directed; - -// =================== public constructors ====================== -// =============================================================== - -/** -* Constructs an empty graph. That is, the graph has zero nodes, but any -* number of nodes and edges can be added later. -* @param directed if true the graph will be directed -*/ -public NeighbourListGraph( boolean directed ) { - - nodes = new ArrayList(1000); - neighbors = new ArrayList>(1000); - nodeindex = new HashMap(1000); - this.directed = directed; -} - -// --------------------------------------------------------------- - -/** -* Constructs a graph with a fixed size without edges. If the graph is -* constructed this way, it is not possible to associate objects to nodes, -* nor it is possible to grow the graph using {@link #addNode}. -* @param directed if true the graph will be directed -*/ -public NeighbourListGraph( int size, boolean directed ) { - - nodes = null; - neighbors = new ArrayList>(size); - for(int i=0; i()); - nodeindex = null; - this.directed = directed; -} - -// =================== public methods ============================= -// ================================================================ - -/** -* If the given object is not associated with a node yet, adds a new -* node. Returns the index of the node. If the graph was constructed to have -* a specific size, it is not possible to add nodes and therefore calling -* this method will throw an exception. -* @throws NullPointerException if the size was specified at construction time. -*/ -public int addNode( Object o ) { - - Integer index = nodeindex.get(o); - if( index == null ) - { - index = nodes.size(); - nodes.add(o); - neighbors.add(new HashSet()); - nodeindex.put(o,index); - } - - return index; -} - - -// =================== graph implementations ====================== -// ================================================================ - - -public boolean setEdge( int i, int j ) { - - boolean ret = neighbors.get(i).add(j); - if( ret && !directed ) neighbors.get(j).add(i); - return ret; -} - -// --------------------------------------------------------------- - -public boolean clearEdge( int i, int j ) { - - boolean ret = neighbors.get(i).remove(j); - if( ret && !directed ) neighbors.get(j).remove(i); - return ret; -} - -// --------------------------------------------------------------- - -public boolean isEdge(int i, int j) { - - return neighbors.get(i).contains(j); -} - -// --------------------------------------------------------------- - -public Collection getNeighbours(int i) { - - return Collections.unmodifiableCollection(neighbors.get(i)); -} - -// --------------------------------------------------------------- - -/** If the graph was gradually grown using {@link #addNode}, returns the -* object associated with the node, otherwise null */ -public Object getNode(int i) { return (nodes==null?null:nodes.get(i)); } - -// --------------------------------------------------------------- - -/** -* Returns null always. -*/ -public Object getEdge(int i, int j) { return null; } - -// --------------------------------------------------------------- - -public int size() { return neighbors.size(); } - -// -------------------------------------------------------------------- - -public boolean directed() { return directed; } - -// -------------------------------------------------------------------- - -public int degree(int i) { return neighbors.get(i).size(); } -} - - - - diff --git a/contrib/psg/src/peersim/graph/PrefixSubGraph.java b/contrib/psg/src/peersim/graph/PrefixSubGraph.java deleted file mode 100644 index 5098316eea..0000000000 --- a/contrib/psg/src/peersim/graph/PrefixSubGraph.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.graph; - -import java.util.*; - -/** -* This class is an adaptor for representing special subgraphs of any graph. -* It can represent the subgraphs spanned by the nodes 0,...,i where -* i is less than or equal to n-1, the last node of the original graph. -* The underlying graph is stored by reference. This means that if the -* graph changes, then these changes will be reflected by this class as well. -* Besides, the size of the prefix can be changed at will at any time -* using {@link #setSize}. -*/ -public class PrefixSubGraph implements Graph { - - -// ====================== private fileds ======================== -// ============================================================== - - -private final Graph g; - -/** The graph represents the subgraph defined by nodes 0,...,prefSize */ -private int prefSize; - - -// ====================== public constructors =================== -// ============================================================== - - -/** -* Constructs an initially max size subgraph of g. That is, the subgraph will -* contain all nodes. -*/ -public PrefixSubGraph( Graph g ) { - - this.g = g; - prefSize = g.size(); -} - - -// ======================= Graph implementations ================ -// ============================================================== - - -public boolean isEdge(int i, int j) { - - if( i<0 || i>=prefSize ) throw new IndexOutOfBoundsException(); - if( j<0 || j>=prefSize ) throw new IndexOutOfBoundsException(); - return g.isEdge(i,j); -} - -// --------------------------------------------------------------- - -public Collection getNeighbours(int i) { - - if( i<0 || i>=prefSize ) throw new IndexOutOfBoundsException(); - - List result = new LinkedList(); - for(Integer j:g.getNeighbours(i)) - { - if( j < prefSize ) result.add(j); - } - - return Collections.unmodifiableCollection(result); -} - -// --------------------------------------------------------------- - -public Object getNode(int i) { - - if( i<0 || i>=prefSize ) throw new IndexOutOfBoundsException(); - return g.getNode(i); -} - -// --------------------------------------------------------------- - -/** -* Returns the edge in the original graph if both i and j are smaller than -* size(). -*/ -public Object getEdge(int i, int j) { - - if( isEdge(i,j) ) return g.getEdge(i,j); - return null; -} - -// -------------------------------------------------------------------- - -public int size() { return prefSize; } - -// -------------------------------------------------------------------- - -public boolean directed() { return g.directed(); } - -// -------------------------------------------------------------------- - -/** not supported */ -public boolean setEdge( int i, int j ) { - - throw new UnsupportedOperationException(); -} - -// --------------------------------------------------------------- - -/** not supported */ -public boolean clearEdge( int i, int j ) { - - throw new UnsupportedOperationException(); -} - -// --------------------------------------------------------------- - -public int degree(int i) { - - if( i<0 || i>=prefSize ) throw new IndexOutOfBoundsException(); - return g.degree(i); -} - - -// ================= public functions ================================= -// ==================================================================== - - -/** -* Sets the size of the subgraph. If i is negative, it is changed to 0 and -* if it is larger than the underlying graph size, it is changed to the -* underlying graph size (set at construction time). -* @return old size. -*/ -public int setSize(int i) { - - int was = prefSize; - if( i < 0 ) i = 0; - if( i > g.size() ) i=g.size(); - prefSize=i; - return was; -} -} - diff --git a/contrib/psg/src/peersim/graph/SubGraphEdges.java b/contrib/psg/src/peersim/graph/SubGraphEdges.java deleted file mode 100644 index bb4201fbf8..0000000000 --- a/contrib/psg/src/peersim/graph/SubGraphEdges.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.graph; - -import java.util.*; - -/** -* This class is an adaptor for representing subgraphs of any graph. -* The subgraph is defined the following way. -* The subgraph always contains all the nodes of the original underlying -* graph. However, it is possible to remove edges by flagging nodes as -* removed, in which case -* the edges that have at least one end on those nodes are removed. -* If the underlying graph changes after initialization, this class follows -* the change. -*/ -public class SubGraphEdges implements Graph { - - -// ====================== private fields ======================== -// ============================================================== - - -private final Graph g; - -private final BitSet nodes; - - -// ====================== public constructors =================== -// ============================================================== - - -/** -* Constructs an initially empty subgraph of g. That is, the subgraph will -* contain no nodes. -*/ -public SubGraphEdges( Graph g ) { - - this.g = g; - nodes = new BitSet(g.size()); -} - - -// ======================= Graph implementations ================ -// ============================================================== - - -public boolean isEdge(int i, int j) { - - return nodes.get(i) && nodes.get(j) && g.isEdge(i,j); -} - -// --------------------------------------------------------------- - -public Collection getNeighbours(int i) { - - List result = new LinkedList(); - if( nodes.get(i) ) - { - for(Integer in:g.getNeighbours(i)) - { - if( nodes.get(in) ) result.add(in); - } - } - - return Collections.unmodifiableCollection(result); -} - -// --------------------------------------------------------------- - -public Object getNode(int i) { return g.getNode(i); } - -// --------------------------------------------------------------- - -/** -* If both i and j are within the node set of the subgraph and the original -* graph has an (i,j) edge, returns that edge. -*/ -public Object getEdge(int i, int j) { - - if( isEdge(i,j) ) return g.getEdge(i,j); - return null; -} - -// -------------------------------------------------------------------- - -public int size() { return g.size(); } - -// -------------------------------------------------------------------- - -public boolean directed() { return g.directed(); } - -// -------------------------------------------------------------------- - -/** not supported */ -public boolean setEdge( int i, int j ) { - - throw new UnsupportedOperationException(); -} - -// --------------------------------------------------------------- - -/** not supported */ -public boolean clearEdge( int i, int j ) { - - throw new UnsupportedOperationException(); -} - -// --------------------------------------------------------------- - -public int degree(int i) { - - int degree=0; - if( nodes.get(i) ) - { - for(Integer in:g.getNeighbours(i)) - { - if( nodes.get(in) ) degree++; - } - } - return degree; -} - - -// ================= public functions ================================= -// ==================================================================== - - -/** -* This function returns the size of the subgraph, i.e. the number of nodes -* in the subgraph. -*/ -public int subGraphSize() { return nodes.cardinality(); } - -// -------------------------------------------------------------------- - -/** -* Removes given node from subgraph. -* @return true if the node was already in the subgraph otherwise false. -*/ -public boolean removeNode(int i) { - - boolean was = nodes.get(i); - nodes.clear(i); - return was; -} - -// -------------------------------------------------------------------- - -/** -* Adds given node to subgraph. -* @return true if the node was already in the subgraph otherwise false. -*/ -public boolean addNode(int i) { - - boolean was = nodes.get(i); - nodes.set(i); - return was; -} -} - diff --git a/contrib/psg/src/peersim/graph/UndirectedGraph.java b/contrib/psg/src/peersim/graph/UndirectedGraph.java deleted file mode 100644 index d229bae93f..0000000000 --- a/contrib/psg/src/peersim/graph/UndirectedGraph.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.graph; - -import java.util.*; - -/** -* This class is an adaptor making any Graph an undirected graph -* by making its edges bidirectional. The graph to be made undirected -* is passed to the constructor. Only the reference is stored so -* if the directed graph changes later, the undirected version will -* follow that change. However, {@link #getNeighbours} has O(n) time complexity -* (in other words, too slow for large graphs). -* @see ConstUndirGraph -*/ -public class UndirectedGraph implements Graph { - - -// ====================== private fileds ======================== -// ============================================================== - - -private final Graph g; - - -// ====================== public constructors =================== -// ============================================================== - - -public UndirectedGraph( Graph g ) { - - this.g = g; -} - - -// ======================= Graph implementations ================ -// ============================================================== - - -public boolean isEdge(int i, int j) { - - return g.isEdge(i,j) || g.isEdge(j,i); -} - -// --------------------------------------------------------------- - -/** -* Uses sets as collection so does not support multiple edges now, even if -* the underlying directed graph does. -*/ -public Collection getNeighbours(int i) { - - Set result = new HashSet(); - result.addAll(g.getNeighbours(i)); - final int max = g.size(); - for(int j=0; j threads; - -public ProcessManager() -{ - threads = Collections.synchronizedList(new ArrayList()); -} - -public void addThread(ProcessHandler p) -{ - threads.add(p); -} - -/** - * Assumes that the process manager - */ -public void joinAll() -{ - int i=0; - while (i < threads.size()) { - try { - threads.get(i).join(); - i++; - } catch (InterruptedException e) { - } - } -} - - -/** - * Kill the child process. - */ -public void run() -{ - System.err.println("Terminating simulation."); - for (int i=0; i < threads.size(); i++) { - if (threads.get(i) != null) - threads.get(i).doStop(); - } -} - -} \ No newline at end of file diff --git a/contrib/psg/src/peersim/rangesim/RangeSimulator.java b/contrib/psg/src/peersim/rangesim/RangeSimulator.java deleted file mode 100644 index 0995bcc83f..0000000000 --- a/contrib/psg/src/peersim/rangesim/RangeSimulator.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.rangesim; - -import java.io.*; -import java.util.*; - -import peersim.*; -import peersim.config.*; -import peersim.core.*; -import peersim.util.*; - -/** - * This class is the main class for the Range Simulator. A range is - * a collection of values S to be assigned to a variable - * v. The Range Simulator invokes the standard Peersim - * simulator once for each distinct value. If multiple ranges - * S1, S2, ..., Sn are specified, the standard Peersim - * simulator is invoked for each element in - * S1 * S2 * ... * Sn. - *

    - * Ranges are specified with the following syntax: -

    -range.[id] [var];[range]
    -
    - * where: - *
      - *
    • {@value #PAR_RANGE} is the prefix for all range - * specifications;
    • - *
    • id is an identifier; since they are not referred anywhere else, - * consecutive numbers are a good choice for range identifiers;
    • - *
    • var is a variable parameter
    • - *
    • range describes the collection of values to be associated - * to var, whose syntax and semantics is defined in - * {@link peersim.util.StringListParser}.
    • - *
    - * Examples of range specifications are the following: -
    -range.0 SIZE;2^10:2^18|*2
    -range.1 K;20:30
    -range.2 CHURN;0.05,0.10,0.20 
    -
    - * With this specification, the collection of values associated to - * SIZE is {2^10,2^11,...,2^18}; K contains - * {20,21,22,...,30}, while CHURN contains just the - * specified values. - *

    - * Values can be specified as constant expressions (like 2^10, (5+10), etc.) - * but variables cannot be used. - *

    - * A separate Java virtual machine is invoked to run each of the - * experiments. An attempt is done to run the same JVM version as - * the one running the Range Simulator; if this is not possible - * (for example due to path problems), the command shell mechanism - * is used to run the first JVM version found in the path. - *

    - * It is possible to specify options for the forked JVM using the - * {@value #PAR_JVM} parameter on the command line. For example, - * a command line like this: -
    -java peersim.rangesim.RangeSimulator config.file jvm.options=-Xmx256m
    -
    - * can be used to run the forked JVM with a maximum heap of 256MB. - *

    - * The new JVM inherits the same classpath as the JVM running the - * RangeSimulator. The {@value #PAR_JVM} parameter can be used to - * specify additional classpath specification. - * - * @author Alberto Montresor - * @version $Revision: 1.11 $ - */ -public class RangeSimulator implements ProcessHandler -{ - -// -------------------------------------------------------------------------- -// Configuration parameters -// -------------------------------------------------------------------------- - -/** - * This is the prefix of the config properties whose value vary during - * a set of experiments. - * @config - */ -private static final String PAR_RANGE = "range"; - -/** - * This config property can be used to set options in the JVMs that - * are forked to execute experiments with different configuration - * parameters. - * @config - */ -public static final String PAR_JVM = "jvm.options"; - - -// -------------------------------------------------------------------------- -// Static variables -// -------------------------------------------------------------------------- - -/** Names of range parameters */ -private String[] pars; - -/** Values to be simulated, for each parameter */ -private String[][] values; - -/** The jvm options to be used when creating jvms */ -private String[] jvmoptions; - -/** Command line arguments */ -private String[] args; - -/** The current process that is executed */ -private Process p; - - -// -------------------------------------------------------------------------- -// Main -// -------------------------------------------------------------------------- - -/** - * Main method of the system. - */ -public static void main(String[] args) -{ - RangeSimulator r = new RangeSimulator(args); - r.run(); -} - -//-------------------------------------------------------------------------- -// Constructor -//-------------------------------------------------------------------------- - -public RangeSimulator(String[] args) -{ - - // Check if there are no arguments or there is an explicit --help - // flag; if so, print the usage of the class - if (args.length == 0 || args[0].equals("--help")) { - usage(); - System.exit(101); - } - - this.args = args.clone(); - - // Read property file - System.err.println("Simulator: loading configuration"); - Properties properties = new ParsedProperties(args); - Configuration.setConfig(properties); - - // Read jvm options and separate them in different strings - String opt = Configuration.getString(PAR_JVM, null); - if (opt == null) - jvmoptions = new String[0]; - else - jvmoptions = opt.split(" "); - - // Parse range parameters - parseRanges(); - -} - -/** - * Main method to be executed - */ -public void run() -{ - // Shutdown thread management - ProcessManager t = new ProcessManager(); - t.addThread(this); - Runtime.getRuntime().addShutdownHook(t); - - // Executes experiments; report short messages about exceptions that are - // handled by the configuration mechanism. - try { - doExperiments(args); - } catch (MissingParameterException e) { - Runtime.getRuntime().removeShutdownHook(t); - System.err.println(e + ""); - System.exit(101); - } catch (IllegalParameterException e) { - Runtime.getRuntime().removeShutdownHook(t); - System.err.println(e + ""); - System.exit(101); - } - Runtime.getRuntime().removeShutdownHook(t); - System.exit(0); -} - -// -------------------------------------------------------------------- - -/** - * Parses a collection of range specifications and returns the set of - * parameter that will change during the simulation and the values that - * will be used for those parameters. - */ -private void parseRanges() -{ - // Get ranges - String[] ranges = Configuration.getNames(PAR_RANGE); - - // Start is the first element in which ranges are stored - int start; - - // If there is an explicit simulation.experiment or there are no - // ranges, put an experiment range at the beginning of the values. - // Otherwise, just use the ranges. - if (Configuration.contains(Simulator.PAR_EXPS) || ranges.length == 0) { - pars = new String[ranges.length + 1]; - values = new String[ranges.length + 1][]; - pars[0] = "EXP"; - values[0] = StringListParser.parseList("1:" - + Configuration.getInt(Simulator.PAR_EXPS, 1)); - start = 1; - } else { - pars = new String[ranges.length]; - values = new String[ranges.length][]; - start = 0; - } - - for (int i = start; i < pars.length; i++) { - String[] array = Configuration.getString(ranges[i-start]).split(";"); - if (array.length != 2) { - throw new IllegalParameterException(ranges[i], - " should be formatted as ;"); - } - pars[i] = array[0]; - values[i] = StringListParser.parseList(array[1]); - } -} - -// -------------------------------------------------------------------- - -/** - * Selects the next set of values by incrementing the specified index - * array. The index array is treated as a vector of digits; the first is - * managed managed as a vector of digits. - */ -private void nextValues(int[] idx, String[][] values) -{ - idx[idx.length - 1]++; - for (int j = idx.length - 1; j > 0; j--) { - if (idx[j] == values[j].length) { - idx[j] = 0; - idx[j - 1]++; - } - } -} - -// -------------------------------------------------------------------- - -private void doExperiments(String[] args) -{ - - // Configure the java parameter for exception - String filesep = System.getProperty("file.separator"); - String classpath = System.getProperty("java.class.path"); - String javapath = System.getProperty("java.home") + filesep + "bin" + filesep - + "java"; - ArrayList list = new ArrayList(20); - list.add(javapath); - list.add("-cp"); - list.add(classpath); - - // Add the jvm options - for (int i=0; i < jvmoptions.length; i++) - list.add(jvmoptions[i]); - - // The class to be run in the forked JVM - list.add("peersim.Simulator"); - - // Parameters specified on the command line - for (int i=0; i < args.length; i++) { - list.add(args[i]); - } - - // Since multiple experiments are managed here, the value - // of standard variable for multiple experiments is changed to 1 - list.add(Simulator.PAR_EXPS+"=1"); - - // Activate redirection to separate stdout from stderr - list.add(Simulator.PAR_REDIRECT+"="+TaggedOutputStream.class.getCanonicalName()); - int startlog = list.size(); - list.add(""); - - // Create a placeholder for the seed - int startseed = list.size(); - list.add(""); - - // Create placeholders for the range parameters - int startpar = list.size(); - for (int i=0; i < values.length; i++) - list.add(""); - - // Execute with different values - int[] idx = new int[values.length]; // Initialized to 0 - while (idx[0] < values[0].length) { - - // Configure the argument string array - for (int j = 0; j < pars.length; j++) { - list.set(startpar + j, pars[j] + "=" + values[j][idx[j]]); - } - - // Fill the log placeholder - StringBuffer log = new StringBuffer(); - for (int j = 0; j < pars.length; j++) { - log.append(pars[j]); - log.append(" "); - log.append(values[j][idx[j]]); - log.append(" "); - } - list.set(startlog, Simulator.PAR_REDIRECT+"."+ - TaggedOutputStream.PAR_RANGES+"="+log); - - // Fill the seed place holder - long seed = CommonState.r.nextLong(); - list.set(startseed, CommonState.PAR_SEED+"="+seed); - - System.err.println("Experiment: " + log); - - executeProcess(list); - - // Increment values - nextValues(idx, values); - - } -} - -//-------------------------------------------------------------------- - -/** - * Execute the "command line" represented by this String list. - * The first argument is the process to be executed. We try - * to run the same JVM as the current one. If not possible, - * we use the first java command found in the path. - */ -private void executeProcess(List list) -{ - // Prepare the argument array for process forking - String[] newargs = new String[list.size()]; - - // Execute a new JVM - try { - ProcessBuilder pb = new ProcessBuilder(list.toArray(newargs)); - pb.redirectErrorStream(true); - p = pb.start(); - } catch (IOException e1) { - try { - list.set(0, "java"); - ProcessBuilder pb = new ProcessBuilder(list.toArray(newargs)); - pb.redirectErrorStream(true); - p = pb.start(); - } catch (IOException e2) { - System.err.println("Unable to launch a Java virtual machine"); - System.exit(1); - } - } - - // Read the output from the process and redirect it to System.out - // and System.err. - BufferedReader toprint = new BufferedReader(new InputStreamReader(p - .getInputStream())); - String line; - while ((line = getLine(toprint)) != null) { - if (line.length() == 0) { - System.out.println(); - } else { - int last = line.charAt(line.length()-1); - if (last != TaggedOutputStream.TAG) { - System.err.println(line); - } else { - line = line.substring(0, line.length()-1); - System.out.println(line); - } - } - } - - // We close all the files and we destroy the process. They are not - // cleaned when the process is closed. See: - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4784692 - // http://www.thescripts.com/forum/thread18019.html - try { - p.getErrorStream().close(); - p.getInputStream().close(); - p.getOutputStream().close(); - p.destroy(); - } catch (IOException e) { - e.printStackTrace(); - } - - // The static variable p (used also by ShutdownThread) is back to - // null - no process must be killed on shutdown. - p = null; - - - -} - -//-------------------------------------------------------------------- - -private static String getLine(BufferedReader toprint) -{ - try { - return toprint.readLine(); - } catch (IOException e) { - // If we get here, this means that the forked process has - // been killed by the shutdown thread. We just exit without - // printing this exception. - System.exit(1); - return null; // Never reached, but needed. - } -} - - -// -------------------------------------------------------------------- - -private static void usage() -{ - System.err.println("Usage:"); - System.err.println(" peersim.RangeSimulator [property]*"); -} - -//-------------------------------------------------------------------- - -RangeSimulator() -{ -} - -/** - * Stop the process executing the external java virtual machine. - */ -public void doStop() -{ - if (p != null) - p.destroy(); -} - -/** - * Wait until the java virtual machine has terminated; it won't be - * used in this class, but you never know. - */ -public void join() throws InterruptedException -{ - p.waitFor(); -} - -} diff --git a/contrib/psg/src/peersim/rangesim/TaggedOutputStream.java b/contrib/psg/src/peersim/rangesim/TaggedOutputStream.java deleted file mode 100644 index 628855383a..0000000000 --- a/contrib/psg/src/peersim/rangesim/TaggedOutputStream.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.rangesim; - -import java.io.*; -import java.util.*; - -import peersim.config.*; -import peersim.core.*; - -/** - * This OutputStream uses an underlying stream to output - * data. Each line (terminated with `\n`) is augmented - * with a tag character. This is used to discriminate - * among standard error and standard output. This - * feature is needed for launching new JVMs; it should - * not be used for other purposes. - * - * @author Alberto Montresor - * @version $Revision: 1.5 $ - */ -public class TaggedOutputStream extends PrintStream -{ - -//-------------------------------------------------------------------------- -//Constants -//-------------------------------------------------------------------------- - -/** - * This character is appended at the end of each line. - */ -public static final int TAG = 1; - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * This parameter contains the string that should be printed on each - * line, containing the values of the range parameters for the experiment - * which is being run. The full name of this configuration string is - * prefixed by {@value peersim.Simulator#PAR_REDIRECT}. - * @config - */ -public static final String PAR_RANGES = "ranges"; - -/** - * This parameter contains the list of observers for which the string - * contained in parameter {@value #PAR_RANGES} should be augmented with - * a "TIME <t>" specification regarding current time. Observers are - * separated by one of this characters: ' ' - ',' - ';'. - * @config - */ -public static final String PAR_TIME = "simulation.timed-observers"; - - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -/** Variable used to save the original System.out to simplify printing */ -private PrintStream stdout; - -/** Buffer used to store a single line; it can grow */ -private byte[] buffer = new byte[1024]; - -/** Current size of the buffer */ -private int size; - -/** The value of the PAR_RANGES parameter */ -private final String ranges; - -/** The value of the PAR_TIME parameter */ -private final ArrayList obstime; - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - - -/** - * Creates a tagged output stream that prints the tagged - * output on the specified stream. - */ -public TaggedOutputStream(String prefix) -{ - super(System.out); - - obstime = new ArrayList(); - String[] obs = Configuration.getString(PAR_TIME, "").split("[ :,]"); - for (int i=0; i < obs.length; i++) { - obstime.add("control." + obs[i]); - } - ranges = Configuration.getString(prefix + "." + PAR_RANGES, ""); - stdout = System.out; - size = 0; -} - -//-------------------------------------------------------------------------- -//Methods -//-------------------------------------------------------------------------- - -// Comment inherited from interface -@Override -public synchronized void write(byte[] b, int off, int len) -{ - if (size+len > buffer.length) { - byte[] tmp = new byte[Math.max(buffer.length*2, size+len)]; - System.arraycopy(buffer, 0, tmp, 0, size); - buffer = tmp; - } - int last = off+len; - for (int i=off; i < last; i++) { - if (b[i] == '\n') { - buffer[size++] = TAG; - buffer[size++] = b[i]; - printLine(); - } else { - buffer[size++] = b[i]; - } - } -} - -// Comment inherited from interface -@Override -public synchronized void write(int b) -{ - if (size == buffer.length) { - byte[] tmp = new byte[buffer.length*2]; - System.arraycopy(buffer, 0, tmp, 0, size); - buffer = tmp; - } - if (b == '\n') { - buffer[size++] = TAG; - buffer[size++] = (byte) b; - printLine(); - } else { - buffer[size++] = (byte) b; - } -} - -/** - * Actually prints a line, inserting ranges and time - * when needed. - */ -private void printLine() -{ - String line = new String(buffer, 0, size); - String[] parts = line.split(":"); - if (parts.length == 2) { - stdout.print(parts[0]); - stdout.print(": "); - stdout.print(ranges); - if (obstime.contains(parts[0])) - stdout.print(" TIME " + CommonState.getTime() + " "); - stdout.print(parts[1]); - } else { - stdout.print(line); - } - size = 0; -} - -} diff --git a/contrib/psg/src/peersim/reports/BallExpansion.java b/contrib/psg/src/peersim/reports/BallExpansion.java deleted file mode 100644 index b46e1172a5..0000000000 --- a/contrib/psg/src/peersim/reports/BallExpansion.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.reports; - -import peersim.config.*; -import peersim.core.*; -import peersim.util.*; - -/** - * Control to observe the ball expansion, that is, - * the number of nodes that are - * accessible from a given node in at most 1, 2, etc steps. - */ -public class BallExpansion extends GraphObserver -{ - -// ===================== fields ======================================= -// ==================================================================== - -/** - * This parameter defines the maximal distance we care about. - * In other words, two nodes are further away, they will not be taken - * into account when calculating statistics. - *

    - * Defaults to the - * network size (which means all distances are taken into account). - * Note that this default is normally way too much; many low diameter graphs - * have only short distances between the nodes. Setting a short - * (but sufficient) distance saves memory. - * Also note that the initial network - * size is used if no value is given which might not be what you want if e.g. the - * network is growing. - * @config - */ -private static final String PAR_MAXD = "maxd"; - -/** - * The number of nodes to print info about. - * Defaults to 1000. If larger than the current network size, then the - * current network size is used. - * @config - */ -private static final String PAR_N = "n"; - -/** - * If defined, statistics are printed instead over the minimal path lengths. Not - * defined by default. - * @config - */ -private static final String PAR_STATS = "stats"; - -private final int maxd; - -private final int n; - -private final boolean stats; - -/** working variable */ -private final int[] b; - -private final RandPermutation rp = new RandPermutation(CommonState.r); - -// ===================== initialization ================================ -// ===================================================================== - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -public BallExpansion(String name) -{ - super(name); - maxd = Configuration.getInt(name + "." + PAR_MAXD, Network.size()); - n = Configuration.getInt(name + "." + PAR_N, 1000); - stats = Configuration.contains(name + "." + PAR_STATS); - b = new int[maxd]; -} - -// ====================== methods ====================================== -// ===================================================================== - -/** -* Prints information about ball expansion. It uses {@value #PAR_N} nodes to -* collect statistics. -* If parameter {@value #PAR_STATS} is defined then the output is -* produced by {@link IncrementalStats#toString}, over the values of minimal -* distances from the given number of nodes to all other nodes in the network. -* If at least one node is unreachable from any selected starting node, then -* the path length is taken as infinity and statistics are calculated -* accordingly. In that case, {@link IncrementalStats#getMaxCount()} returns -* the number of nodes of "infinite distance", that is, the number of -* unreachable nodes. -* Otherwise one line is printed for all nodes we observe, containing the -* number of nodes at distance 1, 2, etc, separated by spaces. -* In this output format, unreachable nodes are simply ignored, but of course -* the sum of the numbers in one line can be used to detect partitioning if -* necessary. -* Finally, note that the {@value #PAR_N} nodes are not guaranteed to be the -* same nodes over consecutive calls to this method. -* @return always false -*/ -public boolean execute() { - - updateGraph(); - System.out.print(name + ": "); - rp.reset(g.size()); - if (stats) - { - IncrementalStats is = new IncrementalStats(); - for (int i = 0; i < n && i < g.size(); ++i) - { - ga.dist(g, rp.next()); - for (int j=0; j 0) - is.add(ga.d[j]); - else if (ga.d[j] == -1) - is.add(Double.POSITIVE_INFINITY); - // deliberately left ga.d[j]==0 out, as we don't - // want to count trivial distance to oneself. - } - } - System.out.println(is); - } - else - { - System.out.println(); - for (int i = 0; i < n && i < g.size(); ++i) - { - ga.flooding(g, b, rp.next()); - int j = 0; - while (j < b.length && b[j] > 0) - { - System.out.print(b[j++] + " "); - } - System.out.println(); - } - } - return false; -} - -} diff --git a/contrib/psg/src/peersim/reports/Clustering.java b/contrib/psg/src/peersim/reports/Clustering.java deleted file mode 100644 index 38b81f7e28..0000000000 --- a/contrib/psg/src/peersim/reports/Clustering.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.reports; - -import peersim.config.Configuration; -import peersim.graph.GraphAlgorithms; -import peersim.util.IncrementalStats; - -/** - * Control to observe the clustering coefficient. - * @see GraphAlgorithms#clustering - */ -public class Clustering extends GraphObserver -{ - -// ===================== fields ======================================= -// ==================================================================== - -/** - * The number of nodes to collect info about. Defaults to the size of the graph. - * @config - */ -private static final String PAR_N = "n"; - -private final int n; - -// ===================== initialization ================================ -// ===================================================================== - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -public Clustering(String name) -{ - super(name); - n = Configuration.getInt(name + "." + PAR_N, Integer.MAX_VALUE); -} - -// ====================== methods ====================================== -// ===================================================================== - -/** -* Prints information about the clustering coefficient. -* It uses {@value #PAR_N} nodes to collect statistics. -* The output is -* produced by {@link IncrementalStats#toString}, over the values of -* the clustering coefficients of the given number of nodes. -* Clustering coefficients are calculated by {@link GraphAlgorithms#clustering}. -* @return always false -*/ -public boolean execute() -{ - IncrementalStats stats = new IncrementalStats(); - updateGraph(); - for (int i = 0; i < n && i < g.size(); ++i) { - stats.add(GraphAlgorithms.clustering(g, i)); - } - System.out.println(name + ": " + stats); - return false; -} - -} diff --git a/contrib/psg/src/peersim/reports/ConnectivityObserver.java b/contrib/psg/src/peersim/reports/ConnectivityObserver.java deleted file mode 100644 index d23ac082c2..0000000000 --- a/contrib/psg/src/peersim/reports/ConnectivityObserver.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.reports; - -import java.util.Iterator; -import java.util.Map; -import peersim.config.Configuration; -import peersim.util.IncrementalStats; - -/** - * Reports statistics about connectivity properties of the network, such as - * weakly or strongly connected clusters. - */ -public class ConnectivityObserver extends GraphObserver -{ - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * The parameter used to request cluster size statistics instead of the usual - * list of clusters. Not set by default. - * @config - */ -private static final String PAR_STATS = "stats"; - -/** - * Defines the types of connected clusters to discover. - * Possible values are - *

      - *
    • "wcc": weakly connected clusters
    • - *
    • "scc": strongly connected clusters
    • - *
    - * Defaults to "wcc". - * @config - */ -private static final String PAR_TYPE = "type"; - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -/** {@link #PAR_STATS} */ -private final boolean sizestats; - -/** {@link #PAR_TYPE} */ -private final String type; - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -public ConnectivityObserver(String name) -{ - super(name); - sizestats = Configuration.contains(name + "." + PAR_STATS); - type = Configuration.getString(name + "." + PAR_TYPE,"wcc"); -} - -//-------------------------------------------------------------------------- -//Methods -//-------------------------------------------------------------------------- - -/** -* Prints information about clusters. -* If parameter {@value #PAR_STATS} is defined then the output is -* produced by {@link IncrementalStats#toString}, over the sizes of the -* clusters. -* Otherwise one line is printed that contains the string representation of -* a map, that holds cluster IDs mapped to cluster sizes. -* The meaning of the cluster IDs is not specified, but is printed for -* debugging purposes. -* @return always false -* @see peersim.graph.GraphAlgorithms#tarjan -* @see peersim.graph.GraphAlgorithms#weaklyConnectedClusters -*/ -public boolean execute() -{ - Map clst; - updateGraph(); - - if(type.equals("wcc")) - clst=ga.weaklyConnectedClusters(g); - else if(type.equals("scc")) - clst=ga.tarjan(g); - else - throw new RuntimeException( - "Unsupported connted cluster type '"+type+"'"); - - if (!sizestats) { - System.out.println(name + ": " + clst); - } else { - IncrementalStats stats = new IncrementalStats(); - Iterator it = clst.values().iterator(); - while (it.hasNext()) { - stats.add(((Integer) it.next()).intValue()); - } - System.out.println(name + ": " + stats); - } - return false; -} - -} diff --git a/contrib/psg/src/peersim/reports/DegreeStats.java b/contrib/psg/src/peersim/reports/DegreeStats.java deleted file mode 100644 index d6c57e6288..0000000000 --- a/contrib/psg/src/peersim/reports/DegreeStats.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.reports; - -import peersim.config.*; -import peersim.core.*; -import peersim.util.*; - -/** - * Prints several statistics about the node degrees in the graph. - */ -public class DegreeStats extends GraphObserver -{ - -//-------------------------------------------------------------------------- -//Parameter -//-------------------------------------------------------------------------- - -/** - * The number of nodes to be used for sampling the degree. - * Defaults to full size of the graph. - * @config - */ -private static final String PAR_N = "n"; - -/** - * If defined, then the given number of nodes will be traced. That is, it is - * guaranteed that in each call the same nodes will be picked in the same order. - * If a node being traced fails, its degree will be considered 0. Not defined by - * default. - * @config - */ -private static final String PAR_TRACE = "trace"; - -/** - * Selects a method to use when printing results. Three methods are known: - * "stats" will use {@link IncrementalStats#toString}. "freq" will - * use {@link IncrementalFreq#print}. "list" will print the - * degrees of the sample nodes one by one in one line, separated by spaces. - * Default is "stats". - * @config - */ -private static final String PAR_METHOD = "method"; - -/** - * Selects the types of links to print information about. Three methods are - * known: "live": links pointing to live nodes, "dead": links pointing to nodes - * that are unavailable and "all": both dead and live links summed. "all" and - * "dead" require parameter {@value peersim.reports.GraphObserver#PAR_UNDIR} - * to be unset (graph must be directed). Default is "live". - * @config - */ -private static final String PAR_TYPE = "linktype"; - -//-------------------------------------------------------------------------- -//Parameter -//-------------------------------------------------------------------------- - -private final int n; - -private final boolean trace; - -private Node[] traced = null; - -private final String method; - -private final String type; - -private final RandPermutation rp = new RandPermutation(CommonState.r); - -private int nextnode = 0; - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -public DegreeStats(String name) -{ - super(name); - n = Configuration.getInt(name + "." + PAR_N, -1); - trace = Configuration.contains(name + "." + PAR_TRACE); - method = Configuration.getString(name + "." + PAR_METHOD, "stats"); - type = Configuration.getString(name + "." + PAR_TYPE, "live"); - if ((type.equals("all") || type.equals("dead")) && undir) { - throw new IllegalParameterException( - name + "." + PAR_TYPE, " Parameter "+ name + "." + - PAR_UNDIR + " must not be defined if " + name + "." - + PAR_TYPE + "=" + type + "."); - } -} - -//-------------------------------------------------------------------------- -//Methods -//-------------------------------------------------------------------------- - -/** - * Returns next node to get degree information about. - */ -private int nextNodeId() -{ - if (trace) { - if (traced == null) { - int nn = (n < 0 ? Network.size() : n); - traced = new Node[nn]; - for (int j = 0; j < nn; ++j) - traced[j] = Network.get(j); - } - return traced[nextnode++].getIndex(); - } else - return rp.next(); -} - -// --------------------------------------------------------------------- - -/** - * Returns degree information about next node. - */ -private int nextDegree() -{ - final int nodeid = nextNodeId(); - if (type.equals("live")) { - return g.degree(nodeid); - } else if (type.equals("all")) { - return ((OverlayGraph) g).fullDegree(nodeid); - } else if (type.equals("dead")) { - return ((OverlayGraph) g).fullDegree(nodeid) - g.degree(nodeid); - } else - throw new RuntimeException(name + ": invalid type"); -} - -// --------------------------------------------------------------------- - -/** - * Prints statistics about node degree. The format of the output is specified - * by {@value #PAR_METHOD}. See also the rest of the configuration parameters. - * @return always false - */ -public boolean execute() -{ - updateGraph(); - if (!trace) - rp.reset(g.size()); - else - nextnode = 0; - final int nn = (n < 0 ? Network.size() : n); - if (method.equals("stats")) { - IncrementalStats stats = new IncrementalStats(); - for (int i = 0; i < nn; ++i) - stats.add(nextDegree()); - System.out.println(name + ": " + stats); - } else if (method.equals("freq")) { - IncrementalFreq stats = new IncrementalFreq(); - for (int i = 0; i < nn; ++i) - stats.add(nextDegree()); - stats.print(System.out); - System.out.println("\n\n"); - } else if (method.equals("list")) { - System.out.print(name + ": "); - for (int i = 0; i < nn; ++i) - System.out.print(nextDegree() + " "); - System.out.println(); - } - return false; -} - -} diff --git a/contrib/psg/src/peersim/reports/GraphObserver.java b/contrib/psg/src/peersim/reports/GraphObserver.java deleted file mode 100644 index 6f939ea5e0..0000000000 --- a/contrib/psg/src/peersim/reports/GraphObserver.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.reports; - -import peersim.core.*; -import peersim.config.Configuration; -import peersim.graph.*; -import peersim.cdsim.CDState; - -/** -* Class that provides functionality for observing graphs. -* It can efficiently create an undirected version of the graph, making sure -* it is updated only when the simulation has advanced already, and provides -* some common parameters. -*/ -public abstract class GraphObserver implements Control { - - -// ===================== fields ======================================= -// ==================================================================== - -/** - * The protocol to operate on. - * @config - */ -private static final String PAR_PROT = "protocol"; - -/** - * If defined, the undirected version of the graph will be analyzed. Not defined - * by default. - * @config - */ -protected static final String PAR_UNDIR = "undir"; - -/** -* Alias for {@value #PAR_UNDIR}. -* @config -*/ -private static final String PAR_UNDIR_ALT = "undirected"; - -/** - * If defined, the undirected version of the graph will be stored using much - * more memory but observers will be in general a few times faster. As a - * consequence, it will not work with large graphs. Not defined by default. It - * is a static property, that is, it affects all graph observers that are used - * in a simulation. That is, it is not a parameter of any observer, the name - * should be specified as a standalone property. - * @config - */ -private static final String PAR_FAST = "graphobserver.fast"; - -/** The name of this observer in the configuration */ -protected final String name; - -protected final int pid; - -protected final boolean undir; - -protected final GraphAlgorithms ga = new GraphAlgorithms(); - -protected Graph g; - -// --------------------------------------------------------------------- - -private static int lastpid = -1234; - -private static long time = -1234; - -private static int phase = -1234; - -private static int ctime = -1234; - -private static Graph dirg; - -private static Graph undirg; - -private static boolean fast; - -/** If any instance of some extending class defines undir we need to -maintain an undir graph. Note that the graph is stored in a static -field so it is common to all instances. */ -private static boolean needUndir=false; - -// ===================== initialization ================================ -// ===================================================================== - - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -protected GraphObserver(String name) { - - this.name = name; - pid = Configuration.getPid(name+"."+PAR_PROT); - undir = (Configuration.contains(name + "." + PAR_UNDIR) | - Configuration.contains(name + "." + PAR_UNDIR_ALT)); - GraphObserver.fast = Configuration.contains(PAR_FAST); - GraphObserver.needUndir = (GraphObserver.needUndir || undir); -} - - -// ====================== methods ====================================== -// ===================================================================== - -/** -* Sets {@link #g}. -* It MUST be called by any implementation of {@link #execute()} before -* doing anything else. -* Attempts to initialize {@link #g} from a -* pre-calculated graph stored in a static field, but first it -* checks whether it needs to be updated. -* If the simulation time has progressed or it was calculated for a different -* protocol, then updates this static graph as well. -* The purpose of this mechanism is to save the time of constructing the -* graph if many observers are run on the same graph. Time savings can be very -* significant if the undirected version of the same graph is observed by many -* observers. -*/ -protected void updateGraph() { - - if( CommonState.getTime() != GraphObserver.time || - (CDState.isCD() && (CDState.getCycleT() != GraphObserver.ctime)) || - CommonState.getPhase() != GraphObserver.phase || - pid != GraphObserver.lastpid ) - { - // we need to update the graphs - - GraphObserver.lastpid = pid; - GraphObserver.time = CommonState.getTime(); - if( CDState.isCD() ) GraphObserver.ctime = CDState.getCycleT(); - GraphObserver.phase = CommonState.getPhase(); - - GraphObserver.dirg = new OverlayGraph(pid); - if( GraphObserver.needUndir ) - { - if( fast ) - GraphObserver.undirg = - new FastUndirGraph(GraphObserver.dirg); - else - GraphObserver.undirg = - new ConstUndirGraph(GraphObserver.dirg); - } - } - - if( undir ) g = GraphObserver.undirg; - else g = GraphObserver.dirg; -} - -} - - - diff --git a/contrib/psg/src/peersim/reports/GraphPrinter.java b/contrib/psg/src/peersim/reports/GraphPrinter.java deleted file mode 100644 index 3317c10f0e..0000000000 --- a/contrib/psg/src/peersim/reports/GraphPrinter.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.reports; - -import peersim.config.Configuration; -import peersim.graph.GraphIO; -import peersim.util.FileNameGenerator; -import java.io.PrintStream; -import java.io.FileOutputStream; -import java.io.IOException; - -/** -* Prints the whole graph in a given format. -*/ -public class GraphPrinter extends GraphObserver { - - -// ===================== fields ======================================= -// ==================================================================== - -/** -* This is the prefix of the filename where the graph is saved. -* The extension is ".graph" and after the prefix the basename contains -* a numeric index that is incremented at each saving point. -* If not given, the graph is dumped on the standard output. -* @config -*/ -private static final String PAR_BASENAME = "outf"; - -/** -* The name for the format of the output. Defaults to "neighborlist", -* which is a plain dump of neighbors. The class -* {@link peersim.dynamics.WireFromFile} can read this format. -* Other supported formats are "chaco" to be used with Yehuda Koren's -* Embedder, "netmeter" to be used with Sergi Valverde's netmeter and also -* with pajek, -* "edgelist" that dumps one (directed) node pair in each line for each edge, -* "gml" that is a generic format of many graph tools, and "dot" that can -* be used with the graphviz package. -* @see GraphIO#writeEdgeList -* @see GraphIO#writeChaco -* @see GraphIO#writeNeighborList -* @see GraphIO#writeNetmeter -* @config -*/ -private static final String PAR_FORMAT = "format"; - -private final String baseName; - -private final FileNameGenerator fng; - -private final String format; - - -// ===================== initialization ================================ -// ===================================================================== - - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -public GraphPrinter(String name) { - - super(name); - baseName = Configuration.getString(name+"."+PAR_BASENAME,null); - format = Configuration.getString(name+"."+PAR_FORMAT,"neighborlist"); - if(baseName!=null) fng = new FileNameGenerator(baseName,".graph"); - else fng = null; -} - - -// ====================== methods ====================================== -// ===================================================================== - - -/** -* Saves the graph according to the specifications in the configuration. -* @return always false -*/ -public boolean execute() { -try { - updateGraph(); - - System.out.print(name+": "); - - // initialize output streams - FileOutputStream fos = null; - PrintStream pstr = System.out; - if( baseName != null ) - { - String fname = fng.nextCounterName(); - fos = new FileOutputStream(fname); - System.out.println("writing to file "+fname); - pstr = new PrintStream(fos); - } - else System.out.println(); - - if( format.equals("neighborlist") ) - GraphIO.writeNeighborList(g, pstr); - else if( format.equals("edgelist") ) - GraphIO.writeEdgeList(g, pstr); - else if( format.equals("chaco") ) - GraphIO.writeChaco(g, pstr); - else if( format.equals("netmeter") ) - GraphIO.writeNetmeter(g, pstr); - else if( format.equals("gml") ) - GraphIO.writeGML(g, pstr); - else if( format.equals("dot") ) - GraphIO.writeDOT(g, pstr); - else - System.err.println(name+": unsupported format "+format); - - if( fos != null ) fos.close(); - - return false; -} -catch( IOException e ) -{ - throw new RuntimeException(e); -} -} - -} - diff --git a/contrib/psg/src/peersim/reports/GraphStats.java b/contrib/psg/src/peersim/reports/GraphStats.java deleted file mode 100644 index a57773c8c9..0000000000 --- a/contrib/psg/src/peersim/reports/GraphStats.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.reports; - -import peersim.config.Configuration; -import peersim.graph.GraphAlgorithms; -import peersim.util.IncrementalStats; - -/** -* Prints reports on the graph like average clustering and average path length, -* based on random sampling of the nodes. -* In fact its functionality is a subset of the union of {@link Clustering} -* and {@link BallExpansion}, and therefore is redundant, -* but it is there for historical reasons. -* @see BallExpansion -* @see Clustering -*/ -public class GraphStats extends GraphObserver { - - -// ===================== fields ======================================= -// ==================================================================== - -/** -* The number of nodes to use for -* sampling average path length. -* Statistics are printed over a set of node pairs. -* To create the set of pairs, we select the given number of different nodes -* first, and then pair all these nodes with every other node in the network. -* If zero is given, then no statistics -* will be printed about path length. If a negative value is given then -* the value is the full size of the graph. -* Defaults to zero. -* @config -*/ -private static final String PAR_NL = "nl"; - -/** -* The number of nodes to use to sample -* average clustering. -* If zero is given, then no statistics -* will be printed about clustering. If a negative value is given then -* the value is the full size of the graph. -* Defaults to zero. -* @config -*/ -private static final String PAR_NC = "nc"; - -private final int nc; - -private final int nl; - - -// ===================== initialization ================================ -// ===================================================================== - - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -public GraphStats(String name) { - - super(name); - nl = Configuration.getInt(name+"."+PAR_NL,0); - nc = Configuration.getInt(name+"."+PAR_NC,0); -} - - -// ====================== methods ====================================== -// ===================================================================== - -/** -* Returns statistics over minimal path length and clustering. -* The output is the average over the set of -* clustering coefficients of randomly selected nodes, and the -* set of distances from randomly selected nodes to all the other nodes. -* The output is always concatenated in one line, containing zero, one or two -* numbers (averages) as defined by the config parameters. -* Note that the path length between a pair of nodes can be infinite, in which -* case the statistics will reflect this (the average will be infinite, etc). -* See also the configuration parameters. -* @return always false -* @see BallExpansion -* @see Clustering -*/ -public boolean execute() { - - System.out.print(name+": "); - - IncrementalStats stats = new IncrementalStats(); - updateGraph(); - - if( nc != 0 ) - { - stats.reset(); - final int n = ( nc<0 ? g.size() : nc ); - for(int i=0; ijava.lang.Runtime). - * - * @author Alberto Montresor - * @version $Revision: 1.1 $ - */ -public class MemoryObserver implements Control -{ - -/** The runtime object to obtain memory info */ -private final static Runtime r = Runtime.getRuntime(); - -/** The prefix to be printed */ -private final String prefix; - -/** - * Constructor to be instantiated in PeerSim. - * @param prefix - */ -public MemoryObserver(String prefix) -{ - this.prefix = prefix; -} - -public boolean execute() -{ - System.out.println(prefix + ": max=" + r.maxMemory() + ", total=" + - r.totalMemory() + ", free=" + r.freeMemory()); - return false; -} - -} diff --git a/contrib/psg/src/peersim/reports/RandRemoval.java b/contrib/psg/src/peersim/reports/RandRemoval.java deleted file mode 100644 index 8872873146..0000000000 --- a/contrib/psg/src/peersim/reports/RandRemoval.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.reports; - -import peersim.core.*; -import peersim.config.Configuration; -import peersim.graph.*; -import peersim.util.IncrementalStats; -import java.util.Map; -import java.util.Iterator; - -/** - * It tests the network for robustness to random node removal. - * It does not actually remove - * nodes, it is only an observer, so can be applied several times during the - * simulation. A warning though: as a side effect it may - * shuffle the network (see {@value #PAR_N}) so if this is an issue, - * it should not be used, - * or only after the simulation has finished. - */ -public class RandRemoval extends GraphObserver -{ - -// ===================== fields ======================================= -// ==================================================================== - -// XXX remove side effect -/** - * This parameter defines the number of runs of the iterative removal procedure - * to get statistics. Look out: if set to a value larger than 1 then as a side - * effect the overlay will be shuffled. Defaults to 1. - * @config - */ -private static final String PAR_N = "n"; - -private final int n; - -// ===================== initialization ================================ -// ===================================================================== - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -public RandRemoval(String name) -{ - super(name); - n = Configuration.getInt(name + "." + PAR_N, 1); -} - -// ====================== methods ====================================== -// ===================================================================== - -/** -* Prints results of node removal tests. The following experiment is -* repeated {@value #PAR_N} times. From the graph 50%, 51%, ..., 99% of the nodes -* are removed at random. For all percentages it is calculated what is -* the maximal -* clustersize (weakly connected clusters) and the number of -* clusters in the remaining graph. -* These values are averaged over the experiments, and for all 50 different -* percentage values a line is printed that contains the respective averages, -* first the average maximal cluster size, followed by the average number -* of clusters. -* @return always false -*/ -public boolean execute() -{ - if( n < 1 ) return false; - updateGraph(); - - System.out.println(name + ":"); - - final int size = Network.size(); - final int steps = 50; - IncrementalStats[] maxClust = new IncrementalStats[steps]; - IncrementalStats[] clustNum = new IncrementalStats[steps]; - for (int i = 0; i < steps; ++i) { - maxClust[i] = new IncrementalStats(); - clustNum[i] = new IncrementalStats(); - } - for (int j = 0; j < n; ++j) { - PrefixSubGraph sg = new PrefixSubGraph(g); - IncrementalStats stats = new IncrementalStats(); - for (int i = 0; i < steps; i++) { - sg.setSize(size / 2 - i * (size / 100)); - Map clst = ga.weaklyConnectedClusters(sg); - stats.reset(); - Iterator it = clst.values().iterator(); - while (it.hasNext()) { - stats.add(((Integer) it.next()).intValue()); - } - maxClust[i].add(stats.getMax()); - clustNum[i].add(clst.size()); - } - if( j+1 < n ) Network.shuffle(); - } - for (int i = 0; i < steps; ++i) { - System.out.println(maxClust[i].getAverage() + " " - + clustNum[i].getAverage()); - } - return false; -} - -} diff --git a/contrib/psg/src/peersim/transport/E2ENetwork.java b/contrib/psg/src/peersim/transport/E2ENetwork.java deleted file mode 100644 index a184f9ad46..0000000000 --- a/contrib/psg/src/peersim/transport/E2ENetwork.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - - -/** - * This static singleton emulates an underlying router network - * of fixed size, and stores the latency measurements for all pairs - * of routers. - * - * @author Alberto Montresor - * @version $Revision: 1.6 $ - */ -public class E2ENetwork -{ - -//--------------------------------------------------------------------- -//Fields -//--------------------------------------------------------------------- - -/** - * True if latency between nodes is considered symmetric. False otherwise. - */ -private static boolean symm; - -/** - * Size of the router network. - */ -private static int size; - -/** - * Latency distances between nodes. - */ -private static int[][] array; - -//--------------------------------------------------------------------- -//Initialization -//--------------------------------------------------------------------- - -/** Disable instance construction */ -private E2ENetwork() {} - -//--------------------------------------------------------------------- -//Methods -//--------------------------------------------------------------------- - -/** - * Resets the network, by creating a triangular (if symm is true) or - * a rectangular (if symm is false) array of integers. Initially all - * latencies between any pairs are set to be 0. - * @param size the number or routers - * @param symm if latency is symmetric between all pairs of routers - */ -public static void reset(int size, boolean symm) -{ - E2ENetwork.symm = symm; - E2ENetwork.size = size; - array = new int[size][]; - for (int i=0; i < size; i++) { - if (symm) - array[i] = new int[i]; - else - array[i] = new int[size]; - } -} - -//--------------------------------------------------------------------- - -/** - * Returns the latency associated to the specified (sender, receiver) - * pair. Routers are indexed from 0. - * - * @param sender the index of the sender - * @param receiver the index of the receiver - * @return the latency associated to the specified (sender, receiver) - * pair. - */ -public static int getLatency(int sender, int receiver) -{ - if (sender == receiver) - return 0; - // XXX There should be the possibility to fix the delay. - if (symm) { - // Symmetric network - if (sender < receiver) { - int tmp = sender; - sender = receiver; - receiver = tmp; - } - } - return array[sender][receiver]; -} - -//--------------------------------------------------------------------- - -/** - * Sets the latency associated to the specified (sender, receiver) - * pair. Routers are indexed from 0. - * - * @param sender the index of the sender - * @param receiver the index of the receiver - * @param latency the latency to be set - */ -public static void setLatency(int sender, int receiver, int latency) -{ - if (symm) { - // Symmetric network - if (sender < receiver) { - int tmp = sender; - sender = receiver; - receiver = tmp; - } - } - array[sender][receiver] = latency; -} - -//--------------------------------------------------------------------- - -/** - * Returns the current size of the underlying network (i.e., the number of - * routers). - */ -public static int getSize() -{ - return size; -} - -} diff --git a/contrib/psg/src/peersim/transport/E2ETransport.java b/contrib/psg/src/peersim/transport/E2ETransport.java deleted file mode 100644 index e2eab7861b..0000000000 --- a/contrib/psg/src/peersim/transport/E2ETransport.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - -import peersim.config.*; -import peersim.core.*; -import peersim.edsim.*; - - -/** - * This transport protocol is based on the {@link E2ENetwork} class. - * Each instance - * of this transport class is assigned to one of the routers contained in - * the (fully static singleton) {@link E2ENetwork}, - * and subsequently the {@link E2ENetwork} class is used to obtain the - * latency for messages sending based on the router assignment. - * - * @author Alberto Montresor - * @version $Revision: 1.11 $ - */ -public class E2ETransport implements Transport, RouterInfo -{ - -//--------------------------------------------------------------------- -//Parameters -//--------------------------------------------------------------------- - -/** - * The delay that corresponds to the time spent on the source (and destination) - * nodes. In other words, full latency is calculated by fetching the latency - * that belongs to communicating between two routers, incremented by - * twice this delay. Defaults to 0. - * @config - */ -private static final String PAR_LOCAL = "local"; - -//--------------------------------------------------------------------- -//Static fields -//--------------------------------------------------------------------- - -/** Identifier of this transport protocol */ -private static int tid; - -/** Local component of latency */ -private static long local; - -//--------------------------------------------------------------------- -//Fields -//--------------------------------------------------------------------- - -/** Identifier of the internal node */ -private int router = -1; - -//--------------------------------------------------------------------- -//Initialization -//--------------------------------------------------------------------- - -/** - * Reads configuration parameters. - */ -public E2ETransport(String prefix) -{ - tid = CommonState.getPid(); - local = Configuration.getLong(prefix + "." + PAR_LOCAL, 0); -} - -//--------------------------------------------------------------------- - -/** - * Clones the object. - */ -public Object clone() -{ - E2ETransport e2e=null; - try { e2e=(E2ETransport)super.clone(); } - catch( CloneNotSupportedException e ) {} // never happens - return e2e; -} - -//--------------------------------------------------------------------- -//Methods inherited by Transport -//--------------------------------------------------------------------- - -/** -* Delivers the message reliably, with the latency calculated by -* {@link #getLatency}. -*/ -public void send(Node src, Node dest, Object msg, int pid) -{ - /* Assuming that the sender corresponds to the source node */ - E2ETransport sender = (E2ETransport) src.getProtocol(tid); - E2ETransport receiver = (E2ETransport) dest.getProtocol(tid); - long latency = - E2ENetwork.getLatency(sender.router, receiver.router) + local*2; - EDSimulator.add(latency, msg, dest, pid); -} - -//--------------------------------------------------------------------- - -/** -* Calculates latency using the static singleton {@link E2ENetwork}. -* It looks up which routers the given nodes are assigned to, then -* looks up the corresponding latency. Finally it increments this value -* by adding twice the local delay configured by {@value #PAR_LOCAL}. -*/ -public long getLatency(Node src, Node dest) -{ - /* Assuming that the sender corresponds to the source node */ - E2ETransport sender = (E2ETransport) src.getProtocol(tid); - E2ETransport receiver = (E2ETransport) dest.getProtocol(tid); - return E2ENetwork.getLatency(sender.router, receiver.router) + local*2; -} - - -//--------------------------------------------------------------------- -//Methods inherited by RouterInfo -//--------------------------------------------------------------------- - -/** - * Associates the node hosting this transport protocol instance with - * a router in the router network. - * - * @param router the numeric index of the router - */ -public void setRouter(int router) -{ - this.router = router; -} - -//--------------------------------------------------------------------- - -/** - * @return the router associated to this transport protocol. - */ -public int getRouter() -{ - return router; -} - -} diff --git a/contrib/psg/src/peersim/transport/KingParser.java b/contrib/psg/src/peersim/transport/KingParser.java deleted file mode 100644 index 1471796e0e..0000000000 --- a/contrib/psg/src/peersim/transport/KingParser.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - -import java.io.*; -import java.util.*; -import peersim.config.*; -import peersim.core.Control; - -/** - * Initializes static singleton {@link E2ENetwork} by reading a king data set. - * - * @author Alberto Montresor - * @version $Revision: 1.9 $ - */ -public class KingParser implements Control -{ - -// --------------------------------------------------------------------- -// Parameters -// --------------------------------------------------------------------- - -/** - * The file containing the King measurements. - * @config - */ -private static final String PAR_FILE = "file"; - -/** - * The ratio between the time units used in the configuration file and the - * time units used in the Peersim simulator. - * @config - */ -private static final String PAR_RATIO = "ratio"; - -// --------------------------------------------------------------------- -// Fields -// --------------------------------------------------------------------- - -/** Name of the file containing the King measurements. */ -private String filename; - -/** - * Ratio between the time units used in the configuration file and the time - * units used in the Peersim simulator. - */ -private double ratio; - -/** Prefix for reading parameters */ -private String prefix; - -// --------------------------------------------------------------------- -// Initialization -// --------------------------------------------------------------------- - -/** - * Read the configuration parameters. - */ -public KingParser(String prefix) -{ - this.prefix = prefix; - ratio = Configuration.getDouble(prefix + "." + PAR_RATIO, 1); - filename = Configuration.getString(prefix + "." + PAR_FILE, null); -} - -// --------------------------------------------------------------------- -// Methods -// --------------------------------------------------------------------- - -/** - * Initializes static singleton {@link E2ENetwork} by reading a king data set. -* @return always false -*/ -public boolean execute() -{ - BufferedReader in = null; - if (filename != null) { - try { - in = new BufferedReader(new FileReader(filename)); - } catch (FileNotFoundException e) { - throw new IllegalParameterException(prefix + "." + PAR_FILE, filename - + " does not exist"); - } - } else { - in = new BufferedReader( new InputStreamReader( - ClassLoader.getSystemResourceAsStream("t-king.map") - ) ); - } - - // XXX If the file format is not correct, we will get quite obscure - // exceptions. To be improved. - - String line = null; - // Skip initial lines - int size = 0; - int lc = 1; - try { - while ((line = in.readLine()) != null && !line.startsWith("node")) lc++; - while (line != null && line.startsWith("node")) { - size++; - lc++; - line = in.readLine(); - } - } catch (IOException e) { - System.err.println("KingParser: " + filename + ", line " + lc + ":"); - e.printStackTrace(); - try { in.close(); } catch (IOException e1) { }; - System.exit(1); - } - E2ENetwork.reset(size, true); - if (line == null) { - System.err.println("KingParser: " + filename + ", line " + lc + ":"); - System.err.println("No latency matrix contained in the specified file"); - try { in.close(); } catch (IOException e1) { }; - System.exit(1); - } - - System.err.println("KingParser: read " + size + " entries"); - - try { - do { - StringTokenizer tok = new StringTokenizer(line, ", "); - if (tok.countTokens() != 3) { - System.err.println("KingParser: " + filename + ", line " + lc + ":"); - System.err.println("Specified line does not contain a triple"); - try { in.close(); } catch (IOException e1) { }; - System.exit(1); - } - int n1 = Integer.parseInt(tok.nextToken()) - 1; - int n2 = Integer.parseInt(tok.nextToken()) - 1; - int latency = (int) (Double.parseDouble(tok.nextToken()) * ratio); - E2ENetwork.setLatency(n1, n2, latency); - lc++; - line = in.readLine(); - } while (line != null); - - in.close(); - - } catch (IOException e) { - System.err.println("KingParser: " + filename + ", line " + lc + ":"); - e.printStackTrace(); - try { in.close(); } catch (IOException e1) { }; - System.exit(1); - } - - - return false; -} - -} diff --git a/contrib/psg/src/peersim/transport/RouterInfo.java b/contrib/psg/src/peersim/transport/RouterInfo.java deleted file mode 100644 index be3c168e74..0000000000 --- a/contrib/psg/src/peersim/transport/RouterInfo.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - -/** - * Generic interface to be implemented by protocols that need to be assigned to - * routers. The idea is that each node is assigned to a router, by - * invoking {@link #setRouter(int)} method. Routers are identified by - * integer indexes (starting from 0), based on the assumption that the - * router network - * is static. The router information is then used by different - * implementations to compute latency, congestion, etc. - * - * @author Alberto Montresor - * @version $Revision: 1.4 $ - */ -public interface RouterInfo -{ - -/** - * Associates the node hosting this transport protocol instance with - * a router in the router network. - * - * @param router the numeric index of the router - */ -public void setRouter(int router); - -/** - * @return the router associated to this transport protocol. - */ -public int getRouter(); - -} diff --git a/contrib/psg/src/peersim/transport/Transport.java b/contrib/psg/src/peersim/transport/Transport.java deleted file mode 100644 index 4606283414..0000000000 --- a/contrib/psg/src/peersim/transport/Transport.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - -import peersim.core.*; - - -/** - * This interface represents a generic transport protocol, used to - * send messages through the underlying network. Generally, transport - * protocols use {@link peersim.edsim.EDSimulator} to schedule the delivery of - * messages with some appropriate delay. They can also model message omission - * failure as well. - * - * @author Alberto Montresor - * @version $Revision: 1.7 $ - */ -public interface Transport extends Protocol -{ - -/** - * Sends message msg from node src to protocol - * pid of node dst. - * - * @param src sender node - * @param dest destination node - * @param msg message to be sent - * @param pid protocol identifier - */ -public void send(Node src, Node dest, Object msg, int pid); - - -/** - * Return a latency estimate from node src to protocol - * pid of node dst. - * - * @param src sender node - * @param dest destination node - */ -public long getLatency(Node src, Node dest); - - -} diff --git a/contrib/psg/src/peersim/transport/TriangularMatrixParser.java b/contrib/psg/src/peersim/transport/TriangularMatrixParser.java deleted file mode 100644 index d3f0768855..0000000000 --- a/contrib/psg/src/peersim/transport/TriangularMatrixParser.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - -import java.io.*; - -import peersim.config.*; -import peersim.core.*; - -/** - * Initializes static singleton {@link E2ENetwork} by reading a trace - * file containing the latency distance measured between a set of - * "virtual" routers. Latency is assumed to be symmetric, so the - * latency between x and y is equal to the latency to y and x. - * - * The format of the file is as follows: all values are stored as - * integers. The first value is the number of nodes considered. - * The rest of the values correspond to a "strictly upper triangular - * matrix" (see this - * - * link), ordered first by row than by column. - * - * @author Alberto Montresor - * @version $Revision: 1.4 $ - */ -public class TriangularMatrixParser implements Control -{ - -// --------------------------------------------------------------------- -// Parameters -// --------------------------------------------------------------------- - -/** - * This configuration parameter identifies the filename of the file - * containing the measurements. First, the file is used as a pathname - * in the local file system. If no file can be identified in this way, - * the file is searched in the local classpath. If the file cannot be - * identified again, an error message is reported. - * @config - */ -private static final String PAR_FILE = "file"; - -/** - * The ratio between the time units used in the configuration file and the - * time units used in the Peersim simulator. - * @config - */ -private static final String PAR_RATIO = "ratio"; - -// --------------------------------------------------------------------- -// Fields -// --------------------------------------------------------------------- - -/** Name of the file containing the measurements. */ -private String filename; - -/** Ratio read from PAR_RATIO */ -private double ratio; - -// --------------------------------------------------------------------- -// Initialization -// --------------------------------------------------------------------- - -/** - * Read the configuration parameters. - */ -public TriangularMatrixParser(String prefix) -{ - filename = Configuration.getString(prefix + "." + PAR_FILE); - ratio = Configuration.getDouble(prefix + "." + PAR_RATIO); -} - -// --------------------------------------------------------------------- -// Methods -// --------------------------------------------------------------------- - -/** - * Initializes static singleton {@link E2ENetwork} by reading a king data set. -* @return always false -*/ -public boolean execute() -{ - try { - ObjectInputStream in = null; - try { - in = new ObjectInputStream( - new BufferedInputStream( - new FileInputStream(filename))); - System.err.println("TriangularMatrixParser: Reading " + filename + " from local file system"); - } catch (FileNotFoundException e) { - in = new ObjectInputStream( - new BufferedInputStream( - ClassLoader.getSystemResourceAsStream(filename))); - System.err.println("TriangularMatrixParser: Reading " + filename + " through the class loader"); - } - - // Read the number of nodes in the file (first four bytes). - int size = in.readInt(); - - // Reset the E2E network - E2ENetwork.reset(size, true); - System.err.println("TriangularMatrixParser: reading " + size + " rows"); - - // If the file format is not correct, data will be read - // incorrectly. Probably a good way to spot this is the - // presence of negative delays, or an end of file. - - // Reading data - int count = 0; - for (int r=0; r < size; r++) { - for (int c = r+1; c < size; c++) { - int x = (int) (ratio*in.readInt()); - count++; - E2ENetwork.setLatency(r,c,x); - } - } - System.err.println("TriangularMatrixParser: Read " + count + " entries"); - } catch (IOException e) { - throw new RuntimeException(e.getMessage()); - } - return false; -} - -} diff --git a/contrib/psg/src/peersim/transport/UniformRandomTransport.java b/contrib/psg/src/peersim/transport/UniformRandomTransport.java deleted file mode 100644 index 1abc6d85af..0000000000 --- a/contrib/psg/src/peersim/transport/UniformRandomTransport.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - -import peersim.config.*; -import peersim.core.*; -import peersim.edsim.*; - - -/** - * Implement a transport layer that reliably delivers messages with a random - * delay, that is drawn from the configured interval according to the uniform - * distribution. - * - * @author Alberto Montresor - * @version $Revision: 1.14 $ - */ -public final class UniformRandomTransport implements Transport -{ - -//--------------------------------------------------------------------- -//Parameters -//--------------------------------------------------------------------- - -/** - * String name of the parameter used to configure the minimum latency. - * @config - */ -private static final String PAR_MINDELAY = "mindelay"; - -/** - * String name of the parameter used to configure the maximum latency. - * Defaults to {@value #PAR_MINDELAY}, which results in a constant delay. - * @config - */ -private static final String PAR_MAXDELAY = "maxdelay"; - -//--------------------------------------------------------------------- -//Fields -//--------------------------------------------------------------------- - -/** Minimum delay for message sending */ -private final long min; - -/** Difference between the max and min delay plus one. That is, max delay is -* min+range-1. -*/ -private final long range; - - -//--------------------------------------------------------------------- -//Initialization -//--------------------------------------------------------------------- - -/** - * Reads configuration parameter. - */ -public UniformRandomTransport(String prefix) -{ - min = Configuration.getLong(prefix + "." + PAR_MINDELAY); - long max = Configuration.getLong(prefix + "." + PAR_MAXDELAY,min); - if (max < min) - throw new IllegalParameterException(prefix+"."+PAR_MAXDELAY, - "The maximum latency cannot be smaller than the minimum latency"); - range = max-min+1; -} - -//--------------------------------------------------------------------- - -/** -* Returns this. This way only one instance exists in the system -* that is linked from all the nodes. This is because this protocol has no -* node specific state. -*/ -public Object clone() -{ - return this; -} - -//--------------------------------------------------------------------- -//Methods -//--------------------------------------------------------------------- - -/** - * Delivers the message with a random - * delay, that is drawn from the configured interval according to the uniform - * distribution. -*/ -public void send(Node src, Node dest, Object msg, int pid) -{ - // avoid calling nextLong if possible - long delay = (range==1?min:min + CommonState.r.nextLong(range)); - EDSimulator.add(delay, msg, dest, pid); -} - -/** - * Returns a random - * delay, that is drawn from the configured interval according to the uniform - * distribution. -*/ -public long getLatency(Node src, Node dest) -{ - return (range==1?min:min + CommonState.r.nextLong(range)); -} - - -} diff --git a/contrib/psg/src/peersim/transport/UniformRouterAssignment.java b/contrib/psg/src/peersim/transport/UniformRouterAssignment.java deleted file mode 100644 index 064ba7d04b..0000000000 --- a/contrib/psg/src/peersim/transport/UniformRouterAssignment.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - -import peersim.config.*; -import peersim.core.*; - - -/** - * Initializes {@link RouterInfo} protocols by assigning routers to them. - * The number of routers is defined by static singleton {@link E2ENetwork}. - * - * @author Alberto Montresor - * @version $Revision: 1.6 $ - */ -public class UniformRouterAssignment implements Control -{ - -//--------------------------------------------------------------------- -//Parameters -//--------------------------------------------------------------------- - -/** - * Parameter name used to configure the {@link RouterInfo} protocol - * that should be initialized. - * @config - */ -private static final String PAR_PROT = "protocol"; - -//--------------------------------------------------------------------- -//Methods -//--------------------------------------------------------------------- - -/** Protocol identifier */ -private int pid; - - -//--------------------------------------------------------------------- -//Initialization -//--------------------------------------------------------------------- - -/** - * Reads configuration parameters. - */ -public UniformRouterAssignment(String prefix) -{ - pid = Configuration.getPid(prefix+"."+PAR_PROT); -} - -//--------------------------------------------------------------------- -//Methods -//--------------------------------------------------------------------- - -/** - * Initializes given {@link RouterInfo} protocol layer by assigning - * routers randomly. - * The number of routers is defined by static singleton {@link E2ENetwork}. -* @return always false -*/ -public boolean execute() -{ - int nsize = Network.size(); - int nrouters = E2ENetwork.getSize(); - for (int i=0; i < nsize; i++) { - Node node = Network.get(i); - RouterInfo t = (RouterInfo) node.getProtocol(pid); - int r = CommonState.r.nextInt(nrouters); - t.setRouter(r); - } - - return false; -} - -} - diff --git a/contrib/psg/src/peersim/transport/UnreliableTransport.java b/contrib/psg/src/peersim/transport/UnreliableTransport.java deleted file mode 100644 index 94608806c6..0000000000 --- a/contrib/psg/src/peersim/transport/UnreliableTransport.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.transport; - -import peersim.config.*; -import peersim.core.*; - - -/** - * This transport protocol can be combined with other transports - * to simulate message losses. Its behavior is the following: each message - * can be dropped based on the configured probability, or it will be sent - * using the underlying transport protocol. - *

    - * The memory requirements are minimal, as a single instance is created and - * inserted in the protocol array of all nodes (because instances have no state - * that depends on the hosting node). - * - * @author Alberto Montresor - * @version $Revision: 1.13 $ - */ -public final class UnreliableTransport implements Transport -{ - -//--------------------------------------------------------------------- -//Parameters -//--------------------------------------------------------------------- - -/** - * The name of the underlying transport protocol. This transport is - * extended with dropping messages. - * @config - */ -private static final String PAR_TRANSPORT = "transport"; - -/** - * String name of the parameter used to configure the probability that a - * message sent through this transport is lost. - * @config - */ -private static final String PAR_DROP = "drop"; - - -//--------------------------------------------------------------------- -//Fields -//--------------------------------------------------------------------- - -/** Protocol identifier for the support transport protocol */ -private final int transport; - -/** Probability of dropping messages */ -private final float loss; - -//--------------------------------------------------------------------- -//Initialization -//--------------------------------------------------------------------- - -/** - * Reads configuration parameter. - */ -public UnreliableTransport(String prefix) -{ - transport = Configuration.getPid(prefix+"."+PAR_TRANSPORT); - loss = (float) Configuration.getDouble(prefix+"."+PAR_DROP); -} - -//--------------------------------------------------------------------- - -/** -* Returns this. This way only one instance exists in the system -* that is linked from all the nodes. This is because this protocol has no -* state that depends on the hosting node. - */ -public Object clone() -{ - return this; -} - -//--------------------------------------------------------------------- -//Methods -//--------------------------------------------------------------------- - -/** Sends the message according to the underlying transport protocol. -* With the configured probability, the message is not sent (i.e. the method does -* nothing). -*/ -public void send(Node src, Node dest, Object msg, int pid) -{ - try - { - if (CommonState.r.nextFloat() >= loss) - { - // Message is not lost - Transport t = (Transport) src.getProtocol(transport); - t.send(src, dest, msg, pid); - } - } - catch(ClassCastException e) - { - throw new IllegalArgumentException("Protocol " + - Configuration.lookupPid(transport) + - " does not implement Transport"); - } -} - -/** Returns the latency of the underlying protocol.*/ -public long getLatency(Node src, Node dest) -{ - Transport t = (Transport) src.getProtocol(transport); - return t.getLatency(src, dest); -} - -} diff --git a/contrib/psg/src/peersim/util/ExtendedRandom.java b/contrib/psg/src/peersim/util/ExtendedRandom.java deleted file mode 100644 index 14e713e767..0000000000 --- a/contrib/psg/src/peersim/util/ExtendedRandom.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.util; - -import java.util.Random; -import java.lang.Math; - -/** - * Extends the functionality of java.util.Random. - */ -public class ExtendedRandom extends Random { - -private long lastSeed; - -// ------------------------------------------------------------------------- - -/** Calls super constructor. Also stores the seed to be returned by -{@link #getLastSeed}. */ -public ExtendedRandom(long seed) { - - super(seed); - lastSeed = seed; -} - -// ------------------------------------------------------------------------- - -/** - * Extracts the next integer, according to a Poisson distribution. - * - * @param mean The mean of the Poisson distribution. - * @return An integer Poisson extraction. - */ -public int nextPoisson(double mean) { - - double emean = Math.exp(-1 * mean); - double product = 1; - int count = 0; - int result = 0; - while (product >= emean) { - product *= nextDouble(); - result = count; - count++; // keep result one behind - } - return result; -} - -// ------------------------------------------------------------------------- - -/** -* Implements nextLong(long) the same way nexInt(int) is implemented in -* java.util.Random. -* @param n the bound on the random number to be returned. Must be positive. -* @return a pseudorandom, uniformly distributed long value between 0 -* (inclusive) and n (exclusive). -*/ -public long nextLong(long n) { - - if (n<=0) - throw new IllegalArgumentException("n must be positive"); - - if ((n & -n) == n) // i.e., n is a power of 2 - { - return nextLong()&(n-1); - } - - long bits, val; - do - { - bits = (nextLong()>>>1); - val = bits % n; - } - while(bits - val + (n-1) < 0); - - return val; -} - -// ------------------------------------------------------------------------- - -/** Sets random seed. Calls super method but also stores the seed to be -returned by {@link #getLastSeed}. */ -public void setSeed( long seed ) { - - super.setSeed(seed); - lastSeed = seed; -} - -// ------------------------------------------------------------------------- - -/** -* Returns the last random seed that was set explicitly. Either at -* construction time or through {@link #setSeed}. -*/ -public long getLastSeed() { return lastSeed; } - -// ------------------------------------------------------------------------- - -/* -public static void main(String[] args) { - - ExtendedRandom er = new ExtendedRandom(12345678); - for(int i=0; i<100; ++i) - System.out.println(er.nextLong(Long.parseLong(args[0]))); - -} -*/ -} - diff --git a/contrib/psg/src/peersim/util/FileNameGenerator.java b/contrib/psg/src/peersim/util/FileNameGenerator.java deleted file mode 100644 index c07d9252d9..0000000000 --- a/contrib/psg/src/peersim/util/FileNameGenerator.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.util; - -import java.io.*; - - -/** -* Generates a series of filenames for classes that have to save e.g. -* snapshots regularly. -*/ -public class FileNameGenerator { - - -/** -* The number of filenames already returned. -*/ -private long counter = 0; - -/** The prefix of the filename */ -public final String prefix; - -/** The extension of the filename */ -public final String ext; - - -// ==================== initialization ============================== -// ================================================================== - - -/** -* @param prefix all returned names will be prefixed by this -* @param ext will be appended to all returned names -*/ -public FileNameGenerator(String prefix, String ext) { - - this.prefix=prefix; - this.ext=ext; -} - - -// ===================== methods ==================================== -// ================================================================== - - -/** -* Generates a name based on a counter. -* The format of the name returned is {@link #prefix} followed by -* an 8 digit zero padded number, followed by {@link #ext}. -* The first number used is zero. -* @return the next filename after increasing the counter -*/ -public String nextCounterName() { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - (new PrintStream(baos)).printf("%08d",counter); - counter++; - return prefix+baos.toString()+ext; -} - -// ------------------------------------------------------------------ - -/* -public static void main(String args[]) { - - FileNameGenerator fng = new FileNameGenerator(args[0],args[1]); - for(int i=0; i<100; ++i) System.err.println(fng.nextCounterName()); -} -*/ -} - diff --git a/contrib/psg/src/peersim/util/IncrementalFreq.java b/contrib/psg/src/peersim/util/IncrementalFreq.java deleted file mode 100644 index 3352daf3cf..0000000000 --- a/contrib/psg/src/peersim/util/IncrementalFreq.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.util; - -import java.io.PrintStream; - -//XXX This implementation is very restricted, to be made more flexible -// using hashtables. -/** -* A class that can collect frequency information on integer input. -* right now it can handle only unsigned input. It simply ignores negative -* numbers. -*/ -public class IncrementalFreq implements Cloneable { - - -// ===================== fields ======================================== -// ===================================================================== - -/** The number of items inserted. */ -private int n; - -/** freq[i] holds the frequency of i. primitive implementation, to be changed */ -private int[] freq = null; - -/** -* The capacity, if larger than 0. Added values larger than or equal to -* this one will be ignored. -*/ -private final int N; - - -// ====================== initialization ============================== -// ==================================================================== - - -/** -* @param maxvalue Values in the input set larger than this one will be ignored. -* However, if it is negative, no values are ignored. -*/ -public IncrementalFreq(int maxvalue) { - - N = maxvalue+1; - reset(); -} - -// -------------------------------------------------------------------- - -/** Calls this(-1), that is, no values will be ignored. -* @see #IncrementalFreq(int) */ -public IncrementalFreq() { - - this(-1); -} - -// -------------------------------------------------------------------- - -/** Reset the state of the object. After calling this, all public methods -* behave the same as they did after constructing the object. -*/ -public void reset() { - - if( freq==null || N==0 ) freq = new int[0]; - else for(int i=0; ii to the input set. - * It calls add(i,1). - * @see #add(int,int) - */ -public final void add( int i ) { add(i,1); } - - -// -------------------------------------------------------------------- - -/** - * Adds item i to the input set k times. - * That is, it increments counter i by k. - * If, however, i is negative, or larger than the maximum defined - * at construction time (if a maximum was set at all) the operation is ignored. - */ -public void add( int i, int k ) { - - if( N>0 && i>=N ) return; - if( i<0 || k<=0 ) return; - - // Increase number of items by k. - n+=k; - - // If index i is out of bounds for the current array of counters, - // increase the size of the array to i+1. - if( i>=freq.length ) - { - int tmp[] = new int[i+1]; - System.arraycopy(freq, 0, tmp, 0, freq.length); - freq=tmp; - } - - // Finally, increase counter i by k. - freq[i]+=k; -} - -// -------------------------------------------------------------------- - -/** Returns number of processed data items. -* This is the number of items over which the class holds statistics. -*/ -public int getN() { return n; } - -// -------------------------------------------------------------------- - -/** Returns the number of occurrences of the given integer. */ -public int getFreq(int i) { - - if( i>=0 && istrict is true, it - * throws an IllegalArgumentException if this is - * not strictly larger than other (element by element) - * (Note that both frequency vectors are positive.) - * Otherwise just sets those elements in this to zero - * that are smaller than those of other. - * @param other The instance of IncrementalFreq to subtract - * @param strict See above explanation - */ -public void remove(IncrementalFreq other, boolean strict) { - - // check if other has non-zero elements in non-overlapping part - if(strict && other.freq.length>freq.length) - { - for(int i=other.freq.length-1; i>=freq.length; --i) - { - if (other.freq[i]!=0) - throw new IllegalArgumentException(); - } - } - - final int minLength = Math.min(other.freq.length, freq.length); - for (int i=minLength-1; i>=0; i--) - { - if (strict && freq[i] < other.freq[i]) - throw new IllegalArgumentException(); - final int remove = Math.min(other.freq[i], freq[i]); - n -= remove; - freq[i] -= remove; - } -} - -// --------------------------------------------------------------------- - -/** -* Prints current frequency information. Prints a separate line for -* all values from 0 to the capacity of the internal representation using the -* format -*

    -* value occurrences
    -* 
    -* That is, numbers with zero occurrences will also be printed. -*/ -public void printAll( PrintStream out ) { - - for(int i=0; i -* value occurrences -* -*/ -public void print( PrintStream out ) { - - for(int i=0; i=0; i--) - { - if (freq[i] != 0) - result.append(freq[i]).append( - "*").append(i).append("+"); - } - - if (result.length()==0) - return "(empty)"; - else - return result.substring(0, result.length()-1); -} - -// --------------------------------------------------------------------- - -public Object clone() throws CloneNotSupportedException { - - IncrementalFreq result = (IncrementalFreq)super.clone(); - if( freq != null ) result.freq = freq.clone(); - return result; -} - -// --------------------------------------------------------------------- - -/** -* Tests equality between two IncrementalFreq instances. -* Two objects are equal if both hold the same set of numbers that have -* occurred non-zero times and the number of occurrences is also equal for -* these numbers. -*/ -public boolean equals(Object obj) { - - if( !( obj instanceof IncrementalFreq) ) return false; - IncrementalFreq other = (IncrementalFreq)obj; - final int minlength = Math.min(other.freq.length, freq.length); - - for (int i=minlength-1; i>=0; i--) - if (freq[i] != other.freq[i]) - return false; - - if( freq.length > minlength ) other=this; - for (int i=minlength; iadd(item,1). -* @see #add(double,int) */ -public final void add( double item ) { add(item,1); } - -// -------------------------------------------------------------------- - -/** Updates the statistics assuming element item is added -* k times.*/ -public void add( double item, int k ) { - - if( item < min ) - { - min = item; - countmin = 0; - } - if( item == min ) countmin+=k; - if( item > max ) - { - max = item; - countmax = 0; - } - if(item == max) countmax+=k; - n+=k; - if( k == 1 ) - { - sum += item; - sqrsum += item*item; - } - else - { - sum += item*k; - sqrsum += item*item*k; - } -} - -// -------------------------------------------------------------------- - -/** The number of data items processed so far */ -public int getN() { return n; } - -// -------------------------------------------------------------------- - -/** The maximum of the data items */ -public double getMax() { return max; } - -// -------------------------------------------------------------------- - -/** The minimum of the data items */ -public double getMin() { return min; } - -// -------------------------------------------------------------------- - -/** Returns the number of data items whose value equals the maximum. */ -public int getMaxCount() { return countmax; } - -// -------------------------------------------------------------------- - -/** Returns the number of data items whose value equals the minimum. */ -public int getMinCount() { return countmin; } - -// -------------------------------------------------------------------- - -/** The sum of the data items */ -public double getSum() { return sum; } - -// -------------------------------------------------------------------- - -/** The sum of the squares of the data items */ -public double getSqrSum() { return sqrsum; } - -// -------------------------------------------------------------------- - -/** The average of the data items */ -public double getAverage() { return sum/n; } - -// -------------------------------------------------------------------- - -/** The empirical variance of the data items. Guaranteed to be larger or -equal to 0.0. If due to rounding errors the value becomes negative, -it returns 0.0.*/ -public double getVar() { - - double var= - (((double)n) / (n-1)) * (sqrsum/n - getAverage()*getAverage()); - return (var>=0.0?var:0.0); - // XXX note that we have very little possibility to increase numeric - // stability if this class is "greedy", ie, if it has no memory - // In a more precise implementation we could delay the calculation of - // statistics and store the data in some intelligent structure -} - -// -------------------------------------------------------------------- - -/** the empirical standard deviation of the data items */ -public double getStD() { return Math.sqrt(getVar()); } - -// -------------------------------------------------------------------- - -/** -* Prints the following quantities separated by spaces in a single line -* in this order. -* Minimum, maximum, number of items, average, variance, number of minimal -* items, number of maximal items. -*/ -public String toString() { - - return min+" "+max+" "+n+" "+sum/n+" "+getVar()+" "+ - countmin+" "+countmax; -} - -} - diff --git a/contrib/psg/src/peersim/util/IndexIterator.java b/contrib/psg/src/peersim/util/IndexIterator.java deleted file mode 100644 index 8d078ab372..0000000000 --- a/contrib/psg/src/peersim/util/IndexIterator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.util; - -/** -* This class provides iterations over the set of integers [0...k-1]. -*/ -public interface IndexIterator { - - /** - * This resets the iteration. The set of integers will be 0,..,k-1. - */ - public void reset(int k); - - /** - * Returns next index. - */ - public int next(); - - /** - * Returns true if {@link #next} can be called at least one more time. - * Note that {@link #next} can be called k times after {@link #reset}. - */ - public boolean hasNext(); -} - diff --git a/contrib/psg/src/peersim/util/LinearIterator.java b/contrib/psg/src/peersim/util/LinearIterator.java deleted file mode 100644 index 2a1ee36dee..0000000000 --- a/contrib/psg/src/peersim/util/LinearIterator.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.util; - -import java.util.NoSuchElementException; - -/** -* This class gives the linear order 0,1,etc or alternatively k-1, k-2, etc., -* depending on the constructor. -*/ -public class LinearIterator implements IndexIterator { - - -// ======================= private fields ============================ -// =================================================================== - -private final boolean reverse; - -private int len = 0; - -private int pointer = 0; - - -// ======================= initialization ============================ -// =================================================================== - - -/** -* Construct an iterator for an empty set of numbers. -* You have to call {@link #reset} to actually fully initialize the object. -* The numbers returned by consecutive calls to {@link #next} are 0,1,... -*/ -public LinearIterator() { reverse=false; } - -// ------------------------------------------------------------------- - -/** -* Construct an interator for an empty set of numbers. -* You have to call {@link #reset} to actually fully initialize the object. -* If parameter is true then the numbers returned by consecutive calls to -* {@link #next} are k-1,k-2,..., otherwise 0,1,... -*/ -public LinearIterator( boolean rev ) { reverse=rev; } - - -// ======================= public methods ============================ -// =================================================================== - - -public void reset(int k) { - - len = k; - pointer = (reverse ? len-1 : 0); -} - -// ------------------------------------------------------------------- - -/** -* Returns next index. The indices are returned in increasing or decreasing -* order depending on the parameter given at construction time. -*/ -public int next() { - - if( !hasNext() ) throw new NoSuchElementException(); - - return (reverse ? pointer-- : pointer++); -} - -// ------------------------------------------------------------------- - -public boolean hasNext() { return (reverse ? pointer >= 0 : pointer < len); } - -// ------------------------------------------------------------------- - -/* -public static void main( String pars[] ) throws Exception { - - LinearIterator rp = new LinearIterator(pars[0].equals("rev")); - - int k = Integer.parseInt(pars[1]); - rp.reset(k); - while(rp.hasNext()) System.out.println(rp.next()); - - System.out.println(); - - k = Integer.parseInt(pars[2]); - rp.reset(k); - while(rp.hasNext()) System.out.println(rp.next()); - System.out.println(rp.next()); -} -*/ -} diff --git a/contrib/psg/src/peersim/util/MedianStats.java b/contrib/psg/src/peersim/util/MedianStats.java deleted file mode 100644 index be1e9be6d0..0000000000 --- a/contrib/psg/src/peersim/util/MedianStats.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.util; - -import java.util.ArrayList; -import java.util.Collections; - -/** - * This class adds the ability to retrieve the median element to the - * {@link IncrementalStats} class. Note that this class actually stores all - * the elements, so (unlike in its superclass) storage requirements depend - * on the number of items processed. - * - * @author giampa - */ -public class MedianStats extends IncrementalStats -{ - -/** Structure to store each entry. */ -private final ArrayList data=new ArrayList(); - -/** Calls {@link #reset}. */ -public MedianStats() -{ - reset(); -} - -/** - * Retrieves the median in the current data collection. - * - * @return The current median value. - */ -public double getMedian() -{ - double result; - - if (data.isEmpty()) - throw new IllegalStateException("Data vector is empty!"); - - // Sort the arraylist - Collections.sort(data); - if (data.size() % 2 != 0) { // odd number - result = data.get(data.size() / 2); - } else { // even number: - double a = data.get(data.size() / 2); - double b = data.get(data.size() / 2 - 1); - result = (a + b) / 2; - } - return result; -} - -public void add(double item, int k) -{ - for (int i = 0; i < k; ++i) { - super.add(item, 1); - data.add(new Double(item)); - } -} - -public void reset() -{ - super.reset(); - if (data != null) - data.clear(); -} - - -public static void main( String[] args ) { - MedianStats s = new MedianStats(); - for(int i=0; i1; i--) - { - int j = r.nextInt(i); - int a = buffer[j]; - buffer[j] = buffer[i-1]; - buffer[i-1] = a; - } -} - -// ------------------------------------------------------------------- - -/** -* Returns the ith element of the permutation set by {@link #setPermutation}. -* If {@link #next} is called after {@link #setPermutation} and before -* this method, then the behavior of this method is unspecified. -*/ -public int get(int i) { - - if( i >= len ) throw new IndexOutOfBoundsException(); - return buffer[i]; -} - -// ------------------------------------------------------------------- - -/** -* It initiates a random permutation of the integers from 0 to k-1. -* It does not actually calculate the permutation. -* The permutation can be read using method {@link #next}. -* Calls to {@link #get} return undefined values, so {@link #next} must be used. -* If the previous permutation was of the same length, it is more efficient. -*/ -public void reset(int k) { - - pointer = k; - if( len == k ) return; - - if( buffer == null || buffer.length < k ) - { - buffer = new int[k]; - } - - len = k; - for( int i=0; i 0; } - -// ------------------------------------------------------------------- - -/* -public static void main( String pars[] ) throws Exception { - - RandPermutation rp = new RandPermutation(new Random()); - - int k; - - k = Integer.parseInt(pars[0]); - rp.setPermutation(k); - for(int i=0; i - * The language for range expression is the following: - *
    - *   [rangelist] := [range] | [range],[rangelist]
    - *   [range] := value | min:max | min:max|step | 
    - *      min:max*|step
    - * 
    - * where value, min, max and step - * are numeric atoms that defines ranges. - *

    - * For example, the following range expression: - *

    - *   5,9:11,13:17|2,32:128*|2
    - * 
    - * corresponds to 5 (single value), 9-10-11 (range between 9 and 11, - * default increment 1), 13-15-17 (range between 13 and 17, specified - * step 2, 32-64-128 (range between 32 and 128, multiplicative step 2). - * - * @author Alberto Montresor - * @version $Revision: 1.8 $ - */ -public class StringListParser -{ - -/** Disable instance construction */ -private StringListParser() { } - -/** - * Parse the specified string. - * - * @param s the string to be parsed - * @return an array of strings containing all the values defined by the - * range string - */ -public static String[] parseList(String s) -{ - ArrayList list = new ArrayList(); - String[] tokens = s.split(","); - for (int i = 0; i < tokens.length; i++) { - parseItem(list, tokens[i]); - } - return list.toArray(new String[list.size()]); -} - -private static void parseItem(List list, String item) -{ - String[] array = item.split(":"); - if (array.length == 1) { - parseSingleItem(list, item); - } else if (array.length == 2) { - parseRangeItem(list, array[0], array[1]); - } else { - throw new IllegalArgumentException("Element " + item - + "should be formatted as : or "); - } -} - -private static void parseSingleItem(List list, String item) -{ - list.add(item); -} - -private static void parseRangeItem(List list, String start, String stop) -{ - Number vstart; - Number vstop; - Number vinc; - boolean sum; - - GroupJep jep = new GroupJep(new Operators()); - jep.parseExpression(start); - vstart = (Number) jep.getValueAsObject(); - int pos = stop.indexOf("|*"); - if (pos >= 0) { - // The string contains a multiplicative factor - jep.parseExpression(stop.substring(0, pos)); - vstop = (Number) jep.getValueAsObject(); - jep.parseExpression(stop.substring(pos + 2)); - vinc = (Number) jep.getValueAsObject(); - sum = false; - } else { - pos = stop.indexOf("|"); - // The string contains an additive factor - if (pos >= 0) { - // The string contains just the final value - jep.parseExpression(stop.substring(0, pos)); - vstop = (Number) jep.getValueAsObject(); - jep.parseExpression(stop.substring(pos + 1)); - vinc = (Number) jep.getValueAsObject(); - sum = true; - } else { - jep.parseExpression(stop); - vstop = (Number) jep.getValueAsObject(); - vinc = BigInteger.ONE; - sum = true; - } - } - - if (vstart instanceof BigInteger && vstart instanceof BigInteger && vinc instanceof BigInteger) { - long vvstart = vstart.longValue(); - long vvstop = vstop.longValue(); - long vvinc = vinc.longValue(); - if (sum) { - for (long i = vvstart; i <= vvstop; i += vvinc) - list.add("" + i); - } else { - for (long i = vvstart; i <= vvstop; i *= vvinc) - list.add("" + i); - } - } else { - double vvstart = vstart.doubleValue(); - double vvstop = vstop.doubleValue(); - double vvinc = vinc.doubleValue(); - if (sum) { - for (double i = vvstart; i <= vvstop; i += vvinc) - list.add("" + i); - } else { - for (double i = vvstart; i <= vvstop; i *= vvinc) - list.add("" + i); - } - } -} - -/* -public static void main(String[] args) -{ - String[] ret = parseList(args[0]); - for (int i = 0; i < ret.length; i++) - System.out.print(ret[i] + " "); - System.out.println(""); -} -*/ -} diff --git a/contrib/psg/src/peersim/util/WeightedRandPerm.java b/contrib/psg/src/peersim/util/WeightedRandPerm.java deleted file mode 100644 index 80c8928900..0000000000 --- a/contrib/psg/src/peersim/util/WeightedRandPerm.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.util; - -import java.util.NoSuchElementException; -import java.util.Random; - -/** -* This class provides a weighted random permutation of indexes. -* Useful for weighted random sampling without replacement. -* The next sample is taken according to the weights given as a parameter -* to {@link #reset(int)}. -* The weights work as follows. -* The first sample is drawn according to the probability distribution -* defined by the (normalized) weights. -* After this the remaining k-1 elements and the associated k-1 -* (re-normalized) weights -* define a new probability distribution, according to which the 2nd element -* is drawn, and so on. -*/ -public class WeightedRandPerm implements IndexIterator { - - -// ======================= private fields ============================ -// =================================================================== - -/** Holds the weights that are used to initialize the permutation */ -private final double[] w; - -/** Holds the sum of the weights until the given index, inclusive. */ -private final double[] wsum; - -private int[] buffer = null; - -/** Working array for calculating the permutation */ -private double[] weights = null; - -private int len = 0; - -private int pointer = 0; - -private double sum = 0.0; - -private final Random r; - - -// ======================= initialization ============================ -// =================================================================== - - -/** Set the source of randomness to use and the weights. You need to call -* {@link #reset} to fully initialize the object. -* @param r source of randomness -* @param weights The array that holds the weights for the calculation of the -* permutation. The length of the array will be an upper bound on the -* parameter {@link #reset} accepts. If {@link #reset} is called with a -* parameter less than the length of weights, the prefix of the same length -* is used. -* The vector elements must be positive, that is, zero is not accepted either. -*/ -public WeightedRandPerm( Random r, double[] weights ) { - - this.r=r; - w = weights.clone(); - wsum = weights.clone();; - this.weights = new double[w.length]; - buffer = new int[w.length]; - - for(int i=0; i - * The method to be used is specified at construction time. - * For backward compatibility, if no method is specified, the method - * getValue is used. In this way, protocols - * implementing the {@link SingleValue} interface can be manipulated using the - * old configuration syntax (i.e., without specifying the method). - *

    - * Please refer to package {@link peersim.vector} for a detailed description of - * the concept of protocol vector and the role of getters and setters. - */ -public class Getter { - -// ============================ fields =================================== -// ======================================================================= - -private final String protocol; -private final String methodn; -private final String prefix; - -/** Identifier of the protocol that defines the vector */ -private int pid; - -/** Getter method name */ -private String methodName; - -/** Getter method */ -private Method method = null; - -/** Parameter type of getter method */ -private Class type; - - -// ========================== initialization ============================= -// ======================================================================= - - -/** - * Constructs a Getter class based on the configuration. Note that the - * actual initialization is delayed until the first access to the class, - * so that if a class is not used, no unnecessary error messages and exceptions - * are generated. - * @param prefix the configuration prefix to use when reading the configuration - * @param protocol the configuration parameter name that contains - * the protocol we want to manipulate using a getter method. - * The parameter prefix + "." + protocol is read. - * @param methodn the configuration parameter name that contains the getter - * method name. - * The parameter prefix + "." + methodn is read, with the default - * value getValue. - */ -public Getter(String prefix, String protocol, String methodn) { - - this.prefix=prefix; - this.protocol=protocol; - this.methodn=methodn; -} - -// -------------------------------------------------------------------------- - -/** Performs actual initialization */ -private void init() { - - if( method!=null) return; - - // Read configuration parameter - pid = Configuration.getPid(prefix + "." + protocol); - methodName = Configuration.getString(prefix+"."+methodn,"getValue"); - // Search the method - Class clazz = Network.prototype.getProtocol(pid).getClass(); - try { - method = GetterSetterFinder.getGetterMethod(clazz, methodName); - } catch (NoSuchMethodException e) { - throw new IllegalParameterException(prefix + "." + - methodn, e+""); - } - // Obtain the type of the field - type = GetterSetterFinder.getGetterType(method); -} - - -// =============================== methods ============================= -// ===================================================================== - -/** -* @return type of return value of getter method -*/ -public Class getType() { - - init(); - return type; -} - -// -------------------------------------------------------------------------- - -/** -* Gets the given value as a Number. -* @param n The node to get the value on. The protocol is defined -* by {@link #pid}. -* @return the read value. -*/ -public Number get(Node n) { - - init(); - - try - { - Object ret =method.invoke(n.getProtocol(pid)); - if (ret instanceof Boolean) - return ((Boolean) ret) ? 1 : 0; - else - return (Number) ret; - } - catch (Exception e) - { - throw new RuntimeException("While using getter "+methodName,e); - } -} - -// -------------------------------------------------------------------------- - -/** -* Gets the given integer value. -* @param n The node to get the value on. The protocol is defined -* by {@link #pid}. -* @return the read value. -*/ -public long getLong(Node n) { - - init(); - - if(type==long.class || type==int.class) - { - try - { - return ((Number) - method.invoke(n.getProtocol(pid))).longValue(); - } - catch (Exception e) - { - throw new RuntimeException( - "While using getter "+methodName,e); - } - } - else throw new RuntimeException("type has to be int or long"); -} - -// -------------------------------------------------------------------------- - -/** -* Gets the given real value. -* @param n The node to get the value on. The protocol is defined -* by {@link #pid}. -* @return the read value. -*/ -public double getDouble(Node n) { - - init(); - - if(type==double.class || type==float.class) - { - try - { - return ((Number) - method.invoke(n.getProtocol(pid))).doubleValue(); - } - catch (Exception e) - { - throw new RuntimeException( - "While using getter "+methodName,e); - } - } - else throw new RuntimeException( - "type has to be double or float"); -} - -// -------------------------------------------------------------------------- - -/** -* Gets the given value as a Number. -* @param i The index of the node to get the value on in the network. -* The protocol is defined -* by {@link #pid}. -* @return the read value. -*/ -public Number get(int i) { return get(Network.get(i)); } - -// -------------------------------------------------------------------------- - -/** -* Gets the given integer value. -* @param i The index of the node to get the value on in the network. -* The protocol is defined -* by {@link #pid}. -* @return the read value. -*/ -public long getLong(int i) { return getLong(Network.get(i)); } - -// -------------------------------------------------------------------------- - -/** -* Gets the given real value. -* @param i The index of the node to get the value on in the network. -* The protocol is defined -* by {@link #pid}. -* @return the read value. -*/ -public double getDouble(int i) { return getDouble(Network.get(i)); } - -} - diff --git a/contrib/psg/src/peersim/vector/GetterSetterFinder.java b/contrib/psg/src/peersim/vector/GetterSetterFinder.java deleted file mode 100644 index 48670be509..0000000000 --- a/contrib/psg/src/peersim/vector/GetterSetterFinder.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import java.lang.reflect.*; -import java.util.*; - -/** - * This utility class can be used to obtain get/set methods from classes. In - * particular, it is used in the vector package to locate get/set methods for - * observing and modifying protocol fields. - * Please refer to package {@link peersim.vector} for a definition of - * getter and setter methods. - */ -class GetterSetterFinder -{ - -//-------------------------------------------------------------------------- - -/** - * Search a getter method in the specified class. It succeeds only of there - * is exactly one method with the given name that is a getter method. - * Please refer to package {@link peersim.vector} for a definition of - * getter methods. - * - * @param clazz - * the class where to find get/set method - * @param methodName - * the method to be searched - * @return the requested method - */ -public static Method getGetterMethod(Class clazz, String methodName) - throws NoSuchMethodException -{ - // Search methods - Method[] methods = clazz.getMethods(); - ArrayList list = new ArrayList(); - for (Method m: methods) { - if (m.getName().equals(methodName)) { - list.add(m); - } - } - if (list.size() == 0) { - throw new NoSuchMethodException("No getter method for method " - + methodName + " in class " + clazz.getName()); - } else if (list.size() > 1) { - throw new NoSuchMethodException("Multiple getter for method " - + methodName + " in class " + clazz.getName()); - } - - // Found a single method with the right name; check if - // it is a gettter. - Method method = list.get(0); - Class[] pars = method.getParameterTypes(); - if (pars.length > 0) { - throw new NoSuchMethodException(method.getName() + " of class " - + clazz.getName() - + " is not a valid getter method: "+ - "its argument list is not empty"); - } - - Class ret = method.getReturnType(); - if ( !( ret==int.class || ret==long.class || - ret==double.class || ret==float.class || ret==boolean.class) - ) { - throw new NoSuchMethodException(method.getName() + " of class " - + clazz.getName() + " is not a valid getter method: "+ - "it should have a return type of int, long, short or double"); - } - - return method; -} - -//-------------------------------------------------------------------------- - -/** - * Search a setter method in the specified class. - * It succeeds only of there - * is exactly one method with the given name that is a setter method. - * Please refer to package {@link peersim.vector} for a definition of - * setter methods. - * @param clazz - * the class where to find get/set method - * @param methodName - * the method to be searched - * @return the requested method, if it fully conforms to the definition of - * the setter methods. - */ -public static Method getSetterMethod(Class clazz, String methodName) - throws NoSuchMethodException -{ - // Search methods - Method[] methods = clazz.getMethods(); - ArrayList list = new ArrayList(); - for (Method m: methods) { - if (m.getName().equals(methodName)) { - list.add(m); - } - } - - if (list.size() == 0) { - throw new NoSuchMethodException("No setter method for method " - + methodName + " in class " + clazz.getName()); - } else if (list.size() > 1) { - throw new NoSuchMethodException("Multiple setter for method " - + methodName + " in class " + clazz.getName()); - } - - // Found a single method with the right name; check if - // it is a setter. - Method method = list.get(0); - Class[] pars = method.getParameterTypes(); - if ( pars.length != 1 || - !( pars[0]==int.class || pars[0]==long.class || - pars[0]==double.class || pars[0]==float.class ) - ) { - throw new NoSuchMethodException(method.getName() + " of class " - + clazz.getName() - + " is not a valid setter method: "+ - "it should have exactly one argument of type "+ - "int, long, short or double"); - } - - Class ret = method.getReturnType(); - if (!ret.equals(void.class)) { - throw new NoSuchMethodException(method.getName() + " of class " - + clazz.getName() + - " is not a valid setter method; it returns a value"); - } - - return method; -} - -//-------------------------------------------------------------------------- - - -/** - * Returns the field type for the specified getter. - */ -public static Class getGetterType(Method m) -{ - return m.getReturnType(); -} - -//-------------------------------------------------------------------------- - -/** - * Returns the field type for the specified setter. - */ -public static Class getSetterType(Method m) -{ - Class[] pars = m.getParameterTypes(); - return pars[0]; -} - -//-------------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/vector/InitVectFromFile.java b/contrib/psg/src/peersim/vector/InitVectFromFile.java deleted file mode 100644 index 1bfaa17a3a..0000000000 --- a/contrib/psg/src/peersim/vector/InitVectFromFile.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import java.io.*; -import java.util.*; -import peersim.config.*; -import peersim.core.*; - -/** - * Initializes a protocol vector from data read from a file. - * The file format is as follows: - * lines starting with # or lines that contain only - * whitespace are ignored. - * From the rest of the lines the first field separated by whitespace is - * read. Only the first field is read from each line, the rest of the line - * is ignored. - * The file can contain more values than necessary but - * enough values must be present. - * @see VectControl - * @see peersim.vector - */ -public class InitVectFromFile extends VectControl -{ - -// -------------------------------------------------------------------------- -// Parameter names -// -------------------------------------------------------------------------- - -/** - * The filename to load links from. - * @config - */ -private static final String PAR_FILE = "file"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** The file to be read */ -private final String file; - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public InitVectFromFile(String prefix) -{ - super(prefix); - file = Configuration.getString(prefix + "." + PAR_FILE); -} - -// -------------------------------------------------------------------------- -// Methods -// -------------------------------------------------------------------------- - -/** - * Initializes values from a file. - * The file format is as follows: - * lines starting with # or lines that contain only - * whitespace are ignored. - * From the rest of the lines the first field separated by whitespace is - * read. Only the first field is read from each line, the rest of the line - * is ignored. - * The file can contain more values than necessary but - * enough values must be present. - * @throws RuntimeException if the file cannot be read or contains too few - * values - * @return always false - */ -public boolean execute() { - - int i = 0; - -try { - FileReader fr = new FileReader(file); - LineNumberReader lnr = new LineNumberReader(fr); - String line; - while ((line = lnr.readLine()) != null && i < Network.size()) { - if (line.startsWith("#")) - continue; - StringTokenizer st = new StringTokenizer(line); - if (!st.hasMoreTokens()) - continue; - if( setter.isInteger() ) - setter.set(i,Long.parseLong(st.nextToken())); - else setter.set(i,Double.parseDouble(st.nextToken())); - i++; - } - lnr.close(); -} -catch(IOException e) -{ - throw new RuntimeException("Unable to read file: " + e); -} - - if (i < Network.size()) - throw new RuntimeException( - "Too few values in file '" + file + "' (only " - + i + "); we need " + Network.size() + "."); - - return false; -} - -// -------------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/vector/LinearDistribution.java b/contrib/psg/src/peersim/vector/LinearDistribution.java deleted file mode 100644 index e7cc19eacb..0000000000 --- a/contrib/psg/src/peersim/vector/LinearDistribution.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.config.*; -import peersim.core.*; - -/** - * Initializes a protocol vector with values in the range [{@value #PAR_MIN}, - * {@value #PAR_MAX}] (inclusive both ends), linearly increasing. - * @see VectControl - * @see peersim.vector - */ -public class LinearDistribution extends VectControl -{ - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * Upper end of the interval.. - * @config - */ -private static final String PAR_MAX = "max"; - -/** - * Lower end of the interval. Defaults to -{@value #PAR_MAX}. - * @config - */ -private static final String PAR_MIN = "min"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** Minimum value */ -private final Number min; - -/** Maximum value */ -private final Number max; - -/** Step value */ -private final double step; - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public LinearDistribution(String prefix) -{ - super(prefix); - - // Read parameters based on type - if (setter.isInteger()) { - max=Long.valueOf(Configuration.getLong(prefix + "." + PAR_MAX)); - min=Long.valueOf(Configuration.getLong(prefix + "." + PAR_MIN, - -max.longValue())); - step= (max.longValue()-min.longValue())/ - ((double)(Network.size()-1)); - } else { // we know it's double or float - max = new Double(Configuration.getDouble(prefix+"."+PAR_MAX)); - min = new Double(Configuration.getDouble(prefix+"."+PAR_MIN, - -max.doubleValue())); - step= (max.doubleValue()-min.doubleValue())/(Network.size()-1); - } -} - -// -------------------------------------------------------------------------- -// Methods -// -------------------------------------------------------------------------- - -/** - * Initializes a protocol vector with values in the range [{@value #PAR_MIN}, - * {@value #PAR_MAX}] (inclusive both ends), linearly increasing. - * @return always false - */ -public boolean execute() { - - if ( setter.isInteger() ) - { - for(int i=0; i - * The method to be used is specified at construction time. - * For backward compatibility, if no method is specified, the method - * setValue is used. In this way, protocols - * implementing the {@link SingleValue} interface can be manipulated using the - * old configuration syntax (i.e., without specifying the method). - *

    - * Please refer to package {@link peersim.vector} for a detailed description of - * the concept of protocol vector and the role of getters and setters. - */ -public class Setter { - -// ============================ fields =================================== -// ======================================================================= - -private final String protocol; -private final String methodn; -private final String prefix; - -/** Identifier of the protocol that defines the vector */ -private int pid; - -/** Setter method name */ -private String methodName; - -/** Setter method */ -private Method method=null; - -/** Parameter type of setter method */ -private Class type; - - -// ========================== initialization ============================= -// ======================================================================= - - -/** - * Constructs a Setter class based on the configuration. - * Note that the - * actual initialization is delayed until the first access to the class, - * so that if a class is not used, no unnecessary error messages and exceptions - * are generated. - * @param prefix the configuration prefix to use when reading the configuration - * @param protocol the configuration parameter name that contains - * the protocol we want to manipulate using a setter method. - * The parameter prefix + "." + protocol is read. - * @param methodn the configuration parameter name that contains the setter - * method name. - * The parameter prefix + "." + methodn is read, with the default - * value setValue. - */ -public Setter(String prefix, String protocol, String methodn) { - - this.prefix=prefix; - this.protocol=protocol; - this.methodn=methodn; -} - -// -------------------------------------------------------------------------- - -private void init() { - - if( method!=null) return; - - // Read configuration parameter - pid = Configuration.getPid(prefix + "." + protocol); - methodName = Configuration.getString(prefix+"."+methodn,"setValue"); - // Search the method - Class clazz = Network.prototype.getProtocol(pid).getClass(); - try { - method = GetterSetterFinder.getSetterMethod(clazz, methodName); - } catch (NoSuchMethodException e) { - throw new IllegalParameterException(prefix + "." + - methodn, e+""); - } - // Obtain the type of the field - type = GetterSetterFinder.getSetterType(method); -} - - -// =============================== methods ============================= -// ===================================================================== - - -/** -* @return type of parameter of setter method -*/ -public Class getType() { - - init(); - return type; -} - -// -------------------------------------------------------------------------- - -/** -* @return true if the setter type is long or int -*/ -public boolean isInteger() { - - init(); - return type==long.class || type==int.class; -} - -// -------------------------------------------------------------------------- - -/** -* Sets the given integer value. -* @param n The node to set the value on. The protocol is defined -* by {@link #pid}. -* @param val the value to set. -*/ -public void set(Node n, long val) { - - init(); - - try - { - if(type==long.class) - { - method.invoke(n.getProtocol(pid),val); - return; - } - if(type==int.class) - { - method.invoke(n.getProtocol(pid),(int)val); - return; - } - } - catch (Exception e) - { - throw new RuntimeException("While using setter "+methodName,e); - - } - - throw new RuntimeException("type has to be int or long"); -} - -// -------------------------------------------------------------------------- - -/** -* Sets the given real value. -* @param n The node to set the value on. The protocol is defined -* by {@link #pid}. -* @param val the value to set. -*/ -public void set(Node n, double val) { - - init(); - - try - { - if(type==double.class) - { - method.invoke(n.getProtocol(pid),val); - return; - } - if(type==float.class) - { - method.invoke(n.getProtocol(pid),(float)val); - return; - } - } - catch (Exception e) - { - throw new RuntimeException("While using setter "+methodName,e); - } - - throw new RuntimeException("type has to be double or float"); -} - -// -------------------------------------------------------------------------- - -/** -* Sets the given integer value. -* @param i The index of the node to set the value on in the network. -* The protocol is defined -* by {@link #pid}. -* @param val the value to set. -*/ -public void set(int i, long val) { set(Network.get(i),val); } - -// -------------------------------------------------------------------------- - -/** -* Sets the given real value. -* @param i The index of the node to set the value on in the network. -* The protocol is defined -* by {@link #pid}. -* @param val the value to set. -*/ -public void set(int i, double val) { set(Network.get(i),val); } - -} - diff --git a/contrib/psg/src/peersim/vector/SingleValue.java b/contrib/psg/src/peersim/vector/SingleValue.java deleted file mode 100644 index 8d3dd9e8f5..0000000000 --- a/contrib/psg/src/peersim/vector/SingleValue.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -/** -* The implementor class has a single parameter. This interface -* provides access to that parameter. -*/ -public interface SingleValue { - -/** - * Returns the value of the parameter hold by the implementor - * of this interface. - */ -public double getValue(); - -/** - * Modifies the value of the parameter hold by the implementor - * of this interface. - */ -public void setValue(double value); - -} - diff --git a/contrib/psg/src/peersim/vector/SingleValueComparator.java b/contrib/psg/src/peersim/vector/SingleValueComparator.java deleted file mode 100644 index 0fa324eb36..0000000000 --- a/contrib/psg/src/peersim/vector/SingleValueComparator.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.core.*; -import java.util.*; - -/** - * This comparator class compares two node objects based on the value - * maintained by one of its protocols. The protocol must implement the - * {@link SingleValue} interface; its identifier has to be specified when a - * new comparator is built. - * - * @author Alberto Montresor - * @version $Revision: 1.4 $ - */ -public class SingleValueComparator implements Comparator -{ - -/** Protocol to be be compared */ -private int pid; - -/** - * Builds a new comparator that compares the double values maintained - * by protocol identified by pid. - */ -public SingleValueComparator(int pid) { this.pid = pid; } - -/** - * Compares the values of two protocols. The parameters must have dynamic type - * {@link Node}. The protocol {@link #pid} is accessed on both nodes. These - * protocols have to implement the {@link SingleValue} interface. The values - * held by these protocol instances are then compared. - */ -public int compare(Object o1, Object o2) -{ - SingleValue s1 = (SingleValue) ((Node) o1).getProtocol(pid); - SingleValue s2 = (SingleValue) ((Node) o2).getProtocol(pid); - return (int) (s1.getValue() - s2.getValue()); -} - -} diff --git a/contrib/psg/src/peersim/vector/SingleValueHolder.java b/contrib/psg/src/peersim/vector/SingleValueHolder.java deleted file mode 100644 index 450086d732..0000000000 --- a/contrib/psg/src/peersim/vector/SingleValueHolder.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.core.*; - -/** - * The task of this protocol is to store a single double value and make it - * available through the {@link SingleValue} interface. - * - * @author Alberto Montresor - * @version $Revision: 1.6 $ - */ -public class SingleValueHolder -implements SingleValue, Protocol -{ - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -/** Value held by this protocol */ -protected double value; - - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Does nothing. - */ -public SingleValueHolder(String prefix) -{ -} - -//-------------------------------------------------------------------------- - -/** - * Clones the value holder. - */ -public Object clone() -{ - SingleValueHolder svh=null; - try { svh=(SingleValueHolder)super.clone(); } - catch( CloneNotSupportedException e ) {} // never happens - return svh; -} - -//-------------------------------------------------------------------------- -//methods -//-------------------------------------------------------------------------- - -/** - * @inheritDoc - */ -public double getValue() -{ - return value; -} - -//-------------------------------------------------------------------------- - -/** - * @inheritDoc - */ -public void setValue(double value) -{ - this.value = value; -} - -//-------------------------------------------------------------------------- - -/** - * Returns the value as a string. - */ -public String toString() { return ""+value; } - -} diff --git a/contrib/psg/src/peersim/vector/SingleValueObserver.java b/contrib/psg/src/peersim/vector/SingleValueObserver.java deleted file mode 100644 index 262d2e06e1..0000000000 --- a/contrib/psg/src/peersim/vector/SingleValueObserver.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.config.*; -import peersim.core.*; -import peersim.util.*; - -/** -* Print statistics over a vector. The vector is defined by a protocol, -* specified by {@value #PAR_PROT}, that has to implement -* {@link SingleValue}. -* Statistics printed are: min, max, number of samples, average, variance, -* number of minimal instances, number of maximal instances (using -* {@link IncrementalStats#toString}). -* @see IncrementalStats -*/ -public class SingleValueObserver implements Control { - - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * The parameter used to determine the accuracy - * (standard deviation) before stopping the simulation. If not - * defined, a negative value is used which makes sure the observer - * does not stop the simulation. - * @see #execute - * @config - */ -private static final String PAR_ACCURACY = "accuracy"; - -/** - * The protocol to operate on. - * @config - */ -private static final String PAR_PROT = "protocol"; - - -//-------------------------------------------------------------------------- -// Fields -//-------------------------------------------------------------------------- - -/** The name of this observer in the configuration */ -private final String name; - -/** Accuracy for standard deviation used to stop the simulation */ -private final double accuracy; - -/** Protocol identifier */ -private final int pid; - - -//-------------------------------------------------------------------------- -// Constructor -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param name the configuration prefix for this class - */ -public SingleValueObserver(String name) -{ - this.name = name; - accuracy = Configuration.getDouble(name + "." + PAR_ACCURACY, -1); - pid = Configuration.getPid(name + "." + PAR_PROT); -} - - -//-------------------------------------------------------------------------- -// Methods -//-------------------------------------------------------------------------- - -/** -* Print statistics over a vector. The vector is defined by a protocol, -* specified by {@value #PAR_PROT}, that has to implement -* {@link SingleValue}. -* Statistics printed are: min, max, number of samples, average, variance, -* number of minimal instances, number of maximal instances (using -* {@link IncrementalStats#toString}). -* @return true if the standard deviation is below the value of - * {@value #PAR_ACCURACY}, and the time of the simulation is larger then zero - * (i.e. it has started). - */ -public boolean execute() -{ - IncrementalStats stats = new IncrementalStats(); - - /* Compute max, min, average */ - for (int i = 0; i < Network.size(); i++) - { - SingleValue v = (SingleValue)Network.get(i).getProtocol(pid); - stats.add( v.getValue() ); - } - - /* Printing statistics */ - System.out.println(name+": "+stats); - - /* Terminate if accuracy target is reached */ - return (stats.getStD()<=accuracy && CommonState.getTime()>0); -} - -//-------------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/vector/TestVectors.java b/contrib/psg/src/peersim/vector/TestVectors.java deleted file mode 100644 index f6920cbe0a..0000000000 --- a/contrib/psg/src/peersim/vector/TestVectors.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - - -/** - * Do testing the vector package. - */ -public class TestVectors extends SingleValueHolder -{ - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -/** Value held by this protocol */ -protected float fvalue; - -/** Value held by this protocol */ -protected int ivalue; - -/** Value held by this protocol */ -protected long lvalue; - - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Builds a new (not initialized) value holder. - * Calls super constructor. - */ -public TestVectors(String prefix) { super(prefix); } - -//-------------------------------------------------------------------------- -//methods -//-------------------------------------------------------------------------- - -/** - * - */ -public int getIValue() { return ivalue; } - -//-------------------------------------------------------------------------- - -/** - * - */ -public void setIValue(int value) { ivalue = value; } - -//-------------------------------------------------------------------------- - -/** - * - */ -public float getFValue() { return fvalue; } - -//-------------------------------------------------------------------------- - -/** - * - */ -public void setFValue(float value) { fvalue = value; } - -//-------------------------------------------------------------------------- - -/** - * - */ -public long getLValue() { return lvalue; } - -//-------------------------------------------------------------------------- - -/** - * - */ -public void setLValue(long value) { lvalue = value; } - -//-------------------------------------------------------------------------- - -/** - * Returns the value as a string. - */ -public String toString() { return value+" "+fvalue+" "+ivalue+" "+lvalue; } - -} - diff --git a/contrib/psg/src/peersim/vector/UniformDistribution.java b/contrib/psg/src/peersim/vector/UniformDistribution.java deleted file mode 100644 index bd30fb1957..0000000000 --- a/contrib/psg/src/peersim/vector/UniformDistribution.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.config.*; -import peersim.core.*; -import peersim.dynamics.*; - -/** - * Initializes the values drawing uniform random samples from the range - * [{@value #PAR_MIN}, {@value #PAR_MAX}[. - * @see VectControl - * @see peersim.vector - */ -public class UniformDistribution extends VectControl implements NodeInitializer -{ - -//-------------------------------------------------------------------------- -//Parameter names -//-------------------------------------------------------------------------- - -/** - * The upper bound of the uniform random variable, exclusive. - * @config - */ -private static final String PAR_MAX = "max"; - -/** - * The lower bound of the uniform - * random variable, inclusive. Defaults to -{@value #PAR_MAX}. - * @config - */ -private static final String PAR_MIN = "min"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** Minimum value */ -private final Number min; - -/** Maximum value */ -private final Number max; - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public UniformDistribution(String prefix) -{ - super(prefix); - - // Read parameters based on type - if (setter.isInteger()) { - max=Long.valueOf(Configuration.getLong(prefix + "." + PAR_MAX)); - min=Long.valueOf(Configuration.getLong(prefix + "." + PAR_MIN, - -max.longValue())); - } else { // we know it's double or float - max = new Double(Configuration.getDouble(prefix+"."+PAR_MAX)); - min = new Double(Configuration.getDouble(prefix+"."+PAR_MIN, - -max.doubleValue())); - } -} - -// -------------------------------------------------------------------------- -// Methods -// -------------------------------------------------------------------------- - -/** - * Initializes the values drawing uniform random samples from the range - * [{@value #PAR_MIN}, {@value #PAR_MAX}[. - * @return always false - */ -public boolean execute() { - - if(setter.isInteger()) - { - long d = max.longValue() - min.longValue(); - for (int i = 0; i < Network.size(); ++i) - { - setter.set(i,CommonState.r.nextLong(d)+min.longValue()); - } - } - else - { - double d = max.doubleValue() - min.doubleValue(); - for (int i = 0; i < Network.size(); ++i) - { - setter.set(i,CommonState.r.nextDouble()*d+ - min.doubleValue()); - } - } - - return false; -} - -// -------------------------------------------------------------------------- - -/** - * Initializes the value drawing a uniform random sample from the range - * [{@value #PAR_MIN}, {@value #PAR_MAX}[. - * @param n the node to initialize - */ -public void initialize(Node n) { - - if( setter.isInteger() ) - { - long d = max.longValue() - min.longValue(); - setter.set(n,CommonState.r.nextLong(d) + min.longValue()); - } - else - { - double d = max.doubleValue() - min.doubleValue(); - setter.set(n,CommonState.r.nextDouble()*d); - } -} - -// -------------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/vector/ValueDumper.java b/contrib/psg/src/peersim/vector/ValueDumper.java deleted file mode 100644 index ce6746e4ab..0000000000 --- a/contrib/psg/src/peersim/vector/ValueDumper.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import java.io.*; - -import peersim.config.*; -import peersim.core.*; -import peersim.util.*; - -/** - * Dump the content of a vector in a file. Each line - * represent a single node. - * Values are dumped to a file whose name is obtained from a - * configurable prefix (set by {@value #PAR_BASENAME}), a number that is - * increased before each dump by one, and the extension ".vec". - *

    - * This observer class can observe any protocol field containing a - * primitive value, provided that the field is associated with a getter method - * that reads it. - * @see VectControl - * @see peersim.vector - */ -public class ValueDumper extends VectControl { - - -// -------------------------------------------------------------------------- -// Parameter names -// -------------------------------------------------------------------------- - -/** - * This is the base name of the file where the values are saved. The full name - * will be baseName+cycleid+".vec". - * @config - */ -private static final String PAR_BASENAME = "outf"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** Prefix name of this observer */ -private final String prefix; - -/** Base name of the file to be written */ -private final String baseName; - -private final FileNameGenerator fng; - -// -------------------------------------------------------------------------- -// Constructor -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public ValueDumper(String prefix) { - - super(prefix); - this.prefix = prefix; - baseName = Configuration.getString(prefix + "." + PAR_BASENAME, null); - if(baseName!=null) fng = new FileNameGenerator(baseName,".vec"); - else fng = null; -} - -// -------------------------------------------------------------------------- -// Methods -// -------------------------------------------------------------------------- - -/** - * Dump the content of a vector in a file. Each line - * represent a single node. - * Values are dumped to a file whose name is obtained from a - * configurable prefix (set by {@value #PAR_BASENAME}), a number that is - * increased before each dump by one, and the extension ".vec". - * @return always false - * @throws RuntimeException if there is an I/O problem - */ -public boolean execute() { -try -{ - System.out.print(prefix + ": "); - - // initialize output streams - if (baseName != null) - { - String filename = fng.nextCounterName(); - System.out.println("writing "+filename); - PrintStream pstr = - new PrintStream(new FileOutputStream(filename)); - for (int i = 0; i < Network.size(); ++i) - { - pstr.println(getter.get(i)); - } - pstr.close(); - } - else - { - System.out.println(); - for (int i = 0; i < Network.size(); ++i) - { - System.out.println(getter.get(i)); - } - } -} -catch (IOException e) -{ - throw new RuntimeException(prefix + ": Unable to write to file: " + e); -} - - return false; -} - -// --------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/vector/VectAngle.java b/contrib/psg/src/peersim/vector/VectAngle.java deleted file mode 100644 index 629a06e42d..0000000000 --- a/contrib/psg/src/peersim/vector/VectAngle.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.core.*; - -/** - * Observes the cosine angle between two vectors. The number which is output is - * the inner product divided by the product of the length of the vectors. - * All values are converted to double before processing. - *

    - * This observer class can observe any protocol field containing a - * primitive value, provided that the field is associated with a getter method - * that reads it. - * The methods to be used are specified through parameter {@value #PAR_METHOD1} - * and {@value #PAR_METHOD2}. - *

    - * Please refer to package {@link peersim.vector} for a detailed description of - * this mechanism. - */ -public class VectAngle implements Control -{ - -// -------------------------------------------------------------------------- -// Parameters -// -------------------------------------------------------------------------- - -/** - * The first protocol to be observed. - * @config - */ -private static final String PAR_PROT1 = "protocol1"; - -/** - * The second protocol to be observed. - * @config - */ -private static final String PAR_PROT2 = "protocol2"; - -/** - * The getter method used to obtain the values of the first protocol. - * Defaults to getValue (for backward compatibility with previous - * implementation of this class, that were based on the - * {@link SingleValue} interface). - * Refer to the {@linkplain peersim.vector vector package description} for more - * information about getters and setters. - * @config - */ -private static final String PAR_METHOD1 = "getter1"; - -/** - * The getter method used to obtain the values of the second protocol. - * Defaults to getValue (for backward compatibility with previous - * implementation of this class, that were based on the - * {@link SingleValue} interface). - * Refer to the {@linkplain peersim.vector vector package description} for more - * information about getters and setters. - * @config - */ -private static final String PAR_METHOD2 = "getter2"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** The prefix for this observer*/ -private final String name; - -private final Getter getter1; - -private final Getter getter2; - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public VectAngle(String prefix) -{ - name = prefix; - getter1 = new Getter(prefix,PAR_PROT1,PAR_METHOD1); - getter2 = new Getter(prefix,PAR_PROT2,PAR_METHOD2); -} - -// -------------------------------------------------------------------------- -// Methods -// -------------------------------------------------------------------------- - -/** - * Observes the cosine angle between two vectors. The printed values - * are: cosine, Eucledian norm of vect 1, Eucledian norm of vector 2, - * angle in radians. -* @return always false -*/ -public boolean execute() { - - double sqrsum1 = 0, sqrsum2 = 0, prod = 0; - for (int i = 0; i < Network.size(); ++i) - { - double v1= getter1.get(i).doubleValue(); - double v2= getter2.get(i).doubleValue(); - sqrsum1 += v1 * v1; - sqrsum2 += v2 * v2; - prod += v2 * v1; - } - - double cos = prod / Math.sqrt(sqrsum1) / Math.sqrt(sqrsum2); - - // deal with numeric errors - if( cos > 1 ) cos=1; - if( cos < -1 ) cos = -1; - - System.out.println(name+": " + cos + " " - + Math.sqrt(sqrsum1) + " " + Math.sqrt(sqrsum2) + " " - + Math.acos(cos)); - return false; -} - -//-------------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/vector/VectControl.java b/contrib/psg/src/peersim/vector/VectControl.java deleted file mode 100644 index 174b9624db..0000000000 --- a/contrib/psg/src/peersim/vector/VectControl.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.core.*; - -/** - * Serves as an abstract superclass for {@link Control}s that deal - * with vectors. - * It reads a {@link Setter} to be used by extending classes. - */ -public abstract class VectControl implements Control { - - -// -------------------------------------------------------------------------- -// Parameter names -// -------------------------------------------------------------------------- - -/** - * The protocol to operate on. - * @config - */ -protected static final String PAR_PROT = "protocol"; - -/** - * The setter method used to set values in the protocol instances. Defaults to - * setValue - * (for backward compatibility with previous implementation of this - * class, that were based on the {@link SingleValue} interface). Refer to the - * {@linkplain peersim.vector vector package description} for more - * information about getters and setters. - * @config - */ -protected static final String PAR_METHOD = "setter"; - -/** - * The getter method used to obtain the protocol values. - * Defaults to getValue - * (for backward compatibility with previous - * implementation of this class, that were based on the - * {@link SingleValue} interface). - * Refer to the {@linkplain peersim.vector vector package description} for more - * information about getters and setters. - * @config - */ -protected static final String PAR_GETTER = "getter"; - -// -------------------------------------------------------------------------- -// Fields -// -------------------------------------------------------------------------- - -/** The setter to be used to write a vector. */ -protected final Setter setter; - -/** The getter to be used to read a vector. */ -protected final Getter getter; - -// -------------------------------------------------------------------------- -// Initialization -// -------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -protected VectControl(String prefix) -{ - setter = new Setter(prefix,PAR_PROT,PAR_METHOD); - getter = new Getter(prefix,PAR_PROT,PAR_GETTER); -} - -} - diff --git a/contrib/psg/src/peersim/vector/VectCopy.java b/contrib/psg/src/peersim/vector/VectCopy.java deleted file mode 100644 index 6d13091d83..0000000000 --- a/contrib/psg/src/peersim/vector/VectCopy.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.core.*; -import peersim.dynamics.*; - -/** - * Sets values in a protocol vector by copying the values of another - * protocol vector. - * The source is defined by {@value #PAR_SOURCE}, - * and getter method {@value peersim.vector.VectControl#PAR_GETTER}. - *

    - * This dynamics class can copy any primitive field in the source - * protocol to any primitive field in the destination protocol, - * provided that the former field is associated with a getter method, - * while the latter is associated with a setter method. - * @see VectControl - * @see peersim.vector - */ -public class VectCopy extends VectControl implements NodeInitializer { - - -//-------------------------------------------------------------------------- -//Parameters -//-------------------------------------------------------------------------- - -/** - * The identifier of the protocol to be copied. - * The vector values are copied from this vector. - * @config - */ -private static final String PAR_SOURCE = "source"; - - -// -------------------------------------------------------------------------- -// Variables -// -------------------------------------------------------------------------- - -/** Source getter */ -private final Getter source; - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public VectCopy(String prefix) -{ - super(prefix); - source = new Getter(prefix,PAR_SOURCE,PAR_GETTER); -} - -//-------------------------------------------------------------------------- -//Method -//-------------------------------------------------------------------------- - -/** - * Sets values in a protocol vector by copying the values of another - * protocol vector. The source is defined by {@value #PAR_SOURCE}, - * and getter method {@value peersim.vector.VectControl#PAR_GETTER}. - * @return always false - */ -public boolean execute() { - - int size = Network.size(); - for (int i = 0; i < size; i++) { - Number ret = source.get(i); - if(setter.isInteger()) setter.set(i,ret.longValue()); - else setter.set(i,ret.doubleValue()); - } - - return false; -} - -//-------------------------------------------------------------------------- - -/** - * Sets the value by copying the value of another - * protocol. The source is defined by {@value #PAR_SOURCE}, - * and getter method {@value peersim.vector.VectControl#PAR_GETTER}. - * @param n the node to initialize - */ -public void initialize(Node n) { - - Number ret = source.get(n); - if(setter.isInteger()) setter.set(n,ret.longValue()); - else setter.set(n,ret.doubleValue()); -} - -//-------------------------------------------------------------------------- - -} diff --git a/contrib/psg/src/peersim/vector/VectorComparator.java b/contrib/psg/src/peersim/vector/VectorComparator.java deleted file mode 100644 index 97f269e9c7..0000000000 --- a/contrib/psg/src/peersim/vector/VectorComparator.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2006 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import java.lang.reflect.*; -import java.util.*; - -import peersim.core.*; - -/** - * This class provides a generic implementation of the - * java.lang.Comparator interface specialized - * for {@link Node} objects. Nodes are compared based - * on one of their protocols, on which a configurable - * method is invoked. Both the protocol id and the - * method are specified in the constructor. - *
    - * This comparator can be used, for example, to sort - * an array of nodes based on method getValue - * associated to the protocol pid: - *

    - * Comparator c = new VectorComparator(pid, "getValue");
    - * Array.sort(Node[] array, c);
    - * 
    - * Note that differently from other classes in this package, - * VectorComparator is declared programmatically in the code - * and not in the configuration file. It is included in this - * package because it shares the same philosophy of the other - * classes. - * - * @author Alberto Montresor - * @version $Revision: 1.1 $ - */ -public class VectorComparator implements Comparator -{ - -//-------------------------------------------------------------------------- -//Fields -//-------------------------------------------------------------------------- - -/** Protocol identifier of the protocol to be observed */ -private final int pid; - -/** The getter to be used to obtain comparable values */ -private final Method method; - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -public VectorComparator(int pid, String methodName) -{ - this.pid = pid; - Node n = Network.prototype; - if (n == null) { - throw new IllegalStateException("No prototype node can be used to search methods"); - } - Object p = n.getProtocol(pid); - Class c = p.getClass(); - try { - method = GetterSetterFinder.getGetterMethod(c, methodName); - } catch (NoSuchMethodException e) { - throw new IllegalArgumentException(e.getMessage()); - } -} - - -public int compare(Object o1, Object o2) -{ - try { - Comparable c1 = (Comparable) method.invoke(((Node) o1).getProtocol(pid)); - Comparable c2 = (Comparable) method.invoke(((Node) o2).getProtocol(pid)); - return c1.compareTo(c2); - } catch (InvocationTargetException e) { - throw new RuntimeException(e.getCause().getMessage()); - } catch (IllegalAccessException e) { - throw new RuntimeException(e.getCause().getMessage()); - } -} - -} diff --git a/contrib/psg/src/peersim/vector/VectorObserver.java b/contrib/psg/src/peersim/vector/VectorObserver.java deleted file mode 100644 index b971fc2c89..0000000000 --- a/contrib/psg/src/peersim/vector/VectorObserver.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2003-2005 The BISON Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -package peersim.vector; - -import peersim.core.*; -import peersim.util.*; - -/** - * This class computes and reports statistics information about a vector. - * Provided statistics include average, max, min, variance, - * etc. Values are printed according to the string format of {@link - * IncrementalStats#toString}. - * @see VectControl - * @see peersim.vector - */ -public class VectorObserver extends VectControl { - - -/** The name of this observer in the configuration */ -private final String prefix; - - -//-------------------------------------------------------------------------- -//Initialization -//-------------------------------------------------------------------------- - -/** - * Standard constructor that reads the configuration parameters. - * Invoked by the simulation engine. - * @param prefix the configuration prefix for this class - */ -public VectorObserver(String prefix) { - - super(prefix); - this.prefix = prefix; -} - -//-------------------------------------------------------------------------- -// Methods -//-------------------------------------------------------------------------- - -/** - * Prints statistics information about a vector. - * Provided statistics include average, max, min, variance, - * etc. Values are printed according to the string format of {@link - * IncrementalStats#toString}. - * @return always false - */ -public boolean execute() { - - IncrementalStats stats = new IncrementalStats(); - - for (int j = 0; j < Network.size(); j++) - { - Number v = getter.get(j); - stats.add( v.doubleValue() ); - } - - System.out.println(prefix+": "+stats); - - return false; -} - -} diff --git a/contrib/psg/src/psgsim/NodeHost.java b/contrib/psg/src/psgsim/NodeHost.java deleted file mode 100644 index 1dce76fd42..0000000000 --- a/contrib/psg/src/psgsim/NodeHost.java +++ /dev/null @@ -1,74 +0,0 @@ -package psgsim; - -import org.simgrid.msg.Host; -import peersim.core.Network; -import peersim.core.Node; - -import java.util.Comparator; -import java.util.Map; -import java.util.TreeMap; - -/** - * - * NodeHost class used to make the mapping Node-Host. - * - * @author Khaled Baati 26/10/2014 - * @version version 1.1 - */ -public class NodeHost { - - /** - * A collection of map contained the couple (host,node) - */ - public static TreeMap mapHostNode = new TreeMap( - new Comparator() { - public int compare(Node n1, Node n2) { - return String.valueOf(n1.getID()).compareTo( - String.valueOf(n2.getID())); - } - }); - - /** - * The main method to make the mapping Node to Host in the - * {@link #mapHostNode} field - */ - public static void start() { - Host host = null; - for (Integer i = 0; i < PSGSimulator.size; i++) { - host = PSGPlatform.hostList[i]; - mapHostNode.put(Network.get(i), host); - } - } - - /** - * This static method gets a Node instance associated with a host of your - * platform. - * - * @param host - * The host associated in your platform. - * @return The node associated. - */ - public static Node getNode(Host host) { - for (Map.Entry element : mapHostNode.entrySet()) { - if (element.getValue() == host) - return element.getKey(); - } - return null; - } - - /** - * This static method gets a host instance associated with the node of your - * platform. - * - * @param node - * The node associated in your platform. - * @return The host associated, else return null (host doesn't exist). - */ - public static Host getHost(Node node) { - for (Map.Entry element : mapHostNode.entrySet()) { - if (element.getKey() == node) - return element.getValue(); - } - return null; - } -} diff --git a/contrib/psg/src/psgsim/PSGDynamicNetwork.java b/contrib/psg/src/psgsim/PSGDynamicNetwork.java deleted file mode 100644 index f4bb3b12c6..0000000000 --- a/contrib/psg/src/psgsim/PSGDynamicNetwork.java +++ /dev/null @@ -1,45 +0,0 @@ -package psgsim; - -import org.simgrid.msg.Host; -import org.simgrid.msg.HostNotFoundException; - -import peersim.core.Node; - -/** - * - * This class can change the size of networks by adding and removing nodes, as - * {@link peersim.dynamics.DynamicNetwork} in peersim. - * - * @author Khaled Baati 09/02/2015 - * @version version 1.1 - */ -public class PSGDynamicNetwork { - - /** - * Removes the node from the network. - * - * @param node - * the node to be removed - */ - public static void remove(Node node) { - // NodeHost.getHost(node).off(); - // Host h=NodeHost.mapHostNode.get(node); - // NodeHost.mapHostNode.remove(node); - PSGSimulator.size = PSGSimulator.size - 1; - } - - /** - * Adds a node to the network. - * - * @param node - * the node to be added - * @throws HostNotFoundException - */ - public static void add(Node node) throws HostNotFoundException { - Host host = PSGPlatform.hostList[(int) node.getID()]; - NodeHost.mapHostNode.put(node, host); - if (PSGPlatform.interfED) - new PSGProcessEvent(host, host.getName(), null).start(); - PSGSimulator.size = PSGSimulator.size + 1; - } -} diff --git a/contrib/psg/src/psgsim/PSGPlatform.java b/contrib/psg/src/psgsim/PSGPlatform.java deleted file mode 100644 index 90c7c8765d..0000000000 --- a/contrib/psg/src/psgsim/PSGPlatform.java +++ /dev/null @@ -1,329 +0,0 @@ -package psgsim; - -import java.io.*; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.TreeMap; - -import org.jdom2.*; -import org.jdom2.output.*; -import org.simgrid.msg.Host; -import org.simgrid.msg.Msg; - -import peersim.config.Configuration; -import peersim.core.Control; -import peersim.core.Protocol; - -/** - * A class store different configuration information for simulation. It creates - * the deployment file according to this informations. - * - * @author Khaled Baati 26/10/2014 - * @version version 1.1 - */ - -public class PSGPlatform { - - enum timeUnit { - us, ms, sec; - } - - /** unit of measure. **/ - static int unit; - - /** the clock. **/ - static double time; - - /** the default unit of measure **/ - static final String sec = "sec"; - - /** All protocols defined in the configuration file. **/ - static Protocol[] protocolsName; - - /** A numeric identifier associated for each protocol. **/ - static int[] pid; - - /** List of hos.t **/ - static Host[] hostList; - - /** A collection map represents the Control and its associated step. **/ - static Map controlStepMap = new LinkedHashMap(); - - /** A collection map represents the protocol and its associated pid. **/ - static TreeMap protocolsPidsMap = new TreeMap( - new Comparator() { - public int compare(Protocol p1, Protocol p2) { - return p1.toString().compareTo(p2.toString()); - } - }); - - /** A collection map represents all CDProtocol and its associated step **/ - static TreeMap cdProtocolsStepMap = new TreeMap( - new Comparator() { - public int compare(Protocol p1, Protocol p2) { - return p1.toString().compareTo(p2.toString()); - } - }); - /** the default platform file **/ - static final String platformFile = "platforms/psg.xml"; - - /** the deployment file **/ - static final String deploymentFile = "deployment.xml"; - - static Element racine; - static Document document; - static boolean interfED = false; - static boolean interfCD = false; - - /** Prepare the deployment file **/ - static { - DocType dtype = new DocType("platform", - "http://simgrid.gforge.inria.fr/simgrid.dtd"); - racine = new Element("platform"); - document = new Document(racine, dtype); - Attribute version = new Attribute("version", "3"); - racine.setAttribute(version); - } - - // ========================== methods ================================== - // ===================================================================== - - /** - * Convert PS unit time to Simgrid unit time - * - * @param valeur - * the value to convert - * @return time converted - */ - public static double psToSgTime(long valeur) { - timeUnit unit = unit(); - switch (unit) { - case us: - return ((double) valeur) / 1000000; - case ms: - return ((double) valeur) / 1000; - default: - return (double) valeur; - - } - } - - /** - * Convert Simgrid unit time to PS unit time - * - * @param valeur - * the value to convert - * @return time converted - */ - public static long sgToPsTime(double valeur) { - timeUnit unit = unit(); - switch (unit) { - case us: - return (long) valeur * 1000000; - case ms: - return (long) valeur * 1000; - default: - return (long) valeur; - - } - } - - /** - * - * @return the duration of simulation. - */ - public static long getDuration() { - return Configuration.getLong("simulation.duration"); - } - - /** - * - * @return PeerSim Time - */ - public static long getTime() { - return sgToPsTime(Msg.getClock()); - } - - /** - * - * @return the Simgrid Clock - */ - public static double getClock() { - return Msg.getClock(); - } - - /** - * Load and run initializers. - */ - public static void init() { - Object[] inits = Configuration.getInstanceArray("init"); - String names[] = Configuration.getNames("init"); - for (int i = 0; i < inits.length; ++i) { - System.err.println("- Running initializer " + names[i] + ": " - + inits[i].getClass().toString()); - ((Control) inits[i]).execute(); - } - } - - /** - * Load all controls and stores them in {@link #controlStepMap} collection - * to be scheduled, and executed in {@link psgsim.PSGProcessController}. - */ - public static void control() { - // load controls - String[] names = Configuration.getNames("control"); - Control control; - for (int i = 0; i < names.length; ++i) { - control = (Control) Configuration.getInstance(names[i]); - Long stepControl = Configuration.getLong(names[i] + "." + "step"); - controlStepMap.put(control, psToSgTime(stepControl)); - } - } - - /** - * Lookup all protocols in the configuration file - */ - public static void protocols() { - String[] names = Configuration.getNames("protocol"); - Class[] interfaces; - protocolsName = new Protocol[names.length]; - pid = new int[names.length]; - boolean save = false; - for (int i = 0; i < names.length; i++) { - protocolsName[i] = (Protocol) Configuration.getInstance(names[i]); - if (i == names.length - 1) - save = true; - userProtocol(protocolsName[i], names[i], save); - pid[i] = i; - protocolsPidsMap.put(protocolsName[i], pid[i]); - } - - } - - /** - * Lookup CDProtocol and EDProtocol among all protocols - * - * @param prot - * the protocol class - * @param names - * the protocol name - * @param save - * parameter equal true when parsing all protocols - */ - public static void userProtocol(Protocol prot, String names, boolean save) { - Class[] interfaces = prot.getClass().getInterfaces(); - for (int j = 0; j < interfaces.length; j++) { - if (interfaces[j].getName().endsWith("EDProtocol")) { - interfED = true; - } - if (interfaces[j].getName().endsWith("CDProtocol")) { - String protName = names.substring("protocol".length() + 1); - long step = Configuration.getLong("protocol" + "." + protName - + "." + "step"); - cdProtocolsStepMap.put(prot, psToSgTime(step)); - } - } - if (save) { - edProt(); - } - } - - /** - * - */ - private static void edProt() { - Host hostVal; - hostList = Host.all(); - for (int i = 0; i < PSGSimulator.size; i++) { - hostVal = hostList[i]; - Element process = new Element("process"); - racine.addContent(process); - Attribute host = new Attribute("host", hostVal.getName()); - Attribute function = new Attribute("function", - "psgsim.PSGProcessEvent"); - process.setAttribute(host); - process.setAttribute(function); - } - save(deploymentFile); - - } - - /** - * - */ - @Deprecated - private static void cdProt() { - for (int i = 0; i < PSGSimulator.size; i++) { - Element process = new Element("process"); - racine.addContent(process); - Attribute host = new Attribute("host", String.valueOf(i)); - Attribute function = new Attribute("function", - "psgsim.PSGProcessCycle"); - process.setAttribute(host); - process.setAttribute(function); - - } - save("deployment.xml"); - - } - - /** - * Reads given configuration property: "platform". If not found, returns the - * default value. - * - * @return the platform file - */ - public static String platformFile() { - String defFile = platformFile; - String file = Configuration.getString("platform", defFile); - return file; - } - - /** - * Reads given configuration property: "unit". If not found, returns the - * default value (ms). - * - * @return the unit of measure - */ - public static timeUnit unit() { - String defUnit = sec; - String unit = Configuration.getString("unit", defUnit); - timeUnit t = timeUnit.valueOf(unit); - return t; - } - - /** - * Create the deployment file - * - * @param file - * the name of the deployment file - */ - public static void save(String file) { - try { - // On utilise ici un affichage classique avec getPrettyFormat() - XMLOutputter out = new XMLOutputter(Format.getPrettyFormat()); - out.output(document, new FileOutputStream(file)); - } catch (java.io.IOException e) { - } - } - - /** - * Delete the deployment file - * - * @param path - * the path of the deployment file - */ - public static void delete(String path) { - File file = new File(path); - try { - file.delete(); - } catch (Exception e) { - System.err.println("deployment file not found"); - - } - System.err.println(path + "file deleted"); - - } - -} diff --git a/contrib/psg/src/psgsim/PSGProcessController.java b/contrib/psg/src/psgsim/PSGProcessController.java deleted file mode 100644 index d587691c80..0000000000 --- a/contrib/psg/src/psgsim/PSGProcessController.java +++ /dev/null @@ -1,68 +0,0 @@ -package psgsim; - -import java.util.LinkedHashMap; -import java.util.Map; -import org.simgrid.msg.Host; -import org.simgrid.msg.MsgException; - -import peersim.core.Control; - -/** - * This class executes all controls object scheduled in the - * {@link PSGPlatform#controlStepMap} collection. - * - * @author Khaled Baati 10/12/2014 - * @version version 1.1 - */ -public class PSGProcessController extends org.simgrid.msg.Process { - - private Map controlStepMapTmp = new LinkedHashMap(); - - public PSGProcessController(Host host, String name, String[] args) { - super(host, name, null); - } - - @Override - public void main(String[] args) throws MsgException { - Double nextControlEvent; - for (Map.Entry entry : PSGPlatform.controlStepMap - .entrySet()) { - controlStepMapTmp.put(entry.getKey(), entry.getValue()); - } - while (PSGPlatform.getTime() <= PSGPlatform.getDuration()) { - for (Map.Entry entrytmp : controlStepMapTmp - .entrySet()) { - Control cle = entrytmp.getKey(); - Double valeur = entrytmp.getValue(); - if (PSGPlatform.getTime() % valeur == 0) { - cle.execute(); - if (PSGPlatform.getTime() != 0) - for (Map.Entry entry : PSGPlatform.controlStepMap - .entrySet()) { - if (cle == entry.getKey()) - controlStepMapTmp.replace(cle, valeur, valeur - + entry.getValue()); - - } - } - } - nextControlEvent = next(); - if (nextControlEvent + PSGPlatform.getTime() >= PSGPlatform.getDuration()) { - break; - } else { - waitFor(nextControlEvent); - } - } - } - - private Double next() { - Double min = controlStepMapTmp.values().iterator().next(); - for (Map.Entry entry : controlStepMapTmp.entrySet()) { - Double valeur = (entry.getValue() - PSGPlatform.getClock()); - if (min > valeur) - min = valeur; - } - - return min; - } -} \ No newline at end of file diff --git a/contrib/psg/src/psgsim/PSGProcessCycle.java b/contrib/psg/src/psgsim/PSGProcessCycle.java deleted file mode 100644 index e0931b1f55..0000000000 --- a/contrib/psg/src/psgsim/PSGProcessCycle.java +++ /dev/null @@ -1,59 +0,0 @@ -package psgsim; - -import java.util.Map.Entry; - -import org.simgrid.msg.Host; -import peersim.cdsim.CDProtocol; -import peersim.core.Node; -import peersim.core.Protocol; - -/** - * This class handle an event of type NextCycleEvent, received on the protocol - * identified by a pid among all CDProtocols defined in the - * {@link PSGPlatform#cdProtocolsStepMap} collection. - *

    - * It executes the nextCyle method associated to this protocol. - * - * @author Khaled Baati 27/10/2014 - * @version version 1.1 - */ -public class PSGProcessCycle { - - /** - * Executes the nextCycle method of the CDprotocol with the appropriate - * parameters, and schedules the next call using {@link PSGSimulator#add}. - * - * @param host - * the host on which this component is run - * @param name - * the host's name - * @param delay - * the start time - * @param event - * the actual event - * @param pid - * the protocol identifier - */ - public static void nextCycle(Host host, String name, double delay, - Object event, int pid) { - CDProtocol cdp = null; - Node node = NodeHost.getNode(host); - cdp = (CDProtocol) node.getProtocol(pid); - cdp.nextCycle(node, pid); - PSGTransport.flush(); - for (Entry entry : PSGPlatform.cdProtocolsStepMap - .entrySet()) { - Double step = entry.getValue(); - for (Entry p : PSGPlatform.protocolsPidsMap - .entrySet()) { - if (p.getValue() == pid) { - break; - } - } - if (PSGPlatform.getTime() <= PSGPlatform.getDuration() && host.isOn()) { - PSGSimulator.add(PSGPlatform.sgToPsTime(step), event, node, pid); - } - } - } - -} diff --git a/contrib/psg/src/psgsim/PSGProcessEvent.java b/contrib/psg/src/psgsim/PSGProcessEvent.java deleted file mode 100644 index cc4f73c214..0000000000 --- a/contrib/psg/src/psgsim/PSGProcessEvent.java +++ /dev/null @@ -1,62 +0,0 @@ -package psgsim; - -import org.simgrid.msg.Host; -import org.simgrid.msg.MsgException; - -import peersim.core.Node; -import peersim.edsim.EDProtocol; - -/** - * This class extends {@link org.simgrid.msg.Process} which creates a process - * for each host (corresponding to node in peersim) in the system. - *

    - * The main method of this class is to handle events received, by calling the - * processEvent method on the corresponding node and pid. - *

    - * See {@link peersim.edsim.EDProtocol#processEvent} - * - * @author Khaled Baati 28/10/2014 - * @version version 1.1 - */ -public class PSGProcessEvent extends org.simgrid.msg.Process { - /** The delivered event **/ - private PSGTask task; - /** The current protocol **/ - private EDProtocol prot; - /** The identifier of the current protocol **/ - private int pid; - - /** - * Constructs a new process from the name of a host. - * - * @param host - * the local host to create according to the active node in - * peersim - * @param name - * the host's name - * @param args - * The arguments of main method of the process. - */ - public PSGProcessEvent(Host host, String name, String[] args) { - super(host, name, args); - } - - @Override - public void main(String[] args) throws MsgException { - Node node = NodeHost.getNode(getHost()); - Host.setAsyncMailbox(getHost().getName()); - while (PSGPlatform.getTime() < PSGPlatform.getDuration()) { - task = null; - task = (PSGTask) PSGTask.receive(Host.currentHost().getName(), - PSGPlatform.psToSgTime(PSGPlatform.getDuration() - PSGPlatform.getTime()-1)); - if (task != null && PSGPlatform.getTime() < PSGPlatform.getDuration()) { - pid = task.getPid(); - prot = (EDProtocol) node.getProtocol(pid); - prot.processEvent(node, pid, task.getEvent()); - PSGTransport.flush(); - } else - break; - } - } - -} diff --git a/contrib/psg/src/psgsim/PSGProcessLauncher.java b/contrib/psg/src/psgsim/PSGProcessLauncher.java deleted file mode 100644 index 97d89c0132..0000000000 --- a/contrib/psg/src/psgsim/PSGProcessLauncher.java +++ /dev/null @@ -1,74 +0,0 @@ -package psgsim; - -import org.simgrid.msg.Host; -import org.simgrid.msg.MsgException; - -import peersim.core.Node; -import peersim.edsim.EDProtocol; -import peersim.edsim.NextCycleEvent; - -/** - * This class extends {@link org.simgrid.msg.Process}, it creates a process for - * each event added in {@link PSGSimulator#add}. - *

    - * This class performs to launch the appropriate call according to the type of - * the event; - *

    - * - A NextCycleEvent: the event will be delivered to the - * {@link PSGProcessCycle} for treatment. - *

    - * - Otherwise the event is delivered to the destination protocol, that must - * implement {@link EDProtocol}, and the processEvent method is executed. - * - * @author Khaled Baati 12/11/2014 - * @version version 1.1 - */ -public class PSGProcessLauncher extends org.simgrid.msg.Process { - private EDProtocol prot = null; - private int pid; - private double delay; - private Object event; - private Host host; - - /** - * Constructs a new process from the name of a host and with the associated - * parameters - * - * @param host - * the local host - * @param name - * the host's name - * @param delay - * the start time of the process - * @param event - * the event added to the simulator - * @param pid - * the protocol identifier - */ - public PSGProcessLauncher(Host host, String name, double delay, Object event, - int pid) { - super(host, name, null, delay, -1); - this.host = host; - this.pid = pid; - this.event = event; - this.delay = delay; - } - - public PSGProcessLauncher(Host host, String name, String[] args) { - - } - - @Override - public void main(String[] args) throws MsgException { - Node node = NodeHost.getNode(host); - if (event instanceof NextCycleEvent) { - PSGProcessCycle.nextCycle(Host.currentHost(), host.getName(), - delay, event, pid); - } else { - prot = (EDProtocol) node.getProtocol(pid); - prot.processEvent(node, pid, event); - PSGTransport.flush(); - } - waitFor(500); - } -} \ No newline at end of file diff --git a/contrib/psg/src/psgsim/PSGSimulator.java b/contrib/psg/src/psgsim/PSGSimulator.java deleted file mode 100644 index cd60973b3d..0000000000 --- a/contrib/psg/src/psgsim/PSGSimulator.java +++ /dev/null @@ -1,99 +0,0 @@ -package psgsim; - -import org.simgrid.msg.Host; -import org.simgrid.msg.HostNotFoundException; -import org.simgrid.msg.Msg; -import org.simgrid.msg.NativeException; - -import peersim.core.CommonState; -import peersim.core.Network; -import peersim.core.Node; - -/** - * This is the main entry point to Simgrid simulator. This class loads the - * different parameters and initializes the simulation. - * - * @author Khaled Baati 14/10/2014 - * @version version 1.1 - */ -public class PSGSimulator { - public static int size; - - static { - Network.reset(); - size = Network.size(); - } - - // ========================== methods ================================== - // ===================================================================== - - /** - * Adds a new event to be scheduled, specifying the number of time units of - * delay (in seconds), the node and the protocol identifier to which the - * event will be delivered. A {@link psgsim.PSGProcessLauncher} process will - * be created according to this event. - * - * @param delay - * The number of time units (seconds in simgrid) before the event - * is scheduled. - * @param event - * The object associated to this event - * @param src - * The node associated to the event. - * @param pid - * The identifier of the protocol to which the event will be - * delivered - */ - public static void add(long delay, Object event, Node src, int pid) { - Host host = NodeHost.getHost(src); - double startTime = PSGPlatform.psToSgTime(delay) + Msg.getClock(); - if (startTime < PSGPlatform.psToSgTime(PSGPlatform.getDuration()) ) { - try { - /** - * random instruction associated to Heap.add(...) method in - * peersim.edsim - **/ - CommonState.r.nextInt(1 << 8); - new PSGProcessLauncher(host, host.getName(), startTime, event, - pid).start(); - } catch (HostNotFoundException e) { - System.err.println("Host not found"); - } - } - - } - - // ========================== main method ================================== - // ===================================================================== - public static void main() throws NativeException, HostNotFoundException { - - String platformfile = PSGPlatform.platformFile(); - System.err.println(platformfile + " loaded"); - String[] arguments = { platformfile, "deployment.xml" }; - Msg.init(arguments); - - /** construct the platform */ - Msg.createEnvironment(arguments[0]); - - PSGPlatform.protocols(); - - /** deploy the application **/ - Msg.deployApplication(arguments[1]); - - /** construct the host-node mapping **/ - NodeHost.start(); - - /** Process Controller **/ - PSGPlatform.control(); - if (!PSGPlatform.controlStepMap.isEmpty()) - new PSGProcessController(PSGPlatform.hostList[0], - PSGPlatform.hostList[0].getName(), null).start(); - - /** Load and execute the initializers classes in the configuration file **/ - PSGPlatform.init(); - - PSGPlatform.delete("deployment.xml"); - /** execute the simulation. **/ - Msg.run(); - } -} diff --git a/contrib/psg/src/psgsim/PSGTask.java b/contrib/psg/src/psgsim/PSGTask.java deleted file mode 100644 index 6d25e2c5fc..0000000000 --- a/contrib/psg/src/psgsim/PSGTask.java +++ /dev/null @@ -1,85 +0,0 @@ -package psgsim; - -import org.simgrid.msg.HostFailureException; -import org.simgrid.msg.Task; -import org.simgrid.msg.TimeoutException; -import org.simgrid.msg.TransferFailureException; - -/** - * The PSGTask includes all the parameters of sending a message as the size, the - * compute duration and the protocol identifier. - * - * @author Khaled Baati 28/10/2014 - * @version version 1.1 - */ -public class PSGTask extends org.simgrid.msg.Task { - /** The Message to be sent **/ - private Object event; - /** The protocol identifier **/ - private int pid; - - /** - * Construct a new task to be sent. - * - * @param name - * The name of task - * @param computeDuration - * The compute duration - * - * @param messageSize - * The size of the message - * @param event - * The message to be sent - * @param pid - * The protocol identifier - */ - public PSGTask(String name, double computeDuration, double messageSize, - Object event, int pid) { - super(name, computeDuration, messageSize); - this.event = event; - this.pid = pid; - } - - /** - * - * @return the protocol identifier - */ - public int getPid() { - return pid; - } - - /** - * - * @return the message - */ - public Object getEvent() { - return event; - } - - /** - * Retrieves next task on the mailbox identified by the specified name (wait - * at most timeout seconds) - * - * @param mailbox - * the mailbox on where to receive the task - * @param timeout - * the timeout to wait for receiving the task - * @return the task - */ - public static Task receive(String mailbox, double timeout) { - double time = PSGPlatform.getClock(); - if (time + timeout > PSGPlatform.getClock()) { - try { - return receive(mailbox, timeout, null); - } catch (TimeoutException e) { - } catch (TransferFailureException e) { - e.printStackTrace(); - } catch (HostFailureException e) { - e.printStackTrace(); - } - } - return null; - - } - -} diff --git a/contrib/psg/src/psgsim/PSGTransport.java b/contrib/psg/src/psgsim/PSGTransport.java deleted file mode 100644 index db964b4ccf..0000000000 --- a/contrib/psg/src/psgsim/PSGTransport.java +++ /dev/null @@ -1,115 +0,0 @@ -package psgsim; - -import java.util.LinkedHashMap; -import java.util.Map; - -import peersim.config.Configuration; -import peersim.config.IllegalParameterException; -import peersim.core.CommonState; -import peersim.core.Node; -import peersim.transport.Transport; - -/** - * PSGTransport is the transport layer. it is responsible for sending messages. - * - * @author Khaled Baati 28/10/2014 - * @version 1.1 - */ -public class PSGTransport implements Transport { - - private static double computeDuration = 0; - private PSGTask task; - private static Map taskToSend = new LinkedHashMap(); - - /** - * String name of the parameter used to configure the minimum latency. * @config - */ - private static final String PAR_MINDELAY = "mindelay"; - - /** - * String name of the parameter used to configure the maximum latency. - * Defaults to {@value #PAR_MINDELAY}, which results in a constant delay. - * - * @config - */ - private static final String PAR_MAXDELAY = "maxdelay"; - - /** Minimum delay for message sending */ - private long min; - /** Maximum delay for message sending */ - private long max; - - /** - * Difference between the max and min delay plus one. That is, max delay is - * min+range-1. - */ - private long range; - - public PSGTransport() { - - } - - public PSGTransport(String prefix) { - min = Configuration.getLong(prefix + "." + PAR_MINDELAY); - max = Configuration.getLong(prefix + "." + PAR_MAXDELAY, min); - if (max < min) - throw new IllegalParameterException(prefix + "." + PAR_MAXDELAY, - "The maximum latency cannot be smaller than the minimum latency"); - range = max - min + 1; - } - - /** - * Returns this. This way only one instance exists in the - * system that is linked from all the nodes. This is because this protocol - * has no node specific state. - */ - public Object clone() { - return this; - } - - @Override - public void send(Node src, Node dest, Object msg, int pid) { - double commSizeLat = 0; - /** - * random instruction associated to UniformRandomTransport.send(...) - * method in peersim.transport - **/ - long delay = (range == 1 ? min : min + CommonState.r.nextLong(range)); - CommonState.r.nextInt(1 << 8); - if (msg instanceof Sizable) { - commSizeLat = ((Sizable) msg).getSize(); - } - - task = new PSGTask("task sender_" + src.getID(), computeDuration, - commSizeLat, msg, pid); - taskToSend.put(this.task, NodeHost.getHost(dest).getName()); - - } - - /** - * Process for sending all messages in the queue. - */ - public static void flush() { - Map taskToSendCopy = new LinkedHashMap(); - for (Map.Entry entry : taskToSend.entrySet()) { - taskToSendCopy.put(entry.getKey(), entry.getValue()); - } - taskToSend.clear(); - for (Map.Entry entry : taskToSendCopy.entrySet()) { - PSGTask task = entry.getKey(); - String dest = entry.getValue(); - task.dsend(dest); - } - taskToSendCopy.clear(); - - } - - @Override - public long getLatency(Node src, Node dest) { - /** - * random instruction associated to - * UniformRandomTransport.getLatency(...) method in peersim.transport - **/ - return (range == 1 ? min : min + CommonState.r.nextLong(range)); - } -} diff --git a/contrib/psg/src/psgsim/Sizable.java b/contrib/psg/src/psgsim/Sizable.java deleted file mode 100644 index 16196f6815..0000000000 --- a/contrib/psg/src/psgsim/Sizable.java +++ /dev/null @@ -1,18 +0,0 @@ -package psgsim; - -/** - * An interface which defines a size for the message or the event to be sent. If you - * wish that your message has a size, your class message must implements this - * interface and defines a size parameter in the constructor. - * - * @author Khaled Baati 05/02/2015 - * @version 1.1 - * - */ -public interface Sizable { - /** - * - * @return The size of the message - */ - public double getSize(); -} diff --git a/contrib/psg/test.sh b/contrib/psg/test.sh deleted file mode 100755 index 7f6d61c7e3..0000000000 --- a/contrib/psg/test.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -if [ $(uname -m) = "i686" ]; then - eval ulimit -s 64 -else - eval ulimit -s 128 -fi - -echo -e "\n"; -echo '------------- Execute the edaggregation example under PSG -------------'; -echo -e "\n"; -java -Xmx1024m -cp lib.jar:classes:../../simgrid.jar peersim.Simulator configs/edaggregationPSG.txt -echo -e "\n"; -echo '------------- Execute the edaggregation example under PS -------------'; -echo -e "\n"; -java -Xmx1024m -cp lib.jar:classes:../../simgrid.jar peersim.Simulator configs/edaggregation.txt -echo -e "\n"; -echo '------------- Execute the chord example under PSG -------------'; -echo -e "\n"; -java -Xmx1024m -cp lib.jar:classes:../../simgrid.jar peersim.Simulator configs/chordPSG.txt -echo -e "\n"; -echo '------------- Execute the chord example under PS -------------'; -echo -e "\n"; -java -Xmx1024m -cp lib.jar:classes:../../simgrid.jar peersim.Simulator configs/chord.txt -echo -e "\n"; -echo '------------- Compare the 2 results PS and PSG -------------'; -echo -e "\n"; - -cd outputs - -ListeRep="$(find * -type d -prune)" # liste des repertoires -for Rep in ${ListeRep}; do - cd $Rep - VAR=$(diff ps.txt psg.txt) - if [ "${VAR}"1 = 1 ] - then - echo The results of diff "for" the $Rep example is '.............:)'; - else - echo The results of diff "for" the $Rep example is '.............:('; - fi - cd .. -done -echo -e "\n"; -exit 0 - diff --git a/contrib/psg/tutorial.odt b/contrib/psg/tutorial.odt deleted file mode 100644 index 9a1f50dd6d451bdb77417943d9781c7d8401944f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63343 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 bAA0_g<&|W?A%5S6^6@JBV6N(`-{1ZhM9#h( diff --git a/contrib/psg/tutorial.pdf b/contrib/psg/tutorial.pdf deleted file mode 100644 index df0ef22282d4338a18160c06c26d9a5f56f77106..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115095 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