Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge pull request #1 from mquinson/master
[simgrid.git] / contrib / psg / src / example / symphony / SymphonyNetworkBuilder.java
1 package example.symphony;\r
2 \r
3 import java.util.Collection;\r
4 import java.util.Comparator;\r
5 import java.util.LinkedList;\r
6 import java.util.logging.Level;\r
7 import java.util.logging.Logger;\r
8 \r
9 import example.symphony.SymphonyProtocol.BootstrapStatus;\r
10 import peersim.config.Configuration;\r
11 import peersim.core.CommonState;\r
12 import peersim.core.Control;\r
13 import peersim.core.Network;\r
14 import peersim.core.Node;\r
15 \r
16 /**\r
17  * Inizializer that create the initial ring\r
18  *\r
19  * @author Andrea Esposito <and1989@gmail.com>\r
20  */\r
21 public class SymphonyNetworkBuilder implements Control {\r
22 \r
23     private static final String PAR_SYMHONY = "symphony";\r
24     private static final String PAR_LONG_LINK = "createLongLinks";\r
25     private static final String PAR_MAX_ATTEMPTS = "attempts";\r
26     private final int symphonyID;\r
27     private final boolean createLongRangeLinks;\r
28     private final int MAX_ATTEMPTS;\r
29 \r
30     public SymphonyNetworkBuilder(String prefix) {\r
31 \r
32         symphonyID = Configuration.getPid(prefix + "." + PAR_SYMHONY);\r
33         createLongRangeLinks = Configuration.getBoolean(prefix + "." + PAR_LONG_LINK, true);\r
34         MAX_ATTEMPTS = Configuration.getInt(prefix + "." + PAR_MAX_ATTEMPTS, 5);\r
35     }\r
36 \r
37     public boolean execute() {\r
38 \r
39         // Sort the network for convenience (from 0.0 to 1.0)\r
40         Network.sort(new Comparator<Node>() {\r
41 \r
42             public int compare(Node o1, Node o2) {\r
43 \r
44                 SymphonyProtocol symphony1 = (SymphonyProtocol) o1.getProtocol(symphonyID);\r
45                 SymphonyProtocol symphony2 = (SymphonyProtocol) o2.getProtocol(symphonyID);\r
46 \r
47                 Double identifier1 = symphony1.getIdentifier();\r
48                 Double identifier2 = symphony2.getIdentifier();\r
49 \r
50                 return identifier1.compareTo(identifier2);\r
51             }\r
52         });\r
53 \r
54         int numShortLinksPerSide = ((SymphonyProtocol) Network.get(0).getProtocol(symphonyID)).numberShortRangeLinksPerSide;\r
55 \r
56         for (int i = 0; i < Network.size(); i++) {\r
57 \r
58             Node node = Network.get(i);\r
59             SymphonyProtocol symphonyNode = (SymphonyProtocol) node.getProtocol(symphonyID);\r
60 \r
61             // Create the short links\r
62             for (int j = 1; j <= numShortLinksPerSide; j++) {\r
63 \r
64                 int pos = i - j;\r
65                 pos = pos < 0 ? Network.size() + pos : pos;\r
66                 symphonyNode.rightShortRangeLinks.add(new Tuple<Node, BootstrapStatus>(Network.get(pos), BootstrapStatus.ONLINE));\r
67 \r
68                 pos = (i + j) % Network.size();\r
69                 symphonyNode.leftShortRangeLinks.add(new Tuple<Node, BootstrapStatus>(Network.get(pos), BootstrapStatus.ONLINE));\r
70             }\r
71 \r
72             symphonyNode.loggedIntoNetwork = SymphonyProtocol.BootstrapStatus.ONLINE;\r
73         }\r
74 \r
75         /*\r
76          * UPDATE: Putted a flag to decide if perform this part of code or not at configuration\r
77          * time. At default i create the long range links.\r
78          *\r
79          * The Long Range Links could be left to the networkmanager but the tests that we'll do have\r
80          * to put into account that in an initial phase will be some message exchanging to create\r
81          * the long range links and so the latency is faked... for that reason the long range links\r
82          * are created manually here such a way to have a complete symphony network from the\r
83          * beginning.\r
84          */\r
85         if (createLongRangeLinks) {\r
86             for (Node node : new AdapterIterableNetwork()) {\r
87 \r
88                 SymphonyProtocol symphonyNode = (SymphonyProtocol) node.getProtocol(symphonyID);\r
89 \r
90                 // Create the long links\r
91                 int k = (int) Math.ceil(Math.log(Network.size()) / Math.log(2));\r
92 \r
93                 if (symphonyNode.fixedLongRangeLinks) {\r
94                     k = symphonyNode.numberFixedLongRangeLinks;\r
95                 }\r
96 \r
97                 Collection<Node> allShortLinks = new LinkedList<Node>();\r
98                 for (Tuple<Node, BootstrapStatus> shortTuple : symphonyNode.leftShortRangeLinks) {\r
99                     allShortLinks.add(shortTuple.x);\r
100                 }\r
101                 for (Tuple<Node, BootstrapStatus> shortTuple : symphonyNode.rightShortRangeLinks) {\r
102                     allShortLinks.add(shortTuple.x);\r
103                 }\r
104 \r
105                 int j = 0;\r
106                 int attempts = MAX_ATTEMPTS;\r
107                 while (j <= k) {\r
108 \r
109                     double distance = Math.exp(k * (CommonState.r.nextDouble() - 1.0));\r
110                     double targetIdentifier = (symphonyNode.getIdentifier() + distance) % 1;\r
111 \r
112                     Node targetNode;\r
113                     try {\r
114 \r
115                         // use the unidirectional routing because i want to catch the manager\r
116                         targetNode = symphonyNode.findClosestNode(targetIdentifier, new AdapterIterableNetwork(), true);\r
117                         SymphonyProtocol symphonyTargetNode = (SymphonyProtocol) targetNode.getProtocol(symphonyID);\r
118                         if (!targetNode.equals(node)\r
119                                 && !symphonyNode.longRangeLinksOutgoing.contains(targetNode)\r
120                                 && symphonyTargetNode.longRangeLinksIncoming.size() < (2 * k)\r
121                                 && !allShortLinks.contains(targetNode)) {\r
122 \r
123                             boolean fresh = symphonyTargetNode.longRangeLinksIncoming.add(node);\r
124 \r
125                             if (fresh) {\r
126                                 j++;\r
127                                 attempts = MAX_ATTEMPTS;\r
128                                 symphonyNode.longRangeLinksOutgoing.add(targetNode);\r
129                             } else {\r
130                                 attempts--;\r
131                                 if (attempts <= 0) { // Because i don't want to loop i try a finite number of times\r
132                                     attempts = MAX_ATTEMPTS;\r
133                                     j++;\r
134                                 }\r
135 \r
136                             }\r
137                         } else {\r
138                             attempts--;\r
139                             if (attempts <= 0) { // Because i don't want to loop i try a finite number of times\r
140                                 attempts = MAX_ATTEMPTS;\r
141                                 j++;\r
142                             }\r
143 \r
144                         }\r
145                     } catch (RoutingException ex) {\r
146                         Logger.getLogger(SymphonyNetworkBuilder.class.getName()).log(Level.SEVERE, null, ex);\r
147                     }\r
148                 }\r
149             }\r
150         }\r
151 \r
152         // Shuffle\r
153         Network.shuffle();\r
154 \r
155         return false;\r
156     }\r
157 }\r