Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
peersimgrid release 1.0
[simgrid.git] / contrib / psg / src / peersim / core / Network.java
1 /*
2  * Copyright (c) 2003-2005 The BISON Project
3  *
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.
7  *
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.
12  *
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.
16  *
17  */
18
19 package peersim.core;
20
21 import peersim.Simulator;
22 import peersim.config.Configuration;
23 import psgsim.PSGDynamicNetwork;
24
25 import java.util.Comparator;
26 import java.util.Arrays;
27
28 import org.simgrid.msg.HostNotFoundException;
29 import org.simgrid.msg.MsgException;
30
31 /**
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.
37  * <p>
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}.
47  */
48 public class Network {
49
50         // ========================= fields =================================
51         // ==================================================================
52
53         /**
54          * This config property defines the node class to be used. If not set, then
55          * {@link GeneralNode} will be used.
56          * 
57          * @config
58          */
59         private static final String PAR_NODE = "network.node";
60
61         /**
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.
68          * 
69          * @see #getCapacity
70          * @config
71          */
72         private static final String PAR_MAXSIZE = "network.initialCapacity";
73
74         /**
75          * This config property defines the initial size of the overlay network.
76          * This property is required.
77          * 
78          * @config
79          */
80         private static final String PAR_SIZE = "network.size";
81
82         /**
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.
90          */
91         static Node[] node = null;
92
93         /**
94          * Actual size of the network.
95          */
96         private static int len;
97
98         /**
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.
102          */
103         public static Node prototype = null;
104
105         // ====================== initialization ===========================
106         // =================================================================
107
108         /**
109          * Reads configuration parameters, constructs the prototype node, and
110          * populates the network by cloning the prototype.
111          */
112         public static void reset() {
113
114                 if (prototype != null) {
115                         // not first experiment
116                         while (len > 0)
117                                 remove(); // this is to call onKill on all nodes
118                         prototype = null;
119                         node = null;
120                 }
121
122                 len = Configuration.getInt(PAR_SIZE);
123                 int maxlen = Configuration.getInt(PAR_MAXSIZE, len);
124                 if (maxlen < len)
125                         throw new IllegalArgumentException(PAR_MAXSIZE + " is less than "
126                                         + PAR_SIZE);
127
128                 node = new Node[maxlen];
129
130                 // creating prototype node
131                 Node tmp = null;
132                 if (!Configuration.contains(PAR_NODE)) {
133                         System.err.println("Network: no node defined, using GeneralNode");
134                         tmp = new GeneralNode("");
135                 } else {
136                         tmp = (Node) Configuration.getInstance(PAR_NODE);
137                 }
138                 prototype = tmp;
139                 prototype.setIndex(-1);
140
141                 // cloning the nodes
142                 if (len > 0) {
143                         for (int i = 0; i < len; ++i) {
144                                 node[i] = (Node) prototype.clone();
145                                 node[i].setIndex(i);
146                         }
147                 }
148         }
149
150         /** Disable instance construction */
151         private Network() {
152         }
153
154         // =============== public methods ===================================
155         // ==================================================================
156
157         /** Number of nodes currently in the network */
158         public static int size() {
159                 return len;
160         }
161
162         // ------------------------------------------------------------------
163
164         /**
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()}.
169          */
170         public static void setCapacity(int newSize) {
171
172                 if (node == null || newSize != node.length) {
173                         for (int i = newSize; i < len; ++i)
174                                 remove();
175                         Node[] newnodes = new Node[newSize];
176                         final int l = Math.min(node.length, newSize);
177                         System.arraycopy(node, 0, newnodes, 0, l);
178                         node = newnodes;
179                         if (len > newSize)
180                                 len = newSize;
181                 }
182         }
183
184         // ------------------------------------------------------------------
185
186         /**
187          * Returns the maximal number of nodes that can be stored without
188          * reallocating the underlying array to increase capacity.
189          */
190         public static int getCapacity() {
191                 return node.length;
192         }
193
194         // ------------------------------------------------------------------
195
196         /**
197          * The node will be appended to the end of the list. If necessary, the
198          * capacity of the internal array is increased.
199          */
200         public static void add(Node n) {
201                 if (len == node.length)
202                         setCapacity(3 * node.length / 2 + 1);
203                 node[len] = n;
204                 n.setIndex(len);
205                 len++;
206                 if (Simulator.getSimID() == 2)
207                         try {
208                                 PSGDynamicNetwork.add(n);
209                         } catch (HostNotFoundException e) {
210                                 System.err.println("Host not found in platform file");
211                         }
212                 System.err.println("node " + n.getID() + " with index " + n.getIndex()
213                                 + " was added at time " + CommonState.getTime());
214         }
215
216         // ------------------------------------------------------------------
217
218         /**
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()}.
223          */
224         public static Node get(int index) {
225                 return node[index];
226         }
227
228         // ------------------------------------------------------------------
229
230         /**
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}.
233          */
234         public static Node remove() {
235                 Node n = node[len - 1]; // if len was zero this throws and exception
236                 node[len - 1] = null;
237                 len--;
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);
243                 return n;
244         }
245
246         // ------------------------------------------------------------------
247
248         /**
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}.
251          * <p>
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
255          * index i.
256          */
257         public static Node remove(int i) {
258
259                 if (i < 0 || i >= len)
260                         throw new IndexOutOfBoundsException("" + i);
261                 swap(i, len - 1);
262                 return remove();
263         }
264
265         // ------------------------------------------------------------------
266
267         /**
268          * Swaps the two nodes at the given indexes.
269          */
270         public static void swap(int i, int j) {
271
272                 Node n = node[i];
273                 node[i] = node[j];
274                 node[j] = n;
275                 node[j].setIndex(j);
276                 node[i].setIndex(i);
277         }
278
279         // ------------------------------------------------------------------
280
281         /**
282          * Shuffles the node array. The index of each node is updated accordingly.
283          */
284         public static void shuffle() {
285
286                 for (int i = len; i > 1; i--)
287                         swap(i - 1, CommonState.r.nextInt(i));
288
289         }
290
291         // ------------------------------------------------------------------
292
293         /**
294          * Sorts the node array. The index of each node is updated accordingly.
295          * 
296          * @param c
297          *            The comparator to be used for sorting the nodes. If null, the
298          *            natural order of the nodes is used.
299          */
300         public static void sort(Comparator<? super Node> c) {
301
302                 Arrays.sort(node, 0, len, c);
303                 for (int i = 0; i < len; i++)
304                         node[i].setIndex(i);
305         }
306
307         // ------------------------------------------------------------------
308
309         public static void test() {
310
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());
316                 }
317
318                 if (prototype == null)
319                         return;
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),
323                                                 System.err);
324                 }
325         }
326
327 }