2 * Copyright (c) 2003-2005 The BISON Project
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 import peersim.Simulator;
22 import peersim.config.Configuration;
23 import psgsim.PSGDynamicNetwork;
25 import java.util.Comparator;
26 import java.util.Arrays;
28 import org.simgrid.msg.HostNotFoundException;
29 import org.simgrid.msg.MsgException;
32 * This class forms the basic framework of all simulations. This is a static
33 * singleton which is based on the assumption that we will simulate only one
34 * overlay network at a time. This allows us to reduce memory usage in many
35 * cases by allowing all the components to directly reach the fields of this
36 * class without having to store a reference.
38 * The network is a set of nodes implemented via an array list for the sake of
39 * efficiency. Each node has an array of protocols. The protocols within a node
40 * can interact directly as defined by their implementation, and can be imagined
41 * as processes running in a common local environment (i.e. the node). This
42 * class is called a "network" because, although it is only a set of nodes, in
43 * most simulations there is at least one {@link Linkable} protocol that defines
44 * connections between nodes. In fact, such a {@link Linkable} protocol layer
45 * can be accessed through a {@link peersim.graph.Graph} view using
46 * {@link OverlayGraph}.
48 public class Network {
50 // ========================= fields =================================
51 // ==================================================================
54 * This config property defines the node class to be used. If not set, then
55 * {@link GeneralNode} will be used.
59 private static final String PAR_NODE = "network.node";
62 * This config property defines the initial capacity of the overlay network.
63 * If not set then the value of {@value #PAR_SIZE} will be used. The main
64 * purpose of this parameter is that it allows for optimization. In the case
65 * of scenarios when the network needs to grow, setting this to the maximal
66 * expected size of the network avoids reallocation of memory during the
67 * growth of the network.
72 private static final String PAR_MAXSIZE = "network.initialCapacity";
75 * This config property defines the initial size of the overlay network.
76 * This property is required.
80 private static final String PAR_SIZE = "network.size";
83 * The node array. This is not a private array which is not nice but
84 * efficiency has the highest priority here. The main purpose is to allow
85 * the package quick reading of the contents in a maximally flexible way.
86 * Nevertheless, methods of this class should be used instead of the array
87 * when modifying the contents. Because this array is not private, it is
88 * necessary to know that the actual node set is only the first
89 * {@link #size()} items of the array.
91 static Node[] node = null;
94 * Actual size of the network.
96 private static int len;
99 * The prototype node which is used to populate the simulation via cloning.
100 * After all the nodes have been cloned, {@link Control} components can be
101 * applied to perform any further initialization.
103 public static Node prototype = null;
105 // ====================== initialization ===========================
106 // =================================================================
109 * Reads configuration parameters, constructs the prototype node, and
110 * populates the network by cloning the prototype.
112 public static void reset() {
114 if (prototype != null) {
115 // not first experiment
117 remove(); // this is to call onKill on all nodes
122 len = Configuration.getInt(PAR_SIZE);
123 int maxlen = Configuration.getInt(PAR_MAXSIZE, len);
125 throw new IllegalArgumentException(PAR_MAXSIZE + " is less than "
128 node = new Node[maxlen];
130 // creating prototype node
132 if (!Configuration.contains(PAR_NODE)) {
133 System.err.println("Network: no node defined, using GeneralNode");
134 tmp = new GeneralNode("");
136 tmp = (Node) Configuration.getInstance(PAR_NODE);
139 prototype.setIndex(-1);
143 for (int i = 0; i < len; ++i) {
144 node[i] = (Node) prototype.clone();
150 /** Disable instance construction */
154 // =============== public methods ===================================
155 // ==================================================================
157 /** Number of nodes currently in the network */
158 public static int size() {
162 // ------------------------------------------------------------------
165 * Sets the capacity of the internal array storing the nodes. The nodes will
166 * remain the same in the same order. If the new capacity is less than the
167 * old size of the node list, than the end of the list is cut. The nodes
168 * that get removed via this cutting are removed through {@link #remove()}.
170 public static void setCapacity(int newSize) {
172 if (node == null || newSize != node.length) {
173 for (int i = newSize; i < len; ++i)
175 Node[] newnodes = new Node[newSize];
176 final int l = Math.min(node.length, newSize);
177 System.arraycopy(node, 0, newnodes, 0, l);
184 // ------------------------------------------------------------------
187 * Returns the maximal number of nodes that can be stored without
188 * reallocating the underlying array to increase capacity.
190 public static int getCapacity() {
194 // ------------------------------------------------------------------
197 * The node will be appended to the end of the list. If necessary, the
198 * capacity of the internal array is increased.
200 public static void add(Node n) {
201 if (len == node.length)
202 setCapacity(3 * node.length / 2 + 1);
206 if (Simulator.getSimID() == 2)
208 PSGDynamicNetwork.add(n);
209 } catch (HostNotFoundException e) {
210 System.err.println("Host not found in platform file");
212 System.err.println("node " + n.getID() + " with index " + n.getIndex()
213 + " was added at time " + CommonState.getTime());
216 // ------------------------------------------------------------------
219 * Returns node with the given index. Note that the same node will normally
220 * have a different index in different times. This can be used as a random
221 * access iterator. This method does not perform range checks to increase
222 * efficiency. The maximal valid index is {@link #size()}.
224 public static Node get(int index) {
228 // ------------------------------------------------------------------
231 * The node at the end of the list is removed. Returns the removed node. It
232 * also sets the fail state of the node to {@link Fallible#DEAD}.
234 public static Node remove() {
235 Node n = node[len - 1]; // if len was zero this throws and exception
236 node[len - 1] = null;
238 System.err.println("node " + n.getID() + " with index " + n.getIndex()
239 + " was removed at time " + CommonState.getTime());
240 n.setFailState(Fallible.DEAD);
241 if (Simulator.getSimID() == 2)
242 PSGDynamicNetwork.remove(n);
246 // ------------------------------------------------------------------
249 * The node with the given index is removed. Returns the removed node. It
250 * also sets the fail state of the node to {@link Fallible#DEAD}.
252 * Look out: the index of the other nodes will not change (the right hand
253 * side of the list is not shifted to the left) except that of the last
254 * node. Only the last node is moved to the given position and will get
257 public static Node remove(int i) {
259 if (i < 0 || i >= len)
260 throw new IndexOutOfBoundsException("" + i);
265 // ------------------------------------------------------------------
268 * Swaps the two nodes at the given indexes.
270 public static void swap(int i, int j) {
279 // ------------------------------------------------------------------
282 * Shuffles the node array. The index of each node is updated accordingly.
284 public static void shuffle() {
286 for (int i = len; i > 1; i--)
287 swap(i - 1, CommonState.r.nextInt(i));
291 // ------------------------------------------------------------------
294 * Sorts the node array. The index of each node is updated accordingly.
297 * The comparator to be used for sorting the nodes. If null, the
298 * natural order of the nodes is used.
300 public static void sort(Comparator<? super Node> c) {
302 Arrays.sort(node, 0, len, c);
303 for (int i = 0; i < len; i++)
307 // ------------------------------------------------------------------
309 public static void test() {
311 System.err.println("number of nodes = " + len);
312 System.err.println("capacity (max number of nodes) = " + node.length);
313 for (int i = 0; i < len; ++i) {
314 System.err.println("node[" + i + "]");
315 System.err.println(node[i].toString());
318 if (prototype == null)
320 for (int i = 0; i < prototype.protocolSize(); ++i) {
321 if (prototype.getProtocol(i) instanceof Linkable)
322 peersim.graph.GraphIO.writeUCINET_DL(new OverlayGraph(i),