--- /dev/null
+package example.symphony;\r
+\r
+import java.util.*;\r
+import peersim.config.Configuration;\r
+import peersim.core.Network;\r
+import peersim.core.Node;\r
+\r
+/**\r
+ *\r
+ * @author Andrea Esposito <and1989@gmail.com>\r
+ */\r
+public class SymphonyEstimationProtocol implements NetworkSizeEstimatorProtocolInterface {\r
+\r
+ private static final String PAR_SYMPHONY = "symphony";\r
+ private static final String PAR_S = "s";\r
+ private final int symphonyID;\r
+ private final int s;\r
+\r
+ public SymphonyEstimationProtocol(String prefix) {\r
+ symphonyID = Configuration.getPid(prefix + "." + PAR_SYMPHONY);\r
+ s = Configuration.getInt(prefix + "." + PAR_S, -1);\r
+ }\r
+\r
+ /**\r
+ * Implementation of the estimated network size as a variant of the paper one. It use anyway the\r
+ * idea to calculate the size from the length segments but without exchanging the information\r
+ * with the neighbours instead using only the local information.\r
+ */\r
+ public int getNetworkSize(Node node) {\r
+ SymphonyProtocol symphony = (SymphonyProtocol) node.getProtocol(symphonyID);\r
+\r
+ // If the node is not yet inside the ring i return the minimum size (2 nodes)\r
+ if (!symphony.isBootstrapped()) {\r
+ return 2;\r
+ }\r
+\r
+ /*\r
+ * I clone the short range links views (wrapped into an ArrayList because the returned list\r
+ * 'Arrays.asList doesn't support the "removeAll" method or better its size is fixed)\r
+ */\r
+ ArrayList<Tuple<Node, SymphonyProtocol.BootstrapStatus>> leftList = new ArrayList<Tuple<Node, SymphonyProtocol.BootstrapStatus>>(Arrays.asList((Tuple<Node, SymphonyProtocol.BootstrapStatus>[]) symphony.leftShortRangeLinks.toArray(new Tuple[0])));\r
+ ArrayList<Tuple<Node, SymphonyProtocol.BootstrapStatus>> rightList = new ArrayList<Tuple<Node, SymphonyProtocol.BootstrapStatus>>(Arrays.asList((Tuple<Node, SymphonyProtocol.BootstrapStatus>[]) symphony.rightShortRangeLinks.toArray(new Tuple[0])));\r
+\r
+ // Remove the neighbours that are offline\r
+ LinkedList<Tuple<Node, SymphonyProtocol.BootstrapStatus>> offlineNeighbors = new LinkedList<Tuple<Node, SymphonyProtocol.BootstrapStatus>>();\r
+ for (Tuple<Node, SymphonyProtocol.BootstrapStatus> tuple : leftList) {\r
+ if (tuple.y == SymphonyProtocol.BootstrapStatus.OFFLINE) {\r
+ offlineNeighbors.add(tuple);\r
+ }\r
+ }\r
+ leftList.removeAll(offlineNeighbors);\r
+ offlineNeighbors.clear();\r
+ for (Tuple<Node, SymphonyProtocol.BootstrapStatus> tuple : rightList) {\r
+ if (tuple.y == SymphonyProtocol.BootstrapStatus.OFFLINE) {\r
+ offlineNeighbors.add(tuple);\r
+ }\r
+ }\r
+ rightList.removeAll(offlineNeighbors);\r
+\r
+ // Sort the neighbours based on the distance from me\r
+ Comparator<Tuple<Node, SymphonyProtocol.BootstrapStatus>> comparator = new AdapterSymphonyNodeComparator(new SymphonyNodeComparator(symphonyID, symphony.getIdentifier()));\r
+ Collections.sort(leftList, comparator);\r
+ Collections.sort(rightList, comparator);\r
+\r
+ // Calculate the variables to estimated the network size\r
+ double Xs = 0;\r
+ int countS = 0;\r
+\r
+ List<Tuple<Node, SymphonyProtocol.BootstrapStatus>> appoList[] = new List[2];\r
+ appoList[0] = leftList;\r
+ appoList[1] = rightList;\r
+\r
+ double[] appoPrecIdentifier = new double[]{symphony.getIdentifier(), symphony.getIdentifier()};\r
+ int[] appoCurrentIndex = new int[]{0, 0};\r
+\r
+ int realS = (int) (s <= 0 ? Math.log(Network.size() / Math.log(2)) : s);\r
+\r
+ for (int i = 0; i < realS; i++) {\r
+ double precIdentifier = appoPrecIdentifier[i % 2];\r
+ int currentIndex = appoCurrentIndex[i % 2];\r
+ List<Tuple<Node, SymphonyProtocol.BootstrapStatus>> currentList = appoList[i % 2];\r
+\r
+ try {\r
+ double currentIdentifier = ((SymphonyProtocol) currentList.get(currentIndex).x.getProtocol(symphonyID)).getIdentifier();\r
+\r
+ appoPrecIdentifier[i % 2] = currentIdentifier;\r
+ appoCurrentIndex[i % 2] = appoCurrentIndex[i % 2] + 1;\r
+\r
+ double distance = Math.abs(currentIdentifier - precIdentifier);\r
+ Xs += Math.min(distance, 1.0 - distance);\r
+ countS++;\r
+ } catch (IndexOutOfBoundsException ex) {\r
+ // Simply i skip the counting\r
+ }\r
+ }\r
+\r
+ int ret = Xs == 0 ? 0 : (int) Math.round(countS / Xs);\r
+\r
+ return ret;\r
+ }\r
+\r
+ @Override\r
+ public Object clone() {\r
+ return this;\r
+ }\r
+}\r