Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
peersimgrid release 1.0
[simgrid.git] / contrib / psg / src / peersim / core / Network.java
diff --git a/contrib/psg/src/peersim/core/Network.java b/contrib/psg/src/peersim/core/Network.java
new file mode 100644 (file)
index 0000000..da9c545
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * 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.
+ * <p>
+ * 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}.
+        * <p>
+        * 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<? super Node> 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);
+               }
+       }
+
+}