--- /dev/null
+package example.symphony;\r
+\r
+import java.util.Collection;\r
+import java.util.Comparator;\r
+import java.util.LinkedList;\r
+import java.util.logging.Level;\r
+import java.util.logging.Logger;\r
+\r
+import example.symphony.SymphonyProtocol.BootstrapStatus;\r
+import peersim.config.Configuration;\r
+import peersim.core.CommonState;\r
+import peersim.core.Control;\r
+import peersim.core.Network;\r
+import peersim.core.Node;\r
+\r
+/**\r
+ * Inizializer that create the initial ring\r
+ *\r
+ * @author Andrea Esposito <and1989@gmail.com>\r
+ */\r
+public class SymphonyNetworkBuilder implements Control {\r
+\r
+ private static final String PAR_SYMHONY = "symphony";\r
+ private static final String PAR_LONG_LINK = "createLongLinks";\r
+ private static final String PAR_MAX_ATTEMPTS = "attempts";\r
+ private final int symphonyID;\r
+ private final boolean createLongRangeLinks;\r
+ private final int MAX_ATTEMPTS;\r
+\r
+ public SymphonyNetworkBuilder(String prefix) {\r
+\r
+ symphonyID = Configuration.getPid(prefix + "." + PAR_SYMHONY);\r
+ createLongRangeLinks = Configuration.getBoolean(prefix + "." + PAR_LONG_LINK, true);\r
+ MAX_ATTEMPTS = Configuration.getInt(prefix + "." + PAR_MAX_ATTEMPTS, 5);\r
+ }\r
+\r
+ public boolean execute() {\r
+\r
+ // Sort the network for convenience (from 0.0 to 1.0)\r
+ Network.sort(new Comparator<Node>() {\r
+\r
+ public int compare(Node o1, Node o2) {\r
+\r
+ SymphonyProtocol symphony1 = (SymphonyProtocol) o1.getProtocol(symphonyID);\r
+ SymphonyProtocol symphony2 = (SymphonyProtocol) o2.getProtocol(symphonyID);\r
+\r
+ Double identifier1 = symphony1.getIdentifier();\r
+ Double identifier2 = symphony2.getIdentifier();\r
+\r
+ return identifier1.compareTo(identifier2);\r
+ }\r
+ });\r
+\r
+ int numShortLinksPerSide = ((SymphonyProtocol) Network.get(0).getProtocol(symphonyID)).numberShortRangeLinksPerSide;\r
+\r
+ for (int i = 0; i < Network.size(); i++) {\r
+\r
+ Node node = Network.get(i);\r
+ SymphonyProtocol symphonyNode = (SymphonyProtocol) node.getProtocol(symphonyID);\r
+\r
+ // Create the short links\r
+ for (int j = 1; j <= numShortLinksPerSide; j++) {\r
+\r
+ int pos = i - j;\r
+ pos = pos < 0 ? Network.size() + pos : pos;\r
+ symphonyNode.rightShortRangeLinks.add(new Tuple<Node, BootstrapStatus>(Network.get(pos), BootstrapStatus.ONLINE));\r
+\r
+ pos = (i + j) % Network.size();\r
+ symphonyNode.leftShortRangeLinks.add(new Tuple<Node, BootstrapStatus>(Network.get(pos), BootstrapStatus.ONLINE));\r
+ }\r
+\r
+ symphonyNode.loggedIntoNetwork = SymphonyProtocol.BootstrapStatus.ONLINE;\r
+ }\r
+\r
+ /*\r
+ * UPDATE: Putted a flag to decide if perform this part of code or not at configuration\r
+ * time. At default i create the long range links.\r
+ *\r
+ * The Long Range Links could be left to the networkmanager but the tests that we'll do have\r
+ * to put into account that in an initial phase will be some message exchanging to create\r
+ * the long range links and so the latency is faked... for that reason the long range links\r
+ * are created manually here such a way to have a complete symphony network from the\r
+ * beginning.\r
+ */\r
+ if (createLongRangeLinks) {\r
+ for (Node node : new AdapterIterableNetwork()) {\r
+\r
+ SymphonyProtocol symphonyNode = (SymphonyProtocol) node.getProtocol(symphonyID);\r
+\r
+ // Create the long links\r
+ int k = (int) Math.ceil(Math.log(Network.size()) / Math.log(2));\r
+\r
+ if (symphonyNode.fixedLongRangeLinks) {\r
+ k = symphonyNode.numberFixedLongRangeLinks;\r
+ }\r
+\r
+ Collection<Node> allShortLinks = new LinkedList<Node>();\r
+ for (Tuple<Node, BootstrapStatus> shortTuple : symphonyNode.leftShortRangeLinks) {\r
+ allShortLinks.add(shortTuple.x);\r
+ }\r
+ for (Tuple<Node, BootstrapStatus> shortTuple : symphonyNode.rightShortRangeLinks) {\r
+ allShortLinks.add(shortTuple.x);\r
+ }\r
+\r
+ int j = 0;\r
+ int attempts = MAX_ATTEMPTS;\r
+ while (j <= k) {\r
+\r
+ double distance = Math.exp(k * (CommonState.r.nextDouble() - 1.0));\r
+ double targetIdentifier = (symphonyNode.getIdentifier() + distance) % 1;\r
+\r
+ Node targetNode;\r
+ try {\r
+\r
+ // use the unidirectional routing because i want to catch the manager\r
+ targetNode = symphonyNode.findClosestNode(targetIdentifier, new AdapterIterableNetwork(), true);\r
+ SymphonyProtocol symphonyTargetNode = (SymphonyProtocol) targetNode.getProtocol(symphonyID);\r
+ if (!targetNode.equals(node)\r
+ && !symphonyNode.longRangeLinksOutgoing.contains(targetNode)\r
+ && symphonyTargetNode.longRangeLinksIncoming.size() < (2 * k)\r
+ && !allShortLinks.contains(targetNode)) {\r
+\r
+ boolean fresh = symphonyTargetNode.longRangeLinksIncoming.add(node);\r
+\r
+ if (fresh) {\r
+ j++;\r
+ attempts = MAX_ATTEMPTS;\r
+ symphonyNode.longRangeLinksOutgoing.add(targetNode);\r
+ } else {\r
+ attempts--;\r
+ if (attempts <= 0) { // Because i don't want to loop i try a finite number of times\r
+ attempts = MAX_ATTEMPTS;\r
+ j++;\r
+ }\r
+\r
+ }\r
+ } else {\r
+ attempts--;\r
+ if (attempts <= 0) { // Because i don't want to loop i try a finite number of times\r
+ attempts = MAX_ATTEMPTS;\r
+ j++;\r
+ }\r
+\r
+ }\r
+ } catch (RoutingException ex) {\r
+ Logger.getLogger(SymphonyNetworkBuilder.class.getName()).log(Level.SEVERE, null, ex);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // Shuffle\r
+ Network.shuffle();\r
+\r
+ return false;\r
+ }\r
+}\r