checkpoint save for testbed_run
[oweals/gnunet.git] / src / testbed / testbed_api_testbed.c
1 /*
2       This file is part of GNUnet
3       (C) 2008--2012 Christian Grothoff (and other contributing authors)
4
5       GNUnet is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published
7       by the Free Software Foundation; either version 3, or (at your
8       option) any later version.
9
10       GNUnet is distributed in the hope that it will be useful, but
11       WITHOUT ANY WARRANTY; without even the implied warranty of
12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13       General Public License for more details.
14
15       You should have received a copy of the GNU General Public License
16       along with GNUnet; see the file COPYING.  If not, write to the
17       Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18       Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file testbed/testbed_api_testbed.c
23  * @brief high-level testbed management
24  * @author Christian Grothoff
25  * @author Sree Harsha Totakura
26  */
27 #include "platform.h"
28 #include "gnunet_testbed_service.h"
29
30 /**
31  * Generic loggins shorthand
32  */
33 #define LOG(kind,...)                                   \
34   GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
35
36 /**
37  * Opaque handle to an abstract operation to be executed by the testing framework.
38  */
39 struct GNUNET_TESTBED_Testbed
40 {
41   // FIXME!
42 };
43
44
45 /**
46  * DLL of operations
47  */
48 struct DLLOperation
49 {
50   /**
51    * The testbed operation handle
52    */
53   struct GNUNET_TESTBED_Operation *op;
54
55   /**
56    * Context information for GNUNET_TESTBED_run()
57    */
58   struct RunContext *rc;  
59   
60   /**
61    * The next pointer for DLL
62    */
63   struct DLLOperation *next;
64   
65   /**
66    * The prev pointer for DLL
67    */
68   struct DLLOperation *prev;
69 };
70
71
72 /**
73  * DLL of peers
74  */
75 struct DLLPeer
76 {
77   /**
78    * Handle to testbed peer
79    */
80   struct GNUNET_TESTBED_Peer *peer;
81   
82   /**
83    * The next pointer for DLL
84    */
85   struct DLLPeer *next;
86   
87   /**
88    * The pre pointer for DLL
89    */
90   struct DLLPeer *prev;  
91 };
92
93
94 /**
95  * Context information for GNUNET_TESTBED_run()
96  */
97 struct RunContext
98 {
99   /**
100    * The controller handle
101    */
102   struct GNUNET_TESTBED_Controller *c;
103
104   /**
105    * Handle to the host on which the controller runs
106    */
107   struct GNUNET_TESTBED_Host *h;
108
109   /**
110    * The handle to the controller process
111    */
112   struct GNUNET_TESTBED_ControllerProc *cproc;
113
114   /**
115    * The callback to use as controller callback
116    */
117   GNUNET_TESTBED_ControllerCallback cc;
118   
119   /**
120    * The pointer to the controller callback
121    */
122   void *cc_cls;
123   
124   /**
125    * Master task to call when testbed initialization is done
126    */
127   GNUNET_SCHEDULER_Task master;
128   
129   /**
130    * The closure for the master task
131    */
132   void *master_cls;
133
134   /**
135    * The head element of DLL operations
136    */
137   struct DLLOperation *dll_op_head;
138   
139   /**
140    * The tail element of DLL operations
141    */
142   struct DLLOperation *dll_op_tail;
143
144   /**
145    * The head element of DLL peers
146    */
147   struct DLLPeer *dll_peer_head;
148   
149   /**
150    * The tail element of DLL peers
151    */
152   struct DLLPeer *dll_peer_tail;  
153   
154   /**
155    * The event mask for the controller
156    */
157   uint64_t event_mask;
158   
159   /**
160    * number of peers to start
161    */
162   unsigned int num_peers;  
163
164 };
165
166
167
168
169 /**
170  * Configure and run a testbed using the given
171  * master controller on 'num_hosts' starting
172  * 'num_peers' using the given peer configuration.
173  *
174  * @param controller master controller for the testbed
175  *                   (must not be destroyed until after the
176  *                    testbed is destroyed).
177  * @param num_hosts number of hosts in 'hosts', 0 to only
178  *        use 'localhost'
179  * @param hosts list of hosts to use for the testbed
180  * @param num_peers number of peers to start
181  * @param peer_cfg peer configuration template to use
182  * @param underlay_topology underlay topology to create
183  * @param va topology-specific options
184  * @return handle to the testbed
185  */
186 struct GNUNET_TESTBED_Testbed *
187 GNUNET_TESTBED_create_va (struct GNUNET_TESTBED_Controller *controller,
188                                   unsigned int num_hosts,
189                                   struct GNUNET_TESTBED_Host **hosts,
190                                   unsigned int num_peers,
191                                   const struct GNUNET_CONFIGURATION_Handle *peer_cfg,
192                                   enum GNUNET_TESTBED_TopologyOption underlay_topology,
193                                   va_list va)
194 {
195   GNUNET_break (0);
196   return NULL;
197 }
198
199
200 /**
201  * Configure and run a testbed using the given
202  * master controller on 'num_hosts' starting
203  * 'num_peers' using the given peer configuration.
204  *
205  * @param controller master controller for the testbed
206  *                   (must not be destroyed until after the
207  *                    testbed is destroyed).
208  * @param num_hosts number of hosts in 'hosts', 0 to only
209  *        use 'localhost'
210  * @param hosts list of hosts to use for the testbed
211  * @param num_peers number of peers to start
212  * @param peer_cfg peer configuration template to use
213  * @param underlay_topology underlay topology to create
214  * @param ... topology-specific options
215  */
216 struct GNUNET_TESTBED_Testbed *
217 GNUNET_TESTBED_create (struct GNUNET_TESTBED_Controller *controller,
218                        unsigned int num_hosts,
219                        struct GNUNET_TESTBED_Host **hosts,
220                        unsigned int num_peers,
221                        const struct GNUNET_CONFIGURATION_Handle *peer_cfg,
222                        enum GNUNET_TESTBED_TopologyOption underlay_topology,
223                        ...)
224 {
225   GNUNET_break (0);
226   return NULL;
227 }
228
229
230 /**
231  * Destroy a testbed.  Stops all running peers and then
232  * destroys all peers.  Does NOT destroy the master controller.
233  *
234  * @param testbed testbed to destroy
235  */
236 void
237 GNUNET_TESTBED_destroy (struct GNUNET_TESTBED_Testbed *testbed)
238 {
239   GNUNET_break (0);
240 }
241
242
243 /**
244  * Functions of this signature are called when a peer has been successfully
245  * created
246  *
247  * @param cls the closure from GNUNET_TESTBED_peer_create()
248  * @param peer the handle for the created peer; NULL on any error during
249  *          creation
250  * @param emsg NULL if peer is not NULL; else MAY contain the error description
251  */
252 static void 
253 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
254
255   struct DLLOperation *dll_op = cls;
256   struct RunContext *rc;
257   struct DLLPeer *dll_peer;
258   
259   GNUNET_assert (NULL != dll_op);  
260   rc = dll_op->rc;
261   GNUNET_assert (NULL != rc);
262   GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op);
263   GNUNET_TESTBED_operation_done (dll_op->op); 
264   GNUNET_free (dll_op);
265   if (NULL == peer)
266   {
267     if (NULL != emsg)
268       LOG (GNUNET_ERROR_TYPE_WARNING, "Error while creating a peer: %s\n", emsg);
269     return;    
270   }  
271   dll_peer = GNUNET_malloc (sizeof (struct DLLPeer));
272   dll_peer->peer = peer;
273   GNUNET_CONTAINER_DLL_insert_tail (rc->dll_peer_head, rc->dll_peer_tail,
274                                     dll_peer);
275 }
276
277
278
279 /**
280  * Callback to signal successfull startup of the controller process
281  *
282  * @param cls the closure from GNUNET_TESTBED_controller_start()
283  * @param cfg the configuration with which the controller has been started;
284  *          NULL if status is not GNUNET_OK
285  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
286  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
287  */
288 static void 
289 controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
290                       int status)
291 {  
292   struct RunContext *rc = cls;
293   struct DLLOperation *dll_op;
294   unsigned int peer;
295   
296   if (status != GNUNET_OK)
297   {
298     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed startup failed\n");
299     return;
300   }
301   rc->c = GNUNET_TESTBED_controller_connect (cfg, rc->h, rc->event_mask, rc->cc,
302                                              rc->cc_cls);
303   GNUNET_assert (NULL != rc->c);  
304   for (peer = 0; peer < rc->num_peers; peer++)
305   {
306     dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
307     dll_op->rc = rc;    
308     dll_op->op = GNUNET_TESTBED_peer_create (rc->c, rc->h, cfg, peer_create_cb,
309                                              dll_op);
310     GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op);    
311   }  
312 }
313
314
315 /**
316  * Convenience method for running a testbed with
317  * a single call.  Underlay and overlay topology
318  * are configured using the "UNDERLAY" and "OVERLAY"
319  * options in the "[testbed]" section of the configuration\
320  * (with possible options given in "UNDERLAY_XXX" and/or
321  * "OVERLAY_XXX").
322  *
323  * The testbed is to be terminated using a call to
324  * "GNUNET_SCHEDULER_shutdown".
325  *
326  * @param host_filename name of the file with the 'hosts', NULL
327  *        to run everything on 'localhost'
328  * @param cfg configuration to use (for testbed, controller and peers)
329  * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg?
330  * @param event_mask bit mask with set of events to call 'cc' for;
331  *                   or-ed values of "1LL" shifted by the
332  *                   respective 'enum GNUNET_TESTBED_EventType'
333  *                   (i.e.  "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...")
334  * @param cc controller callback to invoke on events
335  * @param cc_cls closure for cc
336  * @param master task to run once the testbed is ready
337  * @param master_cls closure for 'task'.
338  */
339 void
340 GNUNET_TESTBED_run (const char *host_filename,
341                     const struct GNUNET_CONFIGURATION_Handle *cfg,
342                     unsigned int num_peers,
343                     uint64_t event_mask,
344                     GNUNET_TESTBED_ControllerCallback cc,
345                     void *cc_cls,
346                     GNUNET_SCHEDULER_Task master,
347                     void *master_cls)
348 {
349   struct RunContext *rc;
350
351   rc = GNUNET_malloc (sizeof (struct RunContext));  
352   GNUNET_break (NULL != host_filename); /* Currently we do not support host
353                                            files */
354   host_filename = NULL;
355   rc->h = GNUNET_TESTBED_host_create (NULL, NULL, 0);
356   GNUNET_assert (NULL != rc->h);
357   rc->cproc = GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, cfg,
358                                                &controller_status_cb, rc);
359   GNUNET_assert (NULL != rc->cproc);  
360   rc->num_peers = num_peers;
361   rc->event_mask = event_mask;
362   rc->cc = cc;
363   rc->cc_cls = cc_cls;
364   rc->master = master;
365   rc->master_cls = master_cls;  
366 }
367
368
369
370 /* end of testbed_api_testbed.c */