social: API changes for application connections: store/load app subscriptions to...
[oweals/gnunet.git] / src / ats-tests / ats-testing-experiment.c
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2010-2013 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., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19  */
20 /**
21  * @file ats-tests/ats-testing-experiment.c
22  * @brief ats benchmark: controlled experiment execution
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "ats-testing.h"
29
30 const char *
31 print_op (enum OperationType op)
32 {
33   switch (op) {
34     case START_SEND:
35       return "START_SEND";
36     case STOP_SEND:
37       return "STOP_SEND";
38     case START_PREFERENCE:
39       return "START_PREFERENCE";
40     case STOP_PREFERENCE:
41       return "STOP_PREFERENCE";
42     default:
43       break;
44   }
45   return "";
46 }
47
48
49 static struct Experiment *
50 create_experiment ()
51 {
52   struct Experiment *e;
53   e = GNUNET_new (struct Experiment);
54   e->name = NULL;
55   e->num_masters = 0;
56   e->num_slaves = 0;
57   e->start = NULL;
58   e->total_duration = GNUNET_TIME_UNIT_ZERO;
59   return e;
60 }
61
62 static void
63 free_experiment (struct Experiment *e)
64 {
65   struct Episode *cur;
66   struct Episode *next;
67   struct GNUNET_ATS_TEST_Operation *cur_o;
68   struct GNUNET_ATS_TEST_Operation *next_o;
69
70   next = e->start;
71   for (cur = next; NULL != cur; cur = next)
72   {
73     next = cur->next;
74
75     next_o = cur->head;
76     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
77     {
78       next_o = cur_o->next;
79       GNUNET_free (cur_o);
80     }
81     GNUNET_free (cur);
82   }
83
84   GNUNET_free_non_null (e->name);
85   GNUNET_free_non_null (e->cfg_file);
86   GNUNET_free (e);
87 }
88
89
90 static int
91 load_episode (struct Experiment *e,
92               struct Episode *cur,
93               struct GNUNET_CONFIGURATION_Handle *cfg)
94 {
95   struct GNUNET_ATS_TEST_Operation *o;
96   char *sec_name;
97   char *op_name;
98   char *op;
99   char *type;
100   char *pref;
101   int op_counter = 0;
102
103   fprintf (stderr, "Parsing episode %u\n",cur->id);
104   GNUNET_asprintf (&sec_name, "episode-%u", cur->id);
105
106   while (1)
107   {
108     /* Load operation */
109     GNUNET_asprintf (&op_name, "op-%u-operation", op_counter);
110     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
111         sec_name, op_name, &op))
112     {
113       GNUNET_free (op_name);
114       break;
115     }
116     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
117     /* operations = set_rate, start_send, stop_send, set_preference */
118     if (0 == strcmp (op, "start_send"))
119     {
120       o->type = START_SEND;
121     }
122     else if (0 == strcmp (op, "stop_send"))
123     {
124       o->type = STOP_SEND;
125     }
126     else if (0 == strcmp (op, "start_preference"))
127     {
128       o->type = START_PREFERENCE;
129     }
130     else if (0 == strcmp (op, "stop_preference"))
131     {
132       o->type = STOP_PREFERENCE;
133     }
134     else
135     {
136       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
137           op_counter, op, cur->id);
138       GNUNET_free (op);
139       GNUNET_free (op_name);
140       GNUNET_free (o);
141       GNUNET_free (sec_name);
142       return GNUNET_SYSERR;
143     }
144     GNUNET_free (op_name);
145
146     /* Get source */
147     GNUNET_asprintf(&op_name, "op-%u-src", op_counter);
148     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
149         sec_name, op_name, &o->src_id))
150     {
151       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
152           op_counter, op, cur->id);
153       GNUNET_free (op);
154       GNUNET_free (op_name);
155       GNUNET_free (o);
156       GNUNET_free (sec_name);
157       return GNUNET_SYSERR;
158     }
159     if (o->src_id > (e->num_masters - 1))
160     {
161       fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n",
162           o->src_id, op_counter, op, cur->id);
163       GNUNET_free (op);
164       GNUNET_free (op_name);
165       GNUNET_free (o);
166       GNUNET_free (sec_name);
167       return GNUNET_SYSERR;
168     }
169     GNUNET_free (op_name);
170
171     /* Get destination */
172     GNUNET_asprintf(&op_name, "op-%u-dest", op_counter);
173     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
174         sec_name, op_name, &o->dest_id))
175     {
176       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
177           op_counter, op, cur->id);
178       GNUNET_free (op);
179       GNUNET_free (op_name);
180       GNUNET_free (o);
181       GNUNET_free (sec_name);
182       return GNUNET_SYSERR;
183     }
184     if (o->dest_id > (e->num_slaves - 1))
185     {
186       fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n",
187           o->dest_id, op_counter, op, cur->id);
188       GNUNET_free (op);
189       GNUNET_free (op_name);
190       GNUNET_free (o);
191       GNUNET_free (sec_name);
192       return GNUNET_SYSERR;
193     }
194     GNUNET_free (op_name);
195
196     GNUNET_asprintf(&op_name, "op-%u-type", op_counter);
197     if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg,
198             sec_name, op_name, &type)) &&
199         ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type)))
200     {
201       /* Load arguments for set_rate, start_send, set_preference */
202       if (0 == strcmp (type, "constant"))
203       {
204         o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
205       }
206       else if (0 == strcmp (type, "linear"))
207       {
208         o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
209       }
210       else if (0 == strcmp (type, "sinus"))
211       {
212         o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
213       }
214       else if (0 == strcmp (type, "random"))
215       {
216         o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
217       }
218       else
219       {
220         fprintf (stderr, "Invalid type %u `%s' in episode %u\n",
221             op_counter, op, cur->id);
222         GNUNET_free (type);
223         GNUNET_free (op);
224         GNUNET_free (op_name);
225         GNUNET_free (sec_name);
226         GNUNET_free (o);
227         return GNUNET_SYSERR;
228       }
229       GNUNET_free (op_name);
230
231       /* Get base rate */
232       GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
233       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
234           sec_name, op_name, &o->base_rate))
235       {
236         fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
237             op_counter, op, cur->id);
238         GNUNET_free (type);
239         GNUNET_free (op);
240         GNUNET_free (op_name);
241         GNUNET_free (sec_name);
242         GNUNET_free (o);
243         return GNUNET_SYSERR;
244       }
245       GNUNET_free (op_name);
246
247       /* Get max rate */
248       GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
249       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
250           sec_name, op_name, &o->max_rate))
251       {
252         if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
253             (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
254             (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
255         {
256           fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
257               op_counter, op, cur->id);
258           GNUNET_free (type);
259           GNUNET_free (op_name);
260           GNUNET_free (op);
261           GNUNET_free (o);
262           GNUNET_free (sec_name);
263           return GNUNET_SYSERR;
264         }
265       }
266       GNUNET_free (op_name);
267
268       /* Get period */
269       GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
270       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
271           sec_name, op_name, &o->period))
272       {
273         o->period = cur->duration;
274       }
275       GNUNET_free (op_name);
276
277       if (START_PREFERENCE == o->type)
278       {
279           /* Get frequency */
280           GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
281           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
282               sec_name, op_name, &o->frequency))
283           {
284               fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
285                   op_counter, op, cur->id);
286               GNUNET_free (type);
287               GNUNET_free (op_name);
288               GNUNET_free (op);
289               GNUNET_free (o);
290               GNUNET_free (sec_name);
291               return GNUNET_SYSERR;
292           }
293           GNUNET_free (op_name);
294
295           /* Get preference */
296           GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
297           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
298               sec_name, op_name, &pref))
299           {
300               fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
301                   op_counter, op, cur->id);
302               GNUNET_free (type);
303               GNUNET_free (op_name);
304               GNUNET_free (op);
305               GNUNET_free_non_null (pref);
306               GNUNET_free (o);
307               GNUNET_free (sec_name);
308               return GNUNET_SYSERR;
309           }
310
311           if (0 == strcmp(pref, "bandwidth"))
312             o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH;
313           else if (0 == strcmp(pref, "latency"))
314             o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY;
315           else
316           {
317               fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
318                   op_counter, op, cur->id);
319               GNUNET_free (type);
320               GNUNET_free (op_name);
321               GNUNET_free (op);
322               GNUNET_free (pref);
323               GNUNET_free_non_null (pref);
324               GNUNET_free (o);
325               GNUNET_free (sec_name);
326               return GNUNET_SYSERR;
327           }
328           GNUNET_free (pref);
329           GNUNET_free (op_name);
330       }
331     }
332
333     /* Safety checks */
334     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
335         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
336     {
337       if ((o->max_rate - o->base_rate) > o->base_rate)
338       {
339         /* This will cause an underflow */
340         GNUNET_break (0);
341       }
342       fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n");
343     }
344
345     if ((START_SEND == o->type) || (START_PREFERENCE == o->type))
346       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n",
347         op_counter, cur->id, print_op (o->type), o->src_id,
348         o->dest_id, (NULL != type) ? type : "",
349         o->base_rate, o->max_rate,
350         GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES));
351     else
352       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n",
353         op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id);
354
355     GNUNET_free_non_null (type);
356     GNUNET_free (op);
357
358     GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o);
359     op_counter++;
360   }
361   GNUNET_free (sec_name);
362
363   return GNUNET_OK;
364 }
365
366
367 static int
368 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
369 {
370   int e_counter = 0;
371   char *sec_name;
372   struct GNUNET_TIME_Relative e_duration;
373   struct Episode *cur;
374   struct Episode *last;
375
376   e_counter = 0;
377   last = NULL;
378   while (1)
379   {
380     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
381     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
382         sec_name, "duration", &e_duration))
383     {
384       GNUNET_free (sec_name);
385       break;
386     }
387
388     cur = GNUNET_new (struct Episode);
389     cur->duration = e_duration;
390     cur->id = e_counter;
391
392     if (GNUNET_OK != load_episode (e, cur, cfg))
393     {
394       GNUNET_free (sec_name);
395       GNUNET_free (cur);
396       return GNUNET_SYSERR;
397     }
398
399     fprintf (stderr, "Found episode %u with duration %s \n",
400         e_counter,
401         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
402
403     /* Update experiment */
404     e->num_episodes ++;
405     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
406     /* Put in linked list */
407     if (NULL == last)
408       e->start = cur;
409     else
410     last->next = cur;
411
412     GNUNET_free (sec_name);
413     e_counter ++;
414     last = cur;
415   }
416   return e_counter;
417 }
418
419 static void
420 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
421 {
422   struct Experiment *e = cls;
423   e->experiment_timeout_task = NULL;
424   fprintf (stderr, "Experiment timeout!\n");
425
426   if (NULL != e->episode_timeout_task)
427   {
428     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
429     e->episode_timeout_task = NULL;
430   }
431
432   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
433       GNUNET_SYSERR);
434 }
435
436 static void
437 enforce_start_send (struct GNUNET_ATS_TEST_Operation *op)
438 {
439   struct BenchmarkPeer *peer;
440   struct BenchmarkPartner *partner;
441
442   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
443   if (NULL == peer)
444   {
445     GNUNET_break (0);
446     return;
447   }
448
449   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
450   if (NULL == partner)
451   {
452     GNUNET_break (0);
453     return;
454   }
455
456   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
457
458   if (NULL != partner->tg)
459   {
460     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
461     GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
462     partner->tg = NULL;
463   }
464
465   partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
466       op->gen_type, op->base_rate, op->max_rate, op->period,
467       GNUNET_TIME_UNIT_FOREVER_REL);
468 }
469
470 static void
471 enforce_stop_send (struct GNUNET_ATS_TEST_Operation *op)
472 {
473   struct BenchmarkPartner *p;
474   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
475   if (NULL == p)
476   {
477     GNUNET_break (0);
478     return;
479   }
480
481   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
482
483   if (NULL != p->tg)
484   {
485     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
486         op->src_id, op->dest_id);
487     GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
488     p->tg = NULL;
489   }
490 }
491
492
493 static void
494 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
495 {
496   struct BenchmarkPeer *peer;
497   struct BenchmarkPartner *partner;
498
499   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
500   if (NULL == peer)
501   {
502     GNUNET_break (0);
503     return;
504   }
505
506   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
507   if (NULL == partner)
508   {
509     GNUNET_break (0);
510     return;
511   }
512
513   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
514
515   if (NULL != partner->pg)
516   {
517     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
518         op->src_id, op->dest_id);
519     GNUNET_ATS_TEST_generate_preferences_stop(partner->pg);
520     partner->pg = NULL;
521   }
522
523   partner->pg = GNUNET_ATS_TEST_generate_preferences_start(peer, partner,
524       op->gen_type, op->base_rate, op->max_rate, op->period, op->frequency,
525       op->pref_type);
526 }
527
528 static void
529 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
530 {
531   struct BenchmarkPartner *p;
532   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
533   if (NULL == p)
534   {
535     GNUNET_break (0);
536     return;
537   }
538
539   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
540
541   if (NULL != p->pg)
542   {
543     fprintf (stderr, "Stopping preference between master %llu slave %llu\n",
544         op->src_id, op->dest_id);
545     GNUNET_ATS_TEST_generate_preferences_stop (p->pg);
546     p->pg = NULL;
547   }
548 }
549
550 static void enforce_episode (struct Episode *ep)
551 {
552   struct GNUNET_ATS_TEST_Operation *cur;
553   for (cur = ep->head; NULL != cur; cur = cur->next)
554   {
555
556     fprintf (stderr, "Enforcing operation: %s [%llu]->[%llu] == %llu\n",
557         print_op (cur->type), cur->src_id, cur->dest_id, cur->base_rate);
558     switch (cur->type) {
559       case START_SEND:
560         enforce_start_send (cur);
561         break;
562       case STOP_SEND:
563         enforce_stop_send (cur);
564         break;
565       case START_PREFERENCE:
566         enforce_start_preference (cur);
567         break;
568       case STOP_PREFERENCE:
569         enforce_stop_preference (cur);
570         break;
571       default:
572         break;
573     }
574   }
575 }
576
577 static void
578 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
579 {
580   struct Experiment *e = cls;
581   e->episode_timeout_task = NULL;
582   if (NULL != e->ep_done_cb)
583     e->ep_done_cb (e->cur);
584
585   /* Scheduling next */
586   e->cur = e->cur->next;
587   if (NULL == e->cur)
588   {
589     /* done */
590     fprintf (stderr, "Last episode done!\n");
591     if (NULL != e->experiment_timeout_task)
592     {
593       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
594       e->experiment_timeout_task = NULL;
595     }
596     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
597     return;
598   }
599
600   fprintf (stderr, "Running episode %u with timeout %s\n",
601       e->cur->id,
602       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
603   enforce_episode(e->cur);
604
605   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
606       &timeout_episode, e);
607 }
608
609
610 void
611 GNUNET_ATS_TEST_experimentation_run (struct Experiment *e,
612     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
613     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
614 {
615   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
616       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
617   e->e_done_cb = e_done_cb;
618   e->ep_done_cb = ep_done_cb;
619   e->start_time = GNUNET_TIME_absolute_get();
620
621   /* Start total time out */
622   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
623       &timeout_experiment, e);
624
625   /* Start */
626   e->cur = e->start;
627   fprintf (stderr, "Running episode %u with timeout %s\n",
628       e->cur->id,
629       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
630   enforce_episode(e->cur);
631   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
632       &timeout_episode, e);
633
634
635 }
636
637
638 struct Experiment *
639 GNUNET_ATS_TEST_experimentation_load (char *filename)
640 {
641   struct Experiment *e;
642   struct GNUNET_CONFIGURATION_Handle *cfg;
643   e = NULL;
644
645   cfg = GNUNET_CONFIGURATION_create();
646   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
647   {
648     fprintf (stderr, "Failed to load `%s'\n", filename);
649     GNUNET_CONFIGURATION_destroy (cfg);
650     return NULL;
651   }
652
653   e = create_experiment ();
654
655   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
656       "name", &e->name))
657   {
658     fprintf (stderr, "Invalid %s", "name");
659     free_experiment (e);
660     return NULL;
661   }
662   else
663     fprintf (stderr, "Experiment name: `%s'\n", e->name);
664
665   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
666       "cfg_file", &e->cfg_file))
667   {
668     fprintf (stderr, "Invalid %s", "cfg_file");
669     free_experiment (e);
670     return NULL;
671   }
672   else
673     fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file);
674
675   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
676       "masters", &e->num_masters))
677   {
678     fprintf (stderr, "Invalid %s", "masters");
679     free_experiment (e);
680     return NULL;
681   }
682   else
683     fprintf (stderr, "Experiment masters: `%llu'\n",
684         e->num_masters);
685
686   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
687       "slaves", &e->num_slaves))
688   {
689     fprintf (stderr, "Invalid %s", "slaves");
690     free_experiment (e);
691     return NULL;
692   }
693   else
694     fprintf (stderr, "Experiment slaves: `%llu'\n",
695         e->num_slaves);
696
697   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
698       "log_freq", &e->log_freq))
699   {
700     fprintf (stderr, "Invalid %s", "log_freq");
701     free_experiment (e);
702     return NULL;
703   }
704   else
705     fprintf (stderr, "Experiment logging frequency: `%s'\n",
706         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
707
708   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
709       "max_duration", &e->max_duration))
710   {
711     fprintf (stderr, "Invalid %s", "max_duration");
712     free_experiment (e);
713     return NULL;
714   }
715   else
716     fprintf (stderr, "Experiment duration: `%s'\n",
717         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
718
719   load_episodes (e, cfg);
720   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
721       e->num_episodes,
722       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
723
724   GNUNET_CONFIGURATION_destroy (cfg);
725   return e;
726 }
727
728 void
729 GNUNET_ATS_TEST_experimentation_stop (struct Experiment *e)
730 {
731   if (NULL != e->experiment_timeout_task)
732   {
733     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
734     e->experiment_timeout_task = NULL;
735   }
736   if (NULL != e->episode_timeout_task)
737   {
738     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
739     e->episode_timeout_task = NULL;
740   }
741   free_experiment (e);
742 }
743
744 /* end of file ats-testing-experiment.c*/
745