Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
bdbd93a6acd8e9868d6f791acb420ae989409595
[simgrid.git] / contrib / psg / src / example / bittorrent / NetworkDynamics.java
1 /*
2  * Copyright (c) 2007-2008 Fabrizio Frioli, Michele Pedrolli
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  * Please send your questions/suggestions to:
20  * {fabrizio.frioli, michele.pedrolli} at studenti dot unitn dot it
21  *
22  */
23
24 package example.bittorrent;
25
26 import peersim.config.*;
27 import peersim.core.*;
28 import peersim.transport.*;
29 import peersim.edsim.*;
30
31 /**
32  * This {@link Control} can change the size of networks by adding and removing
33  * nodes. This class supports only permanent removal of nodes and the addition
34  * of brand new nodes. That is, temporary downtime is not supported by this
35  * class.
36  */
37 public class NetworkDynamics implements Control {
38         private static final int TRACKER = 11;
39         private static final int CHOKE_TIME = 13;
40         private static final int OPTUNCHK_TIME = 14;
41         private static final int ANTISNUB_TIME = 15;
42         private static final int CHECKALIVE_TIME = 16;
43         private static final int TRACKERALIVE_TIME = 17;
44
45         /**
46          * The protocol to operate on.
47          *
48          * @config
49          */
50         private static final String PAR_PROT = "protocol";
51
52         /**
53          * Nodes are removed until the size specified by this parameter is reached.
54          * The network will never go below this size as a result of this class.
55          * Defaults to 0.
56          * 
57          * @config
58          */
59         private static final String PAR_MIN = "minsize";
60
61         /**
62          * Specifies if the tracker can disappear from the network. 0 means no, 1
63          * means yes
64          * 
65          * @config
66          */
67         private static final String PAR_TRACKER_DIE = "tracker_can_die";
68
69         /**
70          * The Transport used by the the control.
71          * 
72          * @config
73          */
74         private static final String PAR_TRANSPORT = "transport";
75
76         /**
77          * Specifies how many nodes will be added to the network.
78          * 
79          * @config
80          */
81         private static final String PAR_ADD = "add";
82
83         /**
84          * Specifies how many nodes will be removed from the network.
85          * 
86          * @config
87          */
88         private static final String PAR_REMOVE = "remove";
89
90         /*
91          * The following are local variables, obtained from config property.
92          */
93         private final int pid;
94         private final int tid;
95         private final int maxSize;
96         private final int minsize;
97         private boolean trackerCanDie = false; // false (value 0) by default
98         private final int add; // number of nodes to be added
99         private final int remove; // number of nodes to be removed
100
101         private final NodeInitializer init;
102         private Node tracker;
103
104         /**
105          * Standard constructor that reads the configuration parameters. Invoked by
106          * the simulation engine.
107          * 
108          * @param prefix
109          *            the configuration prefix for this class
110          */
111         public NetworkDynamics(String prefix) {
112                 pid = Configuration.getPid(prefix + "." + PAR_PROT);
113                 minsize = Configuration.getInt(prefix + "." + PAR_MIN, 0);
114                 tid = Configuration.getPid(prefix + "." + PAR_TRANSPORT);
115                 add = Configuration.getInt(prefix + "." + PAR_ADD);
116                 remove = Configuration.getInt(prefix + "." + PAR_REMOVE);
117
118                 /*
119                  * By default, the tracker can not disappear. If
120                  * control.dynamics.tracker_can_die is set to 1, the tracker can die.
121                  */
122                 if (Configuration.getInt(prefix + "." + PAR_TRACKER_DIE) == 1) {
123                         trackerCanDie = true;
124                 }
125
126                 init = new NodeInitializer("init.net");
127                 tracker = Network.get(0);
128
129                 maxSize = (Network.size() - 1)
130                                 + ((BitTorrent) tracker.getProtocol(pid)).maxGrowth;
131         }
132
133         /**
134          * Adds n nodes to the network. New nodes can be added only if the tracker
135          * is up.
136          * 
137          * @param n
138          *            the number of nodes to add, must be non-negative.
139          */
140         protected void add(int n) {
141                 if (n == 0)
142                         return;
143                 // tracker is up
144                 if (tracker.isUp()) {
145                         for (int i = 0; i < n; ++i) {
146                                 // create a new node
147                                 Node nodeToBeAdded = (Node) Network.prototype.clone();
148
149                                 // add the new node to the network
150                                 Network.add(nodeToBeAdded); // questo nodo sara' in posizione
151                                                                                         // Network.len -1
152
153                                 /*
154                                  * Initialize the new node using the NodeInitializer class; this
155                                  * it the same as
156                                  * init.initialize(Network.get(Network.size()-1));
157                                  */
158                                 init.initialize(nodeToBeAdded);
159
160                                 /*
161                                  * The new node sends a TRACKER message to the tracker, asking
162                                  * for a list of peers. The tracker will respond with a PEERSET
163                                  * message. All the related events are also attached to the new
164                                  * node.
165                                  */
166                                 long latency =((Transport)nodeToBeAdded.getProtocol(tid)).getLatency(nodeToBeAdded,tracker);
167                                 Object ev = new SimpleMsg(TRACKER, nodeToBeAdded);
168                                 EDSimulator.add(latency,ev,tracker,pid);
169 //                              ((Transport) nodeToBeAdded.getProtocol(tid)).send(
170 //                                              nodeToBeAdded, tracker, ev, pid);
171
172                                 ev = new SimpleEvent(CHOKE_TIME);
173                                 EDSimulator.add(10000, ev, nodeToBeAdded, pid);
174                                 ev = new SimpleEvent(OPTUNCHK_TIME);
175                                 EDSimulator.add(30000, ev, nodeToBeAdded, pid);
176                                 ev = new SimpleEvent(ANTISNUB_TIME);
177                                 EDSimulator.add(60000, ev, nodeToBeAdded, pid);
178                                 ev = new SimpleEvent(CHECKALIVE_TIME);
179                                 EDSimulator.add(120000, ev, nodeToBeAdded, pid);
180                                 ev = new SimpleEvent(TRACKERALIVE_TIME);
181                                 EDSimulator.add(1800000, ev, nodeToBeAdded, pid);
182
183                                 // add the new node to the tracker's cache
184                                 if (((BitTorrent) tracker.getProtocol(pid))
185                                                 .addNeighbor(nodeToBeAdded))
186                                         System.out
187                                                         .println("DYN: A new node has been added to the network.");
188                         }
189                 }
190                 /*
191                  * Otherwise, the tracker is down and no new nodes can be added to the
192                  * network.
193                  */
194                 else
195                         System.out.println("DYN: Tracker is down. No new nodes added.");
196         }
197
198         /**
199          * Removes n nodes from the network. A node can be removed either if the
200          * tracker is up or down; if the tracker is up, the node to be removed will
201          * be removed also from the tracker's cache.
202          *
203          * @param n
204          *            the number of nodes to remove.
205          */
206         protected void remove(int n) {
207                 // the index of the node to be removed
208                 int nodeIndex = 0;
209
210                 for (int i = 0; i < n; ++i) {
211                         nodeIndex = CommonState.r.nextInt(Network.size());
212                         // if the tracker can not disappear from the network
213                         if (!trackerCanDie) {
214                                 /*
215                                  * Choose an index for the node to be removed. The value 0 will
216                                  * be discarded, since the tracker cannot disappear. Non
217                                  * existing nodes cannot be removed: if the returned index
218                                  * corresponds to a non-existing node, a new index will be
219                                  * generated.
220                                  */
221                                 while (nodeIndex == 0) {
222                                         nodeIndex = CommonState.r.nextInt(Network.size());
223                                 }
224                         }
225                         // otherwise, also the tracker can disappear
226                         else {
227                                 nodeIndex = CommonState.r.nextInt(Network.size());
228                         }
229
230                         // a warning message
231                         // if (nodeIndex==0)
232                         // System.out.println("DYN: The tracker is going to disapper.");
233
234                         // remove the node with the given index from the network
235                         Node nodeToBeRemoved = Network.remove(nodeIndex);
236
237                         // then remove it from the tracker's cache, if it is possible (= the
238                         // tracker is up);
239                         if (tracker.isUp()) {
240                                 if (((BitTorrent) tracker.getProtocol(pid))
241                                                 .removeNeighbor(nodeToBeRemoved))
242                                         System.err
243                                                         .println("DYN: A node has been removed from the network.");
244                         } else { // the tracker is down
245                                 System.err.println("DYN: The tracker is DOWN!");
246                         }
247                 }
248         }
249
250         /**
251          * Calls {@link #add(int)} or {@link #remove} with the parameters defined by
252          * the configuration.
253          * 
254          * @return always false
255          */
256         public boolean execute() {
257                 int choice = (CommonState.r.nextInt(2)); // 0 or 1
258                 // adding new nodes
259                 if (choice == 0) {
260                         /*
261                          * If the specified number of nodes cannot be added, it tries to add
262                          * a less number of nodes without going out of bounds. Otherwise,
263                          * all specified nodes will be added.
264                          */
265                         if (Network.size() + this.add > maxSize) {
266                                 System.err.println("DYN: " + (maxSize - Network.size())
267                                                 + " nodes will be added.");
268                                 add(maxSize - Network.size());
269                         } else {
270                                 System.err
271                                                 .println("DYN: " + this.add + " nodes will be added.");
272                                 add(this.add);
273                         }
274                 }
275                 // removing existing nodes
276                 else {
277                         if (Network.size() - this.remove < minsize) {
278                                 System.err.println("DYN: " + (Network.size() - minsize)
279                                                 + " nodes will be removed.");
280                                 remove(Network.size() - minsize);
281                         } else {
282                                 System.err.println("DYN: " + this.remove
283                                                 + " nodes will be removed.");
284                                 remove(this.remove);
285                         }
286                 }
287                 return false;
288         }
289 }