glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / ats / gnunet-ats-solver-eval.c
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2010-2013 GNUnet e.V.
4
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your 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  Affero General Public License for more details.
14  */
15 /**
16  * @file ats-tests/ats-testing-experiment.c
17  * @brief ats benchmark: controlled experiment execution
18  * @author Christian Grothoff
19  * @author Matthias Wachs
20  */
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23 #include "gnunet-ats-solver-eval.h"
24 #include "gnunet-service-ats_normalization.h"
25 #include "gnunet-service-ats_preferences.c"
26
27 #define BIG_M_STRING "unlimited"
28
29 /**
30  * Handle for statistics.
31  */
32 struct GNUNET_STATISTICS_Handle *GSA_stats;
33
34
35 static struct Experiment *e;
36
37 static struct LoggingHandle *l;
38
39 static struct SolverHandle *sh;
40
41 static struct TestPeer *peer_head;
42
43 static struct TestPeer *peer_tail;
44
45 static double default_properties[GNUNET_ATS_PropertyCount];
46 static double default_preferences[GNUNET_ATS_PreferenceCount];
47
48 /**
49  * cmd option -e: experiment file
50  */
51 static char *opt_exp_file;
52
53 static char *opt_solver;
54
55 /**
56  * cmd option -l: enable logging
57  */
58 static int opt_log;
59
60 /**
61  * cmd option -p: enable plots
62  */
63 static int opt_save;
64
65 /**
66  * cmd option -v: verbose logs
67  */
68 static int opt_verbose;
69
70 /**
71  * cmd option -p: print logs
72  */
73 static int opt_print;
74
75 /**
76  * cmd option -d: disable normalization
77  */
78 static int opt_disable_normalization;
79
80 static int res;
81
82 static void
83 end_now ();
84
85
86 static char *
87 print_generator_type (enum GeneratorType g)
88 {
89   switch (g) {
90     case GNUNET_ATS_TEST_TG_CONSTANT:
91       return "CONSTANT";
92     case GNUNET_ATS_TEST_TG_LINEAR:
93       return "LINEAR";
94     case GNUNET_ATS_TEST_TG_RANDOM:
95       return "RANDOM";
96     case GNUNET_ATS_TEST_TG_SINUS:
97       return "SINUS";
98     default:
99       return "INVALID";
100       break;
101   }
102 }
103
104
105 static struct TestPeer *
106 find_peer_by_id (int id)
107 {
108   struct TestPeer *cur;
109   for (cur = peer_head; NULL != cur; cur = cur->next)
110     if (cur->id == id)
111       return cur;
112   return NULL;
113 }
114
115 static struct TestPeer *
116 find_peer_by_pid (const struct GNUNET_PeerIdentity *pid)
117 {
118   struct TestPeer *cur;
119   for (cur = peer_head; NULL != cur; cur = cur->next)
120     if (0 == memcmp (&cur->peer_id, pid, sizeof (struct GNUNET_PeerIdentity)))
121       return cur;
122   return NULL;
123 }
124
125 static struct TestAddress *
126 find_address_by_id (struct TestPeer *peer, int aid)
127 {
128   struct TestAddress *cur;
129   for (cur = peer->addr_head; NULL != cur; cur = cur->next)
130     if (cur->aid == aid)
131       return cur;
132   return NULL;
133 }
134
135
136 /**
137  * Logging
138  */
139 void
140 GNUNET_ATS_solver_logging_now (struct LoggingHandle *l)
141 {
142   struct LoggingTimeStep *lts;
143   struct TestPeer *cur;
144   struct TestAddress *cur_addr;
145   struct LoggingPeer *log_p;
146   struct LoggingAddress *log_a;
147   int c;
148
149   lts = GNUNET_new (struct LoggingTimeStep);
150   GNUNET_CONTAINER_DLL_insert_tail(l->head, l->tail, lts);
151   lts->timestamp = GNUNET_TIME_absolute_get();
152   if (NULL == lts->prev)
153     lts->delta = GNUNET_TIME_UNIT_ZERO;
154   else
155     lts->delta = GNUNET_TIME_absolute_get_duration(lts->prev->timestamp);
156
157   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging %llu, delta %llu\n",
158       lts->timestamp.abs_value_us, lts->delta.rel_value_us);
159
160
161   /* Store logging data here */
162   for (cur = peer_head; NULL != cur; cur = cur->next)
163   {
164     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
165                 "Logging peer id %llu\n", cur->id);
166
167     log_p = GNUNET_new (struct LoggingPeer);
168     log_p->id = cur->id;
169     log_p->peer_id = cur->peer_id;
170     log_p->is_requested = cur->is_requested;
171     for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
172     {
173       log_p->pref_abs[c] = cur->pref_abs[c];
174       log_p->pref_norm[c] = cur->pref_norm[c];
175       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
176                   "\t %s = %.2f %.2f [abs/rel]\n",
177                   GNUNET_ATS_print_preference_type(c),
178                   log_p->pref_abs[c], log_p->pref_norm[c]);
179     }
180     GNUNET_CONTAINER_DLL_insert_tail(lts->head, lts->tail, log_p);
181
182     for (cur_addr = cur->addr_head; NULL != cur_addr; cur_addr = cur_addr->next)
183     {
184       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
185                   "Logging peer id %llu address %llu\n",
186                   cur->id, cur_addr->aid);
187       log_a = GNUNET_new (struct LoggingAddress);
188       log_a->aid = cur_addr->aid;
189       log_a->active = cur_addr->ats_addr->active;
190       log_a->network = cur_addr->network;
191       log_a->assigned_bw_in = cur_addr->ats_addr->assigned_bw_in;
192       log_a->assigned_bw_out = cur_addr->ats_addr->assigned_bw_out;
193       for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
194       {
195         log_a->prop_abs[c] = cur_addr->prop_abs[c];
196         log_a->prop_norm[c] = cur_addr->prop_norm[c];
197         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
198                     "\t %s = %.2f %.2f [abs/rel]\n",
199                     GNUNET_ATS_print_property_type(c),
200                     log_a->prop_abs[c],
201                     log_a->prop_norm[c]);
202       }
203       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t Active = %i\n", log_a->active);
204       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\t BW in = %llu\n", log_a->assigned_bw_in);
205       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "\t BW out = %llu\n", log_a->assigned_bw_out);
206
207       GNUNET_CONTAINER_DLL_insert_tail (log_p->addr_head, log_p->addr_tail, log_a);
208     }
209   }
210 }
211
212
213 static void
214 logging_task (void *cls)
215 {
216   struct LoggingHandle *l = cls;
217
218   l->logging_task = NULL;
219   GNUNET_ATS_solver_logging_now (l);
220   l->logging_task = GNUNET_SCHEDULER_add_delayed (l->log_freq,
221                                                   &logging_task,
222                                                   l);
223 }
224
225 struct LoggingHandle *
226 GNUNET_ATS_solver_logging_start (struct GNUNET_TIME_Relative freq)
227 {
228   struct LoggingHandle *l;
229   l = GNUNET_new (struct LoggingHandle);
230
231   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start logging every  %s\n",
232       GNUNET_STRINGS_relative_time_to_string(freq, GNUNET_NO));
233   l->log_freq = freq;
234   l->logging_task = GNUNET_SCHEDULER_add_now (&logging_task, l);
235   return l;
236 }
237
238 void
239 GNUNET_ATS_solver_logging_stop (struct LoggingHandle *l)
240 {
241   if (NULL != l->logging_task)
242     GNUNET_SCHEDULER_cancel (l->logging_task);
243
244   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop logging\n");
245
246   l->logging_task = NULL;
247 }
248
249 static struct LoggingFileHandle *
250 find_logging_file_handle (struct LoggingFileHandle *lf_head,
251     struct LoggingFileHandle *lf_tail,
252     int peer_id, int address_id)
253 {
254   struct LoggingFileHandle *res;
255
256   for (res = lf_head; NULL != res; res = res->next)
257     if ((res->pid == peer_id) && (res->aid == address_id))
258       return res;
259   return NULL;
260
261 }
262
263 void
264 GNUNET_ATS_solver_logging_write_to_disk (struct LoggingHandle *l, int add_time_stamp,
265     char *output_dir)
266 {
267   struct LoggingTimeStep *lts;
268   struct LoggingPeer *log_p;
269   struct LoggingAddress *log_a;
270   struct LoggingFileHandle *lf_head;
271   struct LoggingFileHandle *lf_tail;
272   struct LoggingFileHandle *cur;
273   struct LoggingFileHandle *next;
274   char * filename;
275   char * datastring;
276   char * propstring;
277   char * propstring_tmp;
278   char * prefstring;
279   char * prefstring_tmp;
280   int c;
281   int use_dir;
282
283   use_dir = GNUNET_NO;
284   if (NULL != output_dir)
285   {
286     if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (output_dir))
287     {
288       fprintf (stderr, "Failed to create directory `%s'\n", output_dir);
289       return;
290     }
291     else
292     {
293       fprintf (stderr, "Created directory `%s'\n", output_dir);
294       use_dir = GNUNET_YES;
295     }
296   }
297
298   lf_head = NULL;
299   lf_tail = NULL;
300
301   for (lts = l->head; NULL != lts; lts = lts->next)
302   {
303
304     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing log step %llu\n",
305         (long long unsigned int) lts->timestamp.abs_value_us);
306
307     for (log_p = lts->head; NULL != log_p; log_p = log_p->next)
308     {
309       for (log_a = log_p->addr_head; NULL != log_a; log_a = log_a->next)
310       {
311
312         cur = find_logging_file_handle (lf_head, lf_tail, log_p->id,
313             log_a->aid);
314         if (NULL == cur)
315         {
316           cur = GNUNET_new (struct LoggingFileHandle);
317           cur->aid = log_a->aid;
318           cur->pid = log_p->id;
319
320           if (GNUNET_YES == add_time_stamp)
321             GNUNET_asprintf (&filename, "%s%s%s_%s_p%u_a%u_%llu.log",
322                 (GNUNET_YES == use_dir) ? output_dir : "",
323                 (GNUNET_YES == use_dir) ? DIR_SEPARATOR_STR : "",
324                 e->log_prefix,
325                 opt_solver,
326                 cur->pid,
327                 cur->aid,
328                 l->head->timestamp.abs_value_us);
329           else
330             GNUNET_asprintf (&filename, "%s%s%s_%s_p%u_a%u.log",
331                 (GNUNET_YES == use_dir) ? output_dir : "",
332                 (GNUNET_YES == use_dir) ? DIR_SEPARATOR_STR : "",
333                 e->log_prefix,
334                 opt_solver,
335                 cur->pid,
336                 cur->aid);
337
338           fprintf (stderr, "Add writing log data for peer %llu address %llu to file `%s'\n",
339               cur->pid, cur->aid, filename);
340
341
342           cur->f_hd = GNUNET_DISK_file_open (filename,
343               GNUNET_DISK_OPEN_READWRITE |
344               GNUNET_DISK_OPEN_CREATE |
345               GNUNET_DISK_OPEN_TRUNCATE,
346               GNUNET_DISK_PERM_USER_READ |
347               GNUNET_DISK_PERM_USER_WRITE |
348               GNUNET_DISK_PERM_GROUP_READ |
349               GNUNET_DISK_PERM_OTHER_READ);
350           if (NULL == cur->f_hd)
351           {
352             fprintf (stderr, "Cannot open `%s' to write log data!\n", filename);
353             GNUNET_free (filename);
354             GNUNET_free (cur);
355             goto cleanup;
356           }
357           GNUNET_free (filename);
358           GNUNET_CONTAINER_DLL_insert (lf_head, lf_tail, cur);
359
360           GNUNET_asprintf(&datastring,"#time delta;log duration;peer_requested;addr net; addr_active; bw in; bw out; " \
361               "UTILIZATION_UP [abs/rel]; UTILIZATION_UP; UTILIZATION_DOWN; UTILIZATION_DOWN; " \
362               "UTILIZATION_PAYLOAD_UP; UTILIZATION_PAYLOAD_UP; UTILIZATION_PAYLOAD_DOWN; UTILIZATION_PAYLOAD_DOWN;"\
363               "DELAY; DELAY; " \
364               "DISTANCE ;DISTANCE ; COST_WAN; COST_WAN; COST_LAN; COST_LAN; " \
365               "COST_WLAN; COST_WLAN;COST_BT; COST_BT; PREF BW abs; PREF BW rel; PREF LATENCY abs; PREF LATENCY rel;\n");
366           GNUNET_DISK_file_write (cur->f_hd, datastring, strlen(datastring));
367           GNUNET_free (datastring);
368
369         }
370
371         prefstring = GNUNET_strdup("");
372         for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
373         {
374           /*
375           fprintf(stderr,"\t %s = %.2f %.2f [abs/rel]\n",
376               GNUNET_ATS_print_preference_type(c),
377               log_p->pref_abs[c], log_p->pref_norm[c]);
378            */
379           GNUNET_asprintf(&prefstring_tmp,"%s;%.3f;%.3f",
380               prefstring, log_p->pref_abs[c], log_p->pref_norm[c]);
381
382
383           GNUNET_free (prefstring);
384           prefstring = GNUNET_strdup(prefstring_tmp);
385           GNUNET_free (prefstring_tmp);
386         }
387
388
389         propstring = GNUNET_strdup("");
390         for (c = 1; c < GNUNET_ATS_PropertyCount; c++)
391         {
392           if (GNUNET_ATS_NETWORK_TYPE == c)
393             continue;
394           /*
395           fprintf(stderr, "\t %s = %.2f %.2f [abs/rel]\n",
396               GNUNET_ATS_print_property_type(c),
397               log_a->prop_abs[c], log_a->prop_norm[c]);*/
398           GNUNET_asprintf(&propstring_tmp,"%s%.3f;%.3f;",
399                           propstring,
400                           log_a->prop_abs[c],
401                           log_a->prop_norm[c]);
402           GNUNET_free (propstring);
403           propstring = GNUNET_strdup(propstring_tmp);
404           GNUNET_free (propstring_tmp);
405         }
406         GNUNET_asprintf (&datastring, "%llu;%llu;%u;%u;%i;%u;%u;%s;%s\n",
407             GNUNET_TIME_absolute_get_difference (l->head->timestamp,
408                 lts->timestamp).rel_value_us / 1000, lts->delta,
409             log_p->is_requested, log_a->network, log_a->active,
410             log_a->assigned_bw_in, log_a->assigned_bw_out, propstring,
411             prefstring);
412
413         GNUNET_DISK_file_write (cur->f_hd, datastring, strlen(datastring));
414         GNUNET_free (datastring);
415         GNUNET_free (prefstring);
416         GNUNET_free (propstring);
417       }
418     }
419   }
420
421 cleanup:
422   next = lf_head;
423   for (cur = next; NULL != cur; cur = next)
424   {
425     next = cur->next;
426     GNUNET_CONTAINER_DLL_remove (lf_head, lf_tail, cur);
427     if (NULL != cur->f_hd)
428       GNUNET_DISK_file_close (cur->f_hd);
429     GNUNET_free (cur);
430   }
431
432 }
433
434 void
435 GNUNET_ATS_solver_logging_eval (struct LoggingHandle *l)
436 {
437   struct LoggingTimeStep *lts;
438   struct LoggingPeer *log_p;
439   struct LoggingAddress *log_a;
440   int c;
441
442   for (lts = l->head; NULL != lts; lts = lts->next)
443   {
444     fprintf (stderr, "Log step %llu %llu: \n",
445         (long long unsigned int) lts->timestamp.abs_value_us,
446         (long long unsigned int) lts->delta.rel_value_us);
447
448     for (log_p = lts->head; NULL != log_p; log_p = log_p->next)
449     {
450       fprintf (stderr,"\tLogging peer pid %llu\n", log_p->id);
451       for (c = 1; c < GNUNET_ATS_PreferenceCount; c++)
452       {
453         fprintf(stderr,"\t %s = %.2f %.2f [abs/rel]\n",
454             GNUNET_ATS_print_preference_type(c),
455             log_p->pref_abs[c], log_p->pref_norm[c]);
456       }
457
458       for (log_a = log_p->addr_head; NULL != log_a; log_a = log_a->next)
459       {
460         fprintf (stderr, "\tPeer pid %llu address %llu: %u %u %u\n",
461             log_p->id, log_a->aid, log_a->active,
462             log_a->assigned_bw_in,
463             log_a->assigned_bw_out);
464
465         for (c = 1; c < GNUNET_ATS_PropertyCount; c++)
466         {
467           if (GNUNET_ATS_NETWORK_TYPE == c)
468             continue;
469           fprintf(stderr, "\t %s = %.2f %.2f [abs/rel]\n",
470               GNUNET_ATS_print_property_type(c),
471               log_a->prop_abs[c], log_a->prop_norm[c]);
472         }
473       }
474     }
475   }
476 }
477
478 void
479 GNUNET_ATS_solver_logging_free (struct LoggingHandle *l)
480 {
481   struct LoggingTimeStep *lts_cur;
482   struct LoggingTimeStep *lts_next;
483   struct LoggingPeer *log_p_cur;
484   struct LoggingPeer *log_p_next;
485   struct LoggingAddress *log_a_cur;
486   struct LoggingAddress *log_a_next;
487
488   if (NULL != l->logging_task)
489     GNUNET_SCHEDULER_cancel (l->logging_task);
490   l->logging_task = NULL;
491
492   lts_next = l->head;
493   while (NULL != (lts_cur = lts_next))
494   {
495     lts_next = lts_cur->next;
496
497     log_p_next = lts_cur->head;
498     while (NULL != (log_p_cur = log_p_next))
499     {
500       log_p_next = log_p_cur->next;
501
502       log_a_next = log_p_cur->addr_head;
503       while (NULL != (log_a_cur = log_a_next))
504       {
505         log_a_next = log_a_cur->next;
506
507         GNUNET_CONTAINER_DLL_remove (log_p_cur->addr_head, log_p_cur->addr_tail, log_a_cur);
508         GNUNET_free (log_a_cur);
509       }
510
511       GNUNET_CONTAINER_DLL_remove (lts_cur->head, lts_cur->tail, log_p_cur);
512       GNUNET_free (log_p_cur);
513     }
514
515     GNUNET_CONTAINER_DLL_remove (l->head, l->tail, lts_cur);
516     GNUNET_free (lts_cur);
517   }
518
519   GNUNET_free (l);
520 }
521
522 /**
523  * Property Generators
524  */
525 static struct PropertyGenerator *prop_gen_head;
526 static struct PropertyGenerator *prop_gen_tail;
527
528
529 static double
530 get_property (struct PropertyGenerator *pg)
531 {
532   struct GNUNET_TIME_Relative time_delta;
533   double delta_value;
534   double pref_value;
535
536   /* Calculate the current preference value */
537   switch (pg->type) {
538     case GNUNET_ATS_TEST_TG_CONSTANT:
539       pref_value = pg->base_value;
540       break;
541     case GNUNET_ATS_TEST_TG_LINEAR:
542       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
543       /* Calculate point of time in the current period */
544       time_delta.rel_value_us = time_delta.rel_value_us %
545           pg->duration_period.rel_value_us;
546       delta_value = ((double) time_delta.rel_value_us  /
547           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
548       if ((pg->max_value < pg->base_value) &&
549           ((pg->max_value - pg->base_value) > pg->base_value))
550       {
551         /* This will cause an underflow */
552         GNUNET_break (0);
553       }
554       pref_value = pg->base_value + delta_value;
555       break;
556     case GNUNET_ATS_TEST_TG_RANDOM:
557       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
558           10000 * (pg->max_value - pg->base_value)) / 10000;
559       pref_value = pg->base_value + delta_value;
560       break;
561     case GNUNET_ATS_TEST_TG_SINUS:
562       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
563       /* Calculate point of time in the current period */
564       time_delta.rel_value_us = time_delta.rel_value_us %
565           pg->duration_period.rel_value_us;
566       if ((pg->max_value - pg->base_value) > pg->base_value)
567       {
568         /* This will cause an underflow for second half of sinus period,
569          * will be detected in general when experiments are loaded */
570         GNUNET_break (0);
571       }
572       delta_value = (pg->max_value - pg->base_value) *
573           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
574               time_delta.rel_value_us);
575       pref_value = pg->base_value + delta_value;
576       break;
577     default:
578       pref_value = 0.0;
579       break;
580   }
581   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current property value is %f\n",
582       pref_value);
583   return pref_value;
584 }
585
586
587 static void
588 set_prop_task (void *cls)
589 {
590   struct PropertyGenerator *pg = cls;
591   struct TestPeer *p;
592   struct TestAddress *a;
593   double prop_value;
594   struct GNUNET_ATS_Information atsi;
595
596   pg->set_task = NULL;
597
598   if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains_value (sh->addresses,
599       &pg->test_peer->peer_id, pg->test_address->ats_addr))
600   {
601     GNUNET_break (0);
602     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
603         "Setting property generation for unknown address [%u:%u]\n",
604         pg->peer, pg->address_id);
605     return;
606   }
607   if (NULL == (p = find_peer_by_id (pg->peer)))
608   {
609     GNUNET_break (0);
610     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
611         "Setting property generation for unknown peer %u\n",
612         pg->peer);
613     return;
614   }
615   if (NULL == (a = find_address_by_id (p, pg->address_id)))
616   {
617     GNUNET_break (0);
618     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619         "Setting property generation for unknown peer %u\n",
620         pg->peer);
621     return;
622   }
623
624   prop_value = get_property (pg);
625   a->prop_abs[pg->ats_property] = prop_value;
626
627   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
628       "Setting property for peer [%u] address [%u] for %s to %f\n",
629       pg->peer, pg->address_id,
630       GNUNET_ATS_print_property_type (pg->ats_property), prop_value);
631
632   atsi.type = htonl (pg->ats_property);
633   atsi.value = htonl ((uint32_t) prop_value);
634
635   /* set performance here! */
636   sh->sf->s_bulk_start (sh->sf->cls);
637   if (GNUNET_YES == opt_disable_normalization)
638   {
639     a->prop_abs[pg->ats_property] = prop_value;
640     a->prop_norm[pg->ats_property] = prop_value;
641     sh->sf->s_address_update_property (sh->sf->cls, a->ats_addr,
642         pg->ats_property, prop_value, prop_value);
643   }
644   else
645     GAS_normalization_update_property (pg->test_address->ats_addr, &atsi, 1);
646   sh->sf->s_bulk_stop (sh->sf->cls);
647
648   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
649       &set_prop_task, pg);
650 }
651
652
653 /**
654  * Set ats_property to 0 to find all pgs
655  */
656 static struct PropertyGenerator *
657 find_prop_gen (unsigned int peer, unsigned int address,
658     uint32_t ats_property)
659 {
660   struct PropertyGenerator *cur;
661   for (cur = prop_gen_head; NULL != cur; cur = cur->next)
662     if ((cur->peer == peer) && (cur->address_id == address))
663     {
664       if ((cur->ats_property == ats_property) || (0 == ats_property))
665         return cur;
666     }
667   return NULL;
668 }
669
670 void
671 GNUNET_ATS_solver_generate_property_stop (struct PropertyGenerator *pg)
672 {
673   GNUNET_CONTAINER_DLL_remove (prop_gen_head, prop_gen_tail, pg);
674
675   if (NULL != pg->set_task)
676   {
677     GNUNET_SCHEDULER_cancel (pg->set_task);
678     pg->set_task = NULL;
679   }
680   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
681       "Removing old up preference generator peer [%u] address [%u] `%s'\n",
682       pg->peer, pg->address_id,
683       GNUNET_ATS_print_property_type(pg->ats_property));
684
685   GNUNET_free (pg);
686 }
687
688
689 /**
690  * Generate between the source master and the partner and set property with a
691  * value depending on the generator.
692  *
693  * @param peer source
694  * @param address_id partner
695  * @param test_peer the peer
696  * @param test_address the address
697  * @param type type of generator
698  * @param base_value base value
699  * @param value_rate maximum value
700  * @param period duration of a period of generation (~ 1/frequency)
701  * @param frequency how long to generate property
702  * @param ats_property ATS property to generate
703  * @return the property generator
704  */
705 struct PropertyGenerator *
706 GNUNET_ATS_solver_generate_property_start (unsigned int peer,
707     unsigned int address_id,
708     struct TestPeer *test_peer,
709     struct TestAddress *test_address,
710     enum GeneratorType type,
711     long int base_value,
712     long int value_rate,
713     struct GNUNET_TIME_Relative period,
714     struct GNUNET_TIME_Relative frequency,
715     uint32_t ats_property)
716 {
717   struct PropertyGenerator *pg;
718
719   pg = GNUNET_new (struct PropertyGenerator);
720   GNUNET_CONTAINER_DLL_insert (prop_gen_head, prop_gen_tail, pg);
721   pg->type = type;
722   pg->peer = peer;
723   pg->test_address = test_address;
724   pg->test_peer = test_peer;
725   pg->address_id = address_id;
726   pg->ats_property = ats_property;
727   pg->base_value = base_value;
728   pg->max_value = value_rate;
729   pg->duration_period = period;
730   pg->frequency = frequency;
731   pg->time_start = GNUNET_TIME_absolute_get();
732
733   switch (type) {
734     case GNUNET_ATS_TEST_TG_CONSTANT:
735       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
736           "Setting up %s property generator peer [%u] address [%u] `%s'"\
737           "max %u Bips\n",
738           print_generator_type(type), pg->peer, pg->address_id,
739           GNUNET_ATS_print_property_type (ats_property),
740           base_value);
741       break;
742     case GNUNET_ATS_TEST_TG_LINEAR:
743       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
744           "Setting up %s property generator peer [%u] address [%u] `%s' " \
745           "min %u Bips max %u Bips\n",
746           print_generator_type(type), pg->peer, pg->address_id,
747           GNUNET_ATS_print_property_type(ats_property),
748           base_value, value_rate);
749       break;
750     case GNUNET_ATS_TEST_TG_SINUS:
751       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
752           "Setting up %s property generator peer [%u] address [%u] `%s' "\
753           "baserate %u Bips, amplitude %u Bps\n",
754           print_generator_type(type), pg->peer, pg->address_id,
755           GNUNET_ATS_print_property_type(ats_property),
756           base_value, value_rate);
757       break;
758     case GNUNET_ATS_TEST_TG_RANDOM:
759       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
760           "Setting up %s property generator peer [%u] address [%u] `%s' "\
761           "min %u Bips max %u Bps\n",
762           print_generator_type(type), pg->peer, pg->address_id,
763           GNUNET_ATS_print_property_type(ats_property),
764           base_value, value_rate);
765       break;
766     default:
767       break;
768   }
769
770   pg->set_task = GNUNET_SCHEDULER_add_now (&set_prop_task, pg);
771   return pg;
772 }
773
774
775 /**
776  * Stop all preferences generators
777  */
778 void
779 GNUNET_ATS_solver_generate_property_stop_all ()
780 {
781   struct PropertyGenerator *cur;
782   struct PropertyGenerator *next;
783   next = prop_gen_head;
784   for (cur = next; NULL != cur; cur = next)
785   {
786       next = cur->next;
787       GNUNET_ATS_solver_generate_property_stop (cur);
788   }
789 }
790
791
792 /**
793  * Preference Generators
794  */
795 static struct PreferenceGenerator *pref_gen_head;
796 static struct PreferenceGenerator *pref_gen_tail;
797
798
799 static double
800 get_preference (struct PreferenceGenerator *pg)
801 {
802   struct GNUNET_TIME_Relative time_delta;
803   double delta_value;
804   double pref_value;
805
806   /* Calculate the current preference value */
807   switch (pg->type) {
808     case GNUNET_ATS_TEST_TG_CONSTANT:
809       pref_value = pg->base_value;
810       break;
811     case GNUNET_ATS_TEST_TG_LINEAR:
812       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
813       /* Calculate point of time in the current period */
814       time_delta.rel_value_us = time_delta.rel_value_us %
815           pg->duration_period.rel_value_us;
816       delta_value = ((double) time_delta.rel_value_us  /
817           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
818       if ((pg->max_value < pg->base_value) &&
819           ((pg->max_value - pg->base_value) > pg->base_value))
820       {
821         /* This will cause an underflow */
822         GNUNET_break (0);
823       }
824       pref_value = pg->base_value + delta_value;
825       break;
826     case GNUNET_ATS_TEST_TG_RANDOM:
827       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
828           10000 * (pg->max_value - pg->base_value)) / 10000;
829       pref_value = pg->base_value + delta_value;
830       break;
831     case GNUNET_ATS_TEST_TG_SINUS:
832       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
833       /* Calculate point of time in the current period */
834       time_delta.rel_value_us = time_delta.rel_value_us %
835           pg->duration_period.rel_value_us;
836       if ((pg->max_value - pg->base_value) > pg->base_value)
837       {
838         /* This will cause an underflow for second half of sinus period,
839          * will be detected in general when experiments are loaded */
840         GNUNET_break (0);
841       }
842       delta_value = (pg->max_value - pg->base_value) *
843           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
844               time_delta.rel_value_us);
845       pref_value = pg->base_value + delta_value;
846       break;
847     default:
848       pref_value = 0.0;
849       break;
850   }
851   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n",
852       pref_value);
853   return pref_value;
854 }
855
856
857 static void
858 set_feedback_task (void *cls)
859 {
860   struct PreferenceGenerator *pg = cls;
861   struct TestPeer *p;
862   double feedback;
863   uint32_t bw_acc_out;
864   uint32_t bw_acc_in;
865   uint32_t delay_acc_in;
866   struct GNUNET_TIME_Relative dur;
867   double p_new;
868
869   pg->feedback_task = NULL;
870
871   if (NULL == (p = find_peer_by_id (pg->peer)))
872   {
873     GNUNET_break (0);
874     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
875         "Setting feedback for unknown peer %u\n", pg->peer);
876     return;
877   }
878
879   switch (pg->kind)
880   {
881     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
882       dur = GNUNET_TIME_absolute_get_duration(pg->feedback_last_bw_update);
883       bw_acc_in = dur.rel_value_us *pg->last_assigned_bw_in +  pg->feedback_bw_in_acc;
884       pg->feedback_bw_in_acc = 0;
885
886       bw_acc_out = dur.rel_value_us *pg->last_assigned_bw_out +  pg->feedback_bw_out_acc;
887       p_new = get_preference (pg);
888       feedback  = (p_new / pg->pref_bw_old) * (bw_acc_in + bw_acc_out) /
889           (2 *GNUNET_TIME_absolute_get_duration(pg->feedback_last).rel_value_us);
890
891       break;
892     case GNUNET_ATS_PREFERENCE_LATENCY:
893       dur = GNUNET_TIME_absolute_get_duration(pg->feedback_last_delay_update);
894       delay_acc_in =dur.rel_value_us *pg->last_delay_value +  pg->feedback_delay_acc;
895       pg->feedback_delay_acc = 0;
896
897       p_new = get_preference (pg);
898       feedback  = (p_new / pg->pref_latency_old) * (delay_acc_in) /
899           (GNUNET_TIME_absolute_get_duration(pg->feedback_last).rel_value_us);
900
901       break;
902     default:
903       GNUNET_break (0);
904       feedback = 0.0;
905       break;
906   }
907   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
908       "Giving feedback for peer [%u] for client %p pref %s of %.3f\n",
909       pg->peer, NULL + (pg->client_id),
910       GNUNET_ATS_print_preference_type (pg->kind),
911       feedback);
912
913   sh->sf->s_feedback (sh->sf->cls, NULL + (pg->client_id), &p->peer_id,
914       pg->feedback_frequency, pg->kind, feedback);
915   pg->feedback_last = GNUNET_TIME_absolute_get();
916
917
918   pg->feedback_bw_out_acc = 0;
919   pg->feedback_bw_in_acc = 0;
920   pg->feedback_last_bw_update = GNUNET_TIME_absolute_get();
921
922   pg->feedback_delay_acc = 0;
923   pg->feedback_last_delay_update = GNUNET_TIME_absolute_get();
924
925
926   pg->feedback_task = GNUNET_SCHEDULER_add_delayed (pg->feedback_frequency,
927       &set_feedback_task, pg);
928 }
929
930
931 static void
932 set_pref_task (void *cls)
933 {
934   struct PreferenceGenerator *pg = cls;
935   struct TestPeer *p;
936   double pref_value;
937   pg->set_task = NULL;
938
939   if (NULL == (p = find_peer_by_id (pg->peer)))
940   {
941     GNUNET_break (0);
942     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
943         "Setting preference for unknown peer %u\n", pg->peer);
944     return;
945   }
946
947   pref_value = get_preference (pg);
948   switch (pg->kind) {
949     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
950       pg->pref_bw_old = pref_value;
951       break;
952     case GNUNET_ATS_PREFERENCE_LATENCY:
953       pg->pref_latency_old = pref_value;
954       break;
955     default:
956       break;
957   }
958
959   p->pref_abs[pg->kind] = pref_value;
960
961   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
962       "Setting preference for peer [%u] for client %p pref %s to %f\n",
963       pg->peer, NULL + (pg->client_id),
964       GNUNET_ATS_print_preference_type (pg->kind), pref_value);
965
966   if (GNUNET_YES == opt_disable_normalization)
967   {
968     p->pref_abs[pg->kind] = pref_value;
969     p->pref_norm[pg->kind] = pref_value;
970     sh->sf->s_pref (sh->sf->cls, &p->peer_id, pg->kind, pref_value);
971   }
972   else
973     update_preference (NULL + (pg->client_id),
974                        &p->peer_id,
975                        pg->kind,
976                        pref_value);
977
978   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
979                                                &set_pref_task,
980                                                pg);
981 }
982
983
984 static struct PreferenceGenerator *
985 find_pref_gen (unsigned int peer, enum GNUNET_ATS_PreferenceKind kind)
986 {
987   struct PreferenceGenerator *cur;
988   for (cur = pref_gen_head; NULL != cur; cur = cur->next)
989     if (cur->peer == peer)
990     {
991       if ((cur->kind == kind) || (GNUNET_ATS_PREFERENCE_END == kind))
992         return cur;
993     }
994   return NULL;
995 }
996
997 void
998 GNUNET_ATS_solver_generate_preferences_stop (struct PreferenceGenerator *pg)
999 {
1000   GNUNET_CONTAINER_DLL_remove (pref_gen_head, pref_gen_tail, pg);
1001
1002   if (NULL != pg->feedback_task)
1003   {
1004     GNUNET_SCHEDULER_cancel (pg->feedback_task);
1005     pg->feedback_task = NULL;
1006   }
1007
1008   if (NULL != pg->set_task)
1009   {
1010     GNUNET_SCHEDULER_cancel (pg->set_task);
1011     pg->set_task = NULL;
1012   }
1013   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1014       "Removing old up preference generator peer [%u] `%s'\n",
1015       pg->peer, GNUNET_ATS_print_preference_type(pg->kind));
1016
1017   GNUNET_free (pg);
1018 }
1019
1020
1021 static struct TestAddress*
1022 find_active_address (struct TestPeer *p)
1023 {
1024   struct TestAddress *cur;
1025   for (cur = p->addr_head; NULL != cur; cur = cur->next)
1026     if (GNUNET_YES == cur->ats_addr->active)
1027       return cur;
1028   return NULL;
1029 }
1030
1031
1032 /**
1033  * Generate between the source master and the partner and set property with a
1034  * value depending on the generator.
1035  *
1036  * @param peer source
1037  * @param address_id partner
1038  * @param client_id the client
1039  * @param type type of generator
1040  * @param base_value base value
1041  * @param value_rate maximum value
1042  * @param period duration of a period of generation (~ 1/frequency)
1043  * @param frequency how long to generate property
1044  * @param kind ATS preference to generate
1045  * @param feedback_frequency how often to give feedback
1046  * @return the preference generator
1047  */
1048 struct PreferenceGenerator *
1049 GNUNET_ATS_solver_generate_preferences_start (unsigned int peer,
1050     unsigned int address_id,
1051     unsigned int client_id,
1052     enum GeneratorType type,
1053     long int base_value,
1054     long int value_rate,
1055     struct GNUNET_TIME_Relative period,
1056     struct GNUNET_TIME_Relative frequency,
1057     enum GNUNET_ATS_PreferenceKind kind,
1058     struct GNUNET_TIME_Relative feedback_frequency)
1059 {
1060   struct PreferenceGenerator *pg;
1061   struct TestPeer *p;
1062
1063   if (NULL == (p = find_peer_by_id (peer)))
1064   {
1065     GNUNET_break (0);
1066     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1067         "Starting preference for unknown peer %u\n", peer);
1068     return NULL;
1069   }
1070
1071   pg = GNUNET_new (struct PreferenceGenerator);
1072   GNUNET_CONTAINER_DLL_insert (pref_gen_head, pref_gen_tail, pg);
1073   pg->type = type;
1074   pg->peer = peer;
1075   pg->client_id = client_id;
1076   pg->kind = kind;
1077   pg->base_value = base_value;
1078   pg->max_value = value_rate;
1079   pg->duration_period = period;
1080   pg->frequency = frequency;
1081   pg->time_start = GNUNET_TIME_absolute_get();
1082   pg->feedback_frequency = feedback_frequency;
1083
1084   switch (type) {
1085     case GNUNET_ATS_TEST_TG_CONSTANT:
1086       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1087           "Setting up %s preference generator peer [%u] `%s' max %u Bips\n",
1088           print_generator_type (type), pg->peer,
1089           GNUNET_ATS_print_preference_type(kind),
1090           base_value);
1091       break;
1092     case GNUNET_ATS_TEST_TG_LINEAR:
1093       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1094           "Setting up %s preference generator peer [%u] `%s' min %u Bips max %u Bips\n",
1095           print_generator_type (type), pg->peer, GNUNET_ATS_print_preference_type(kind),
1096           base_value, value_rate);
1097       break;
1098     case GNUNET_ATS_TEST_TG_SINUS:
1099       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1100           "Setting up %s preference generator peer [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
1101           print_generator_type (type), pg->peer, GNUNET_ATS_print_preference_type(kind),
1102           base_value, value_rate);
1103       break;
1104     case GNUNET_ATS_TEST_TG_RANDOM:
1105       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1106           "Setting up %s preference generator peer [%u] `%s' min %u Bips max %u Bps\n",
1107           print_generator_type (type), pg->peer, GNUNET_ATS_print_preference_type(kind),
1108           base_value, value_rate);
1109       break;
1110     default:
1111       break;
1112   }
1113
1114   pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, pg);
1115   if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != feedback_frequency.rel_value_us)
1116   {
1117     struct TestAddress * addr = find_active_address(p);
1118
1119     pg->last_assigned_bw_in = p->assigned_bw_in;
1120     pg->last_assigned_bw_out = p->assigned_bw_out;
1121     pg->feedback_bw_in_acc = 0;
1122     pg->feedback_bw_out_acc = 0;
1123     pg->last_delay_value = addr->prop_norm[GNUNET_ATS_QUALITY_NET_DELAY];
1124     pg->feedback_delay_acc = 0;
1125
1126     pg->feedback_last_bw_update = GNUNET_TIME_absolute_get();
1127     pg->feedback_last_delay_update = GNUNET_TIME_absolute_get();
1128     pg->feedback_last = GNUNET_TIME_absolute_get();
1129     pg->feedback_task = GNUNET_SCHEDULER_add_delayed (feedback_frequency,
1130         &set_feedback_task, pg);
1131   }
1132
1133   return pg;
1134 }
1135
1136
1137
1138 /**
1139  * Stop all preferences generators
1140  */
1141 void
1142 GNUNET_ATS_solver_generate_preferences_stop_all ()
1143 {
1144   struct PreferenceGenerator *cur;
1145   struct PreferenceGenerator *next;
1146   next = pref_gen_head;
1147   for (cur = next; NULL != cur; cur = next)
1148   {
1149       next = cur->next;
1150       GNUNET_ATS_solver_generate_preferences_stop(cur);
1151   }
1152 }
1153
1154
1155
1156 /**
1157  * Experiments
1158  */
1159 static const char *
1160 print_op (enum OperationType op)
1161 {
1162   switch (op) {
1163     case SOLVER_OP_ADD_ADDRESS:
1164       return "ADD_ADDRESS";
1165     case SOLVER_OP_DEL_ADDRESS:
1166       return "DEL_ADDRESS";
1167     case SOLVER_OP_START_SET_PREFERENCE:
1168       return "START_SET_PREFERENCE";
1169     case SOLVER_OP_STOP_SET_PREFERENCE:
1170       return "STOP_STOP_PREFERENCE";
1171     case SOLVER_OP_START_SET_PROPERTY:
1172       return "START_SET_PROPERTY";
1173     case SOLVER_OP_STOP_SET_PROPERTY:
1174       return "STOP_SET_PROPERTY";
1175     case SOLVER_OP_START_REQUEST:
1176       return "START_REQUEST";
1177     case SOLVER_OP_STOP_REQUEST:
1178       return "STOP_REQUEST";
1179     default:
1180       break;
1181   }
1182   return "";
1183 }
1184
1185
1186 static struct Experiment *
1187 create_experiment ()
1188 {
1189   struct Experiment *e;
1190   e = GNUNET_new (struct Experiment);
1191   e->name = NULL;
1192   e->start = NULL;
1193   e->total_duration = GNUNET_TIME_UNIT_ZERO;
1194   return e;
1195 }
1196
1197
1198 static void
1199 free_experiment (struct Experiment *e)
1200 {
1201   struct Episode *cur;
1202   struct Episode *next;
1203   struct GNUNET_ATS_TEST_Operation *cur_o;
1204   struct GNUNET_ATS_TEST_Operation *next_o;
1205
1206   next = e->start;
1207   for (cur = next; NULL != cur; cur = next)
1208   {
1209     next = cur->next;
1210
1211     next_o = cur->head;
1212     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
1213     {
1214       next_o = cur_o->next;
1215       GNUNET_free_non_null (cur_o->address);
1216       GNUNET_free_non_null (cur_o->plugin);
1217       GNUNET_free (cur_o);
1218     }
1219     GNUNET_free (cur);
1220   }
1221
1222   GNUNET_free_non_null (e->name);
1223   GNUNET_free_non_null (e->log_prefix);
1224   GNUNET_free_non_null (e->log_output_dir);
1225   GNUNET_free_non_null (e->cfg_file);
1226   GNUNET_free (e);
1227 }
1228
1229
1230 static int
1231 load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
1232     struct Episode *e,
1233     int op_counter,
1234     char *sec_name,
1235     const struct GNUNET_CONFIGURATION_Handle *cfg)
1236 {
1237   char *op_name;
1238   char *op_network;
1239
1240   /* peer pid */
1241   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1242   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1243       sec_name, op_name, &o->peer_id))
1244   {
1245     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1246         op_counter, "ADD_ADDRESS", op_name);
1247     GNUNET_free (op_name);
1248     return GNUNET_SYSERR;
1249   }
1250   GNUNET_free (op_name);
1251
1252   /* address pid */
1253   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1254   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1255       sec_name, op_name, &o->address_id))
1256   {
1257     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1258         op_counter, "ADD_ADDRESS", op_name);
1259     GNUNET_free (op_name);
1260     return GNUNET_SYSERR;
1261   }
1262   GNUNET_free (op_name);
1263
1264   /* plugin */
1265   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
1266   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1267       sec_name, op_name, &o->plugin))
1268   {
1269     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
1270         op_counter, "ADD_ADDRESS", op_name);
1271     GNUNET_free (op_name);
1272     return GNUNET_SYSERR;
1273   }
1274   GNUNET_free (op_name);
1275
1276   /* address  */
1277   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
1278   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1279       sec_name, op_name, &o->address))
1280   {
1281     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
1282         op_counter, "ADD_ADDRESS", op_name);
1283     GNUNET_free (op_name);
1284     return GNUNET_SYSERR;
1285   }
1286   GNUNET_free (op_name);
1287
1288   /* session */
1289   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
1290   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1291       sec_name, op_name, &o->address_session))
1292   {
1293     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
1294         op_counter, "ADD_ADDRESS", op_name);
1295     GNUNET_free (op_name);
1296     return GNUNET_SYSERR;
1297   }
1298   GNUNET_free (op_name);
1299
1300   /* network */
1301   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
1302   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1303       sec_name, op_name, &op_network))
1304   {
1305     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
1306         op_counter, "ADD_ADDRESS", op_name);
1307     GNUNET_free (op_name);
1308     return GNUNET_SYSERR;
1309   }
1310   else
1311   {
1312     GNUNET_STRINGS_utf8_toupper (op_network,op_network);
1313     if (0 == strcmp(op_network, "UNSPECIFIED"))
1314     {
1315       o->address_network = GNUNET_ATS_NET_UNSPECIFIED;
1316     }
1317     else if (0 == strcmp(op_network, "LOOPBACK"))
1318     {
1319       o->address_network = GNUNET_ATS_NET_LOOPBACK;
1320     }
1321     else if (0 == strcmp(op_network, "LAN"))
1322     {
1323       o->address_network = GNUNET_ATS_NET_LAN;
1324     }
1325     else if (0 == strcmp(op_network, "WAN"))
1326     {
1327       o->address_network = GNUNET_ATS_NET_WAN;
1328     }
1329     else if (0 == strcmp(op_network, "WLAN"))
1330     {
1331       o->address_network = GNUNET_ATS_NET_WLAN;
1332     }
1333     else if (0 == strcmp(op_network, "BT"))
1334     {
1335       o->address_network = GNUNET_ATS_NET_BT;
1336     }
1337     else
1338     {
1339       fprintf (stderr, "Invalid address-network in operation %u `%s' in episode `%s': `%s'\n",
1340           op_counter, "ADD_ADDRESS", op_name, op_network);
1341       GNUNET_free (op_network);
1342       GNUNET_free (op_name);
1343       return GNUNET_SYSERR;
1344     }
1345   }
1346   GNUNET_free (op_network);
1347   GNUNET_free (op_name);
1348
1349   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1350       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
1351       "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
1352
1353   return GNUNET_OK;
1354 }
1355
1356
1357 static int
1358 load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
1359     struct Episode *e,
1360     int op_counter,
1361     char *sec_name,
1362     const struct GNUNET_CONFIGURATION_Handle *cfg)
1363 {
1364   char *op_name;
1365   //char *op_network;
1366
1367   /* peer pid */
1368   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1369   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1370       sec_name, op_name, &o->peer_id))
1371   {
1372     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
1373         op_counter, "DEL_ADDRESS", op_name);
1374     GNUNET_free (op_name);
1375     return GNUNET_SYSERR;
1376   }
1377   GNUNET_free (op_name);
1378
1379   /* address pid */
1380   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1381   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1382       sec_name, op_name, &o->address_id))
1383   {
1384     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1385         op_counter, "DEL_ADDRESS", op_name);
1386     GNUNET_free (op_name);
1387     return GNUNET_SYSERR;
1388   }
1389   GNUNET_free (op_name);
1390
1391 #if 0
1392   /* plugin */
1393   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
1394   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1395       sec_name, op_name, &o->plugin))
1396   {
1397     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
1398         op_counter, "DEL_ADDRESS", op_name);
1399     GNUNET_free (op_name);
1400     return GNUNET_SYSERR;
1401   }
1402   GNUNET_free (op_name);
1403
1404   /* address  */
1405   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
1406   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1407       sec_name, op_name, &o->address))
1408   {
1409     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
1410         op_counter, "DEL_ADDRESS", op_name);
1411     GNUNET_free (op_name);
1412     return GNUNET_SYSERR;
1413   }
1414   GNUNET_free (op_name);
1415
1416   /* session */
1417   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
1418   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1419       sec_name, op_name, &o->address_session))
1420   {
1421     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
1422         op_counter, "DEL_ADDRESS", op_name);
1423     GNUNET_free (op_name);
1424     return GNUNET_SYSERR;
1425   }
1426   GNUNET_free (op_name);
1427 #endif
1428
1429   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1430       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
1431       "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
1432
1433   return GNUNET_OK;
1434 }
1435
1436
1437 static enum GNUNET_ATS_Property
1438 parse_preference_string (const char * str)
1439 {
1440   int c = 0;
1441   char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
1442
1443   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
1444     if (0 == strcmp(str, props[c]))
1445       return c;
1446   return 0;
1447 }
1448
1449
1450 static int
1451 load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1452     struct Episode *e,
1453     int op_counter,
1454     char *sec_name,
1455     const struct GNUNET_CONFIGURATION_Handle *cfg)
1456 {
1457   char *op_name;
1458   char *type;
1459   char *pref;
1460
1461   /* peer pid */
1462   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1463   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1464       sec_name, op_name, &o->peer_id))
1465   {
1466     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1467         op_counter, "START_SET_PREFERENCE", op_name);
1468     GNUNET_free (op_name);
1469     return GNUNET_SYSERR;
1470   }
1471   GNUNET_free (op_name);
1472
1473   /* address pid */
1474   GNUNET_asprintf(&op_name, "op-%u-client-id", op_counter);
1475   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1476       sec_name, op_name, &o->client_id))
1477   {
1478     fprintf (stderr, "Missing client-id in operation %u `%s' in episode `%s'\n",
1479         op_counter, "START_SET_PREFERENCE", op_name);
1480     GNUNET_free (op_name);
1481     return GNUNET_SYSERR;
1482   }
1483   GNUNET_free (op_name);
1484
1485   /* generator */
1486   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
1487   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1488           sec_name, op_name, &type)) )
1489   {
1490     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1491         op_counter, "START_SET_PREFERENCE", op_name);
1492     GNUNET_free (op_name);
1493     return GNUNET_SYSERR;
1494   }
1495
1496   /* Load arguments for set_rate, start_send, set_preference */
1497   if (0 == strcmp (type, "constant"))
1498   {
1499     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1500   }
1501   else if (0 == strcmp (type, "linear"))
1502   {
1503     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1504   }
1505   else if (0 == strcmp (type, "sinus"))
1506   {
1507     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1508   }
1509   else if (0 == strcmp (type, "random"))
1510   {
1511     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1512   }
1513   else
1514   {
1515     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1516         op_counter, op_name, e->id);
1517     GNUNET_free (type);
1518     GNUNET_free (op_name);
1519     return GNUNET_SYSERR;
1520   }
1521   GNUNET_free (type);
1522   GNUNET_free (op_name);
1523
1524
1525   /* Get base rate */
1526   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1527   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1528       sec_name, op_name, &o->base_rate))
1529   {
1530     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1531         op_counter, op_name, e->id);
1532     GNUNET_free (op_name);
1533     return GNUNET_SYSERR;
1534   }
1535   GNUNET_free (op_name);
1536
1537
1538   /* Get max rate */
1539   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1540   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1541       sec_name, op_name, &o->max_rate))
1542   {
1543     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1544         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1545         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1546     {
1547       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1548           op_counter, op_name, e->id);
1549       GNUNET_free (op_name);
1550       return GNUNET_SYSERR;
1551     }
1552   }
1553   GNUNET_free (op_name);
1554
1555   /* Get period */
1556   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1557   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1558       sec_name, op_name, &o->period))
1559   {
1560     o->period = e->duration;
1561   }
1562   GNUNET_free (op_name);
1563
1564   /* Get frequency */
1565   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1566   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1567       sec_name, op_name, &o->frequency))
1568   {
1569       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1570           op_counter, op_name, e->id);
1571       GNUNET_free (op_name);
1572       return GNUNET_SYSERR;
1573   }
1574   GNUNET_free (op_name);
1575
1576   /* Get preference */
1577   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1578   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1579       sec_name, op_name, &pref))
1580   {
1581       fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
1582           op_counter, op_name, e->id);
1583       GNUNET_free (op_name);
1584       return GNUNET_SYSERR;
1585   }
1586
1587   if (0 == (o->pref_type = parse_preference_string(pref)))
1588   {
1589       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1590           op_counter, op_name, e->id);
1591       GNUNET_free (op_name);
1592       GNUNET_free (pref);
1593       return GNUNET_SYSERR;
1594   }
1595   GNUNET_free (pref);
1596   GNUNET_free (op_name);
1597
1598   /* Get feedback delay */
1599   GNUNET_asprintf(&op_name, "op-%u-feedback_delay", op_counter);
1600   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (cfg,
1601       sec_name, op_name, &o->feedback_delay))
1602   {
1603       fprintf (stderr, "Using feedback delay %llu in operation %u `%s' in episode %u\n",
1604           (long long unsigned int) o->feedback_delay.rel_value_us,
1605           op_counter, op_name, e->id);
1606   }
1607   else
1608     o->feedback_delay = GNUNET_TIME_UNIT_FOREVER_REL;
1609   GNUNET_free (op_name);
1610
1611   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1612       "Found operation %s: [%llu:%llu]: %s = %llu\n",
1613       "START_SET_PREFERENCE", o->peer_id, o->address_id,
1614       GNUNET_ATS_print_preference_type(o->pref_type), o->base_rate);
1615
1616   return GNUNET_OK;
1617 }
1618
1619
1620 static int
1621 load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1622     struct Episode *e,
1623     int op_counter,
1624     char *sec_name,
1625     const struct GNUNET_CONFIGURATION_Handle *cfg)
1626 {
1627   char *op_name;
1628   char *pref;
1629
1630   /* peer pid */
1631   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1632   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1633       sec_name, op_name, &o->peer_id))
1634   {
1635     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1636         op_counter, "STOP_SET_PREFERENCE", op_name);
1637     GNUNET_free (op_name);
1638     return GNUNET_SYSERR;
1639   }
1640   GNUNET_free (op_name);
1641
1642   /* address pid */
1643   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1644   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1645       sec_name, op_name, &o->address_id))
1646   {
1647     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1648         op_counter, "STOP_SET_PREFERENCE", op_name);
1649     GNUNET_free (op_name);
1650     return GNUNET_SYSERR;
1651   }
1652   GNUNET_free (op_name);
1653
1654   /* Get preference */
1655   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1656   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1657       sec_name, op_name, &pref))
1658   {
1659     fprintf (stderr, "Missing preference in operation %u `%s' in episode `%s'\n",
1660         op_counter, "STOP_SET_PREFERENCE", op_name);
1661       GNUNET_free (op_name);
1662       return GNUNET_SYSERR;
1663   }
1664
1665   if (0 == (o->pref_type = parse_preference_string(pref)))
1666   {
1667       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1668           op_counter, op_name, e->id);
1669       GNUNET_free (op_name);
1670       GNUNET_free (pref);
1671       return GNUNET_SYSERR;
1672   }
1673   GNUNET_free (pref);
1674   GNUNET_free (op_name);
1675
1676   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1677       "Found operation %s: [%llu:%llu]: %s\n",
1678       "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
1679       GNUNET_ATS_print_preference_type(o->pref_type));
1680   return GNUNET_OK;
1681 }
1682
1683
1684 static enum GNUNET_ATS_Property
1685 parse_property_string (const char *str)
1686 {
1687   enum GNUNET_ATS_Property c;
1688
1689   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
1690     if (0 == strcmp(str,
1691                     GNUNET_ATS_print_property_type (c)))
1692       return c;
1693   return 0;
1694 }
1695
1696
1697 static int
1698 load_op_start_set_property(struct GNUNET_ATS_TEST_Operation *o,
1699     struct Episode *e,
1700     int op_counter,
1701     char *sec_name,
1702     const struct GNUNET_CONFIGURATION_Handle *cfg)
1703 {
1704   char *op_name;
1705   char *type;
1706   char *prop;
1707
1708   /* peer pid */
1709   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1710   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1711       sec_name, op_name, &o->peer_id))
1712   {
1713     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1714         op_counter, "START_SET_PROPERTY", op_name);
1715     GNUNET_free (op_name);
1716     return GNUNET_SYSERR;
1717   }
1718   GNUNET_free (op_name);
1719
1720   /* address pid */
1721   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1722   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1723       sec_name, op_name, &o->address_id))
1724   {
1725     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1726         op_counter, "START_SET_PROPERTY", op_name);
1727     GNUNET_free (op_name);
1728     return GNUNET_SYSERR;
1729   }
1730   GNUNET_free (op_name);
1731
1732   /* generator */
1733   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
1734   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1735           sec_name, op_name, &type)) )
1736   {
1737     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1738         op_counter, "START_SET_PROPERTY", op_name);
1739     GNUNET_free (op_name);
1740     return GNUNET_SYSERR;
1741   }
1742
1743   /* Load arguments for set_rate, start_send, set_preference */
1744   if (0 == strcmp (type, "constant"))
1745   {
1746     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1747   }
1748   else if (0 == strcmp (type, "linear"))
1749   {
1750     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1751   }
1752   else if (0 == strcmp (type, "sinus"))
1753   {
1754     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1755   }
1756   else if (0 == strcmp (type, "random"))
1757   {
1758     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1759   }
1760   else
1761   {
1762     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1763         op_counter, op_name, e->id);
1764     GNUNET_free (type);
1765     GNUNET_free (op_name);
1766     return GNUNET_SYSERR;
1767   }
1768   GNUNET_free (type);
1769   GNUNET_free (op_name);
1770
1771
1772   /* Get base rate */
1773   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1774   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1775       sec_name, op_name, &o->base_rate))
1776   {
1777     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1778         op_counter, op_name, e->id);
1779     GNUNET_free (op_name);
1780     return GNUNET_SYSERR;
1781   }
1782   GNUNET_free (op_name);
1783
1784
1785   /* Get max rate */
1786   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1787   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1788       sec_name, op_name, &o->max_rate))
1789   {
1790     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1791         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1792         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1793     {
1794       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1795           op_counter, op_name, e->id);
1796       GNUNET_free (op_name);
1797       return GNUNET_SYSERR;
1798     }
1799   }
1800   GNUNET_free (op_name);
1801
1802   /* Get period */
1803   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1804   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1805       sec_name, op_name, &o->period))
1806   {
1807     o->period = e->duration;
1808   }
1809   GNUNET_free (op_name);
1810
1811   /* Get frequency */
1812   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1813   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1814       sec_name, op_name, &o->frequency))
1815   {
1816       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1817           op_counter, op_name, e->id);
1818       GNUNET_free (op_name);
1819       return GNUNET_SYSERR;
1820   }
1821   GNUNET_free (op_name);
1822
1823   /* Get preference */
1824   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1825   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1826       sec_name, op_name, &prop))
1827   {
1828       fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n",
1829           op_counter, op_name, e->id);
1830       GNUNET_free (op_name);
1831       GNUNET_free_non_null (prop);
1832       return GNUNET_SYSERR;
1833   }
1834
1835   if (0 == (o->prop_type = parse_property_string(prop)))
1836   {
1837       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1838           op_counter, op_name, e->id);
1839       GNUNET_free (op_name);
1840       GNUNET_free (prop);
1841       return GNUNET_SYSERR;
1842   }
1843
1844   GNUNET_free (prop);
1845   GNUNET_free (op_name);
1846
1847   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1848       "Found operation %s: [%llu:%llu] %s = %llu\n",
1849       "START_SET_PROPERTY", o->peer_id, o->address_id,
1850       GNUNET_ATS_print_property_type (o->prop_type), o->base_rate);
1851
1852   return GNUNET_OK;
1853 }
1854
1855 static int
1856 load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o,
1857     struct Episode *e,
1858     int op_counter,
1859     char *sec_name,
1860     const struct GNUNET_CONFIGURATION_Handle *cfg)
1861 {
1862   char *op_name;
1863   char *pref;
1864
1865   /* peer pid */
1866   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1867   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1868       sec_name, op_name, &o->peer_id))
1869   {
1870     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1871         op_counter, "STOP_SET_PROPERTY", op_name);
1872     GNUNET_free (op_name);
1873     return GNUNET_SYSERR;
1874   }
1875   GNUNET_free (op_name);
1876
1877   /* address pid */
1878   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1879   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1880       sec_name, op_name, &o->address_id))
1881   {
1882     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1883         op_counter, "STOP_SET_PROPERTY", op_name);
1884     GNUNET_free (op_name);
1885     return GNUNET_SYSERR;
1886   }
1887   GNUNET_free (op_name);
1888
1889   /* Get property */
1890   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1891   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1892       sec_name, op_name, &pref))
1893   {
1894     fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n",
1895         op_counter, "STOP_SET_PROPERTY", op_name);
1896       GNUNET_free (op_name);
1897       GNUNET_free_non_null (pref);
1898       return GNUNET_SYSERR;
1899   }
1900
1901   if (0 == (o->prop_type = parse_property_string(pref)))
1902   {
1903       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1904           op_counter, op_name, e->id);
1905       GNUNET_free (op_name);
1906       GNUNET_free_non_null (pref);
1907       return GNUNET_SYSERR;
1908   }
1909
1910   GNUNET_free (pref);
1911   GNUNET_free (op_name);
1912
1913   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1914       "Found operation %s: [%llu:%llu] %s\n",
1915       "STOP_SET_PROPERTY", o->peer_id, o->address_id,
1916       GNUNET_ATS_print_property_type (o->prop_type));
1917
1918   return GNUNET_OK;
1919 }
1920
1921
1922 static int
1923 load_op_start_request (struct GNUNET_ATS_TEST_Operation *o,
1924     struct Episode *e,
1925     int op_counter,
1926     char *sec_name,
1927     const struct GNUNET_CONFIGURATION_Handle *cfg)
1928 {
1929   char *op_name;
1930
1931   /* peer pid */
1932   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1933   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1934       sec_name, op_name, &o->peer_id))
1935   {
1936     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1937         op_counter, "START_REQUEST", op_name);
1938     GNUNET_free (op_name);
1939     return GNUNET_SYSERR;
1940   }
1941   GNUNET_free (op_name);
1942   return GNUNET_OK;
1943 }
1944
1945 static int
1946 load_op_stop_request (struct GNUNET_ATS_TEST_Operation *o,
1947     struct Episode *e,
1948     int op_counter,
1949     char *sec_name,
1950     const struct GNUNET_CONFIGURATION_Handle *cfg)
1951 {
1952   char *op_name;
1953
1954   /* peer pid */
1955   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1956   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1957       sec_name, op_name, &o->peer_id))
1958   {
1959     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1960         op_counter, "STOP_REQUEST", op_name);
1961     GNUNET_free (op_name);
1962     return GNUNET_SYSERR;
1963   }
1964   GNUNET_free (op_name);
1965   return GNUNET_OK;
1966 }
1967
1968
1969 static int
1970 load_episode (struct Experiment *e, struct Episode *cur,
1971     struct GNUNET_CONFIGURATION_Handle *cfg)
1972 {
1973   struct GNUNET_ATS_TEST_Operation *o;
1974   char *sec_name;
1975   char *op_name;
1976   char *op;
1977   int op_counter = 0;
1978   int res;
1979   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Parsing episode %u\n",cur->id);
1980   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
1981
1982   while (1)
1983   {
1984     /* Load operation */
1985     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
1986     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1987         sec_name, op_name, &op))
1988     {
1989       GNUNET_free (op_name);
1990       break;
1991     }
1992     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
1993     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "==== Parsing operation %u: `%s'\n",
1994         cur->id, op_name);
1995
1996     /* operations = set_rate, start_send, stop_send, set_preference */
1997     if (0 == strcmp (op, "address_add"))
1998     {
1999       o->type = SOLVER_OP_ADD_ADDRESS;
2000       res = load_op_add_address (o, cur,
2001           op_counter, sec_name, cfg);
2002     }
2003     else if (0 == strcmp (op, "address_del"))
2004     {
2005       o->type = SOLVER_OP_DEL_ADDRESS;
2006       res = load_op_del_address (o, cur,
2007           op_counter, sec_name, cfg);
2008     }
2009     else if (0 == strcmp (op, "start_set_property"))
2010     {
2011       o->type = SOLVER_OP_START_SET_PROPERTY;
2012       res = load_op_start_set_property (o, cur,
2013           op_counter, sec_name, cfg);
2014     }
2015     else if (0 == strcmp (op, "stop_set_property"))
2016     {
2017       o->type = SOLVER_OP_STOP_SET_PROPERTY;
2018       res = load_op_stop_set_property (o, cur,
2019           op_counter, sec_name, cfg);
2020     }
2021     else if (0 == strcmp (op, "start_set_preference"))
2022     {
2023       o->type = SOLVER_OP_START_SET_PREFERENCE;
2024       res =  load_op_start_set_preference (o, cur,
2025           op_counter, sec_name, cfg);
2026     }
2027     else if (0 == strcmp (op, "stop_set_preference"))
2028     {
2029       o->type = SOLVER_OP_STOP_SET_PREFERENCE;
2030       res =  load_op_stop_set_preference (o, cur,
2031           op_counter, sec_name, cfg);
2032     }
2033     else if (0 == strcmp (op, "start_request"))
2034     {
2035       o->type = SOLVER_OP_START_REQUEST;
2036       res = load_op_start_request (o, cur,
2037           op_counter, sec_name, cfg);
2038     }
2039     else if (0 == strcmp (op, "stop_request"))
2040     {
2041       o->type = SOLVER_OP_STOP_REQUEST;
2042       res = load_op_stop_request(o, cur,
2043           op_counter, sec_name, cfg);
2044     }
2045     else
2046     {
2047       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
2048           op_counter, op, cur->id);
2049       res = GNUNET_SYSERR;
2050     }
2051
2052     GNUNET_free (op);
2053     GNUNET_free (op_name);
2054
2055     if (GNUNET_SYSERR == res)
2056     {
2057       GNUNET_free (o);
2058       GNUNET_free (sec_name);
2059       return GNUNET_SYSERR;
2060     }
2061
2062     GNUNET_CONTAINER_DLL_insert_tail (cur->head,cur->tail, o);
2063     op_counter++;
2064   }
2065   GNUNET_free (sec_name);
2066   return GNUNET_OK;
2067 }
2068
2069 static int
2070 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
2071 {
2072   int e_counter = 0;
2073   char *sec_name;
2074   struct GNUNET_TIME_Relative e_duration;
2075   struct Episode *cur;
2076   struct Episode *last;
2077
2078   e_counter = 0;
2079   last = NULL;
2080   while (1)
2081   {
2082     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
2083     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
2084         sec_name, "duration", &e_duration))
2085     {
2086       GNUNET_free (sec_name);
2087       break;
2088     }
2089
2090     cur = GNUNET_new (struct Episode);
2091     cur->duration = e_duration;
2092     cur->id = e_counter;
2093
2094     if (GNUNET_OK != load_episode (e, cur, cfg))
2095     {
2096       GNUNET_free (sec_name);
2097       GNUNET_free (cur);
2098       return GNUNET_SYSERR;
2099     }
2100
2101     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Found episode %u with duration %s \n",
2102         e_counter,
2103         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
2104
2105     /* Update experiment */
2106     e->num_episodes ++;
2107     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
2108     /* Put in linked list */
2109     if (NULL == last)
2110       e->start = cur;
2111     else
2112       last->next = cur;
2113
2114     GNUNET_free (sec_name);
2115     e_counter ++;
2116     last = cur;
2117   }
2118   return e_counter;
2119 }
2120
2121
2122 static void
2123 timeout_experiment (void *cls)
2124 {
2125   struct Experiment *e = cls;
2126
2127   e->experiment_timeout_task = NULL;
2128   fprintf (stderr, "Experiment timeout!\n");
2129
2130   if (NULL != e->episode_timeout_task)
2131   {
2132     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
2133     e->episode_timeout_task = NULL;
2134   }
2135
2136   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
2137       GNUNET_SYSERR);
2138 }
2139
2140 struct ATS_Address *
2141 create_ats_address (const struct GNUNET_PeerIdentity *peer,
2142                 const char *plugin_name,
2143                 const void *plugin_addr,
2144                 size_t plugin_addr_len,
2145                 uint32_t session_id,
2146                 uint32_t network)
2147 {
2148   struct ATS_Address *aa = NULL;
2149
2150   aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len + strlen (plugin_name) + 1);
2151   aa->atsi = GNUNET_new (struct GNUNET_ATS_Information);
2152   aa->atsi[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
2153   aa->atsi[0].value = htonl (network);
2154   aa->atsi_count = 1;
2155
2156   aa->peer = *peer;
2157   aa->addr_len = plugin_addr_len;
2158   aa->addr = &aa[1];
2159   aa->plugin = (char *) &aa[1] + plugin_addr_len;
2160   GNUNET_memcpy (&aa[1], plugin_addr, plugin_addr_len);
2161   GNUNET_memcpy (aa->plugin, plugin_name, strlen (plugin_name) + 1);
2162   aa->session_id = session_id;
2163
2164   return aa;
2165 }
2166
2167
2168
2169 static void
2170 enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
2171 {
2172   struct TestPeer *p;
2173   struct TestAddress *a;
2174   int c;
2175
2176   if (NULL == (p = find_peer_by_id (op->peer_id)))
2177   {
2178     p = GNUNET_new (struct TestPeer);
2179     p->id = op->peer_id;
2180     p->assigned_bw_in = 0;
2181     p->assigned_bw_out = 0;
2182     memset (&p->peer_id, op->peer_id, sizeof (p->peer_id));
2183     for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
2184     {
2185       p->pref_abs[c] = DEFAULT_ABS_PREFERENCE;
2186       p->pref_norm[c] = DEFAULT_REL_PREFERENCE;
2187     }
2188
2189     GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, p);
2190   }
2191
2192   if (NULL != (find_address_by_id (p, op->address_id)))
2193   {
2194     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Duplicate address %u for peer %u\n",
2195         op->address_id, op->peer_id);
2196     return;
2197   }
2198
2199   a = GNUNET_new (struct TestAddress);
2200   a->aid = op->address_id;
2201   a->network = op->address_network;
2202   a->ats_addr = create_ats_address (&p->peer_id, op->plugin, op->address,
2203       strlen (op->address) + 1, op->address_session, op->address_network);
2204   memset (&p->peer_id, op->peer_id, sizeof (p->peer_id));
2205   GNUNET_CONTAINER_DLL_insert_tail (p->addr_head, p->addr_tail, a);
2206
2207   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
2208     a->prop_norm[c] = DEFAULT_REL_QUALITY;
2209
2210   GNUNET_CONTAINER_multipeermap_put (sh->addresses, &p->peer_id, a->ats_addr,
2211     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2212
2213   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding address %u for peer %u in network `%s'\n",
2214     op->address_id, op->peer_id, GNUNET_ATS_print_network_type(a->network));
2215
2216   sh->sf->s_add (sh->sf->cls, a->ats_addr, op->address_network);
2217
2218 }
2219
2220
2221 static void
2222 enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
2223 {
2224   struct TestPeer *p;
2225   struct TestAddress *a;
2226   struct PropertyGenerator *pg;
2227
2228   if (NULL == (p = find_peer_by_id (op->peer_id)))
2229   {
2230     GNUNET_break (0);
2231     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2232         "Deleting address for unknown peer %u\n", op->peer_id);
2233     return;
2234   }
2235
2236   if (NULL == (a =find_address_by_id (p, op->address_id)))
2237   {
2238     GNUNET_break (0);
2239     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2240         "Deleting address for unknown peer %u\n", op->peer_id);
2241     return;
2242   }
2243
2244   while (NULL != (pg = find_prop_gen (p->id, a->aid, 0)))
2245   {
2246     GNUNET_ATS_solver_generate_property_stop (pg);
2247   }
2248
2249   GNUNET_assert (GNUNET_YES ==
2250                  GNUNET_CONTAINER_multipeermap_remove (sh->addresses,
2251                                                        &p->peer_id,
2252                                                        a->ats_addr));
2253   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2254               "Removing address %u for peer %u\n",
2255               op->address_id,
2256               op->peer_id);
2257
2258   sh->sf->s_del (sh->sf->cls, a->ats_addr);
2259
2260   if (NULL != l)
2261   {
2262     GNUNET_ATS_solver_logging_now (l);
2263   }
2264   GNUNET_CONTAINER_DLL_remove(p->addr_head, p->addr_tail, a);
2265
2266   GNUNET_free_non_null(a->ats_addr->atsi);
2267   GNUNET_free (a->ats_addr);
2268   GNUNET_free (a);
2269
2270 }
2271
2272 static void
2273 enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
2274 {
2275   struct PropertyGenerator *pg;
2276   struct TestPeer *p;
2277   struct TestAddress *a;
2278
2279   if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type)))
2280   {
2281     GNUNET_ATS_solver_generate_property_stop (pg);
2282     GNUNET_free (pg);
2283   }
2284
2285   if (NULL == (p = find_peer_by_id (op->peer_id)))
2286   {
2287     GNUNET_break (0);
2288     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2289         "Starting property generation for unknown peer %u\n", op->peer_id);
2290     return;
2291   }
2292
2293   if (NULL == (a = find_address_by_id (p, op->address_id)))
2294   {
2295     GNUNET_break (0);
2296     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2297         "Setting property for unknown address %u\n", op->peer_id);
2298     return;
2299   }
2300
2301   GNUNET_ATS_solver_generate_property_start (op->peer_id,
2302     op->address_id,
2303     p, a,
2304     op->gen_type,
2305     op->base_rate,
2306     op->max_rate,
2307     op->period,
2308     op->frequency,
2309     op->prop_type);
2310 }
2311
2312 static void
2313 enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
2314 {
2315   struct PropertyGenerator *pg = find_prop_gen(op->peer_id, op->address_id,
2316       op->prop_type);
2317   if (NULL != pg)
2318   {
2319     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2320         "Stopping preference generation for peer %u address %u\n", op->peer_id,
2321         op->address_id);
2322     GNUNET_ATS_solver_generate_property_stop (pg);
2323   }
2324   else
2325   {
2326     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2327         "Cannot find preference generator for peer %u address %u\n",
2328         op->peer_id, op->address_id);
2329     GNUNET_break (0);
2330   }
2331 }
2332
2333 static void
2334 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
2335 {
2336   struct PreferenceGenerator *pg;
2337   if (NULL != (pg = find_pref_gen (op->peer_id, op->pref_type)))
2338   {
2339     GNUNET_ATS_solver_generate_preferences_stop (pg);
2340     GNUNET_free (pg);
2341   }
2342
2343   if (NULL == (find_peer_by_id (op->peer_id)))
2344   {
2345     GNUNET_break (0);
2346     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2347         "Starting preference generation for unknown peer %u\n", op->peer_id);
2348     return;
2349   }
2350
2351   GNUNET_ATS_solver_generate_preferences_start (op->peer_id,
2352     op->address_id,
2353     op->client_id,
2354     op->gen_type,
2355     op->base_rate,
2356     op->max_rate,
2357     op->period,
2358     op->frequency,
2359     op->pref_type,
2360     op->frequency);
2361 }
2362
2363 static void
2364 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
2365 {
2366   struct PreferenceGenerator *pg = find_pref_gen(op->peer_id,
2367       op->pref_type);
2368   if (NULL != pg)
2369   {
2370     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2371         "Stopping property generation for peer %u address %u\n", op->peer_id,
2372         op->address_id);
2373     GNUNET_ATS_solver_generate_preferences_stop (pg);
2374   }
2375   else
2376   {
2377     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2378         "Cannot find preference generator for peer %u address %u\n",
2379         op->peer_id, op->address_id);
2380     GNUNET_break (0);
2381   }
2382 }
2383
2384
2385 static void
2386 enforce_start_request (struct GNUNET_ATS_TEST_Operation *op)
2387 {
2388   struct TestPeer *p;
2389
2390   if (NULL == (p = find_peer_by_id (op->peer_id)))
2391   {
2392     GNUNET_break (0);
2393     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2394         "Requesting address for unknown peer %u\n", op->peer_id);
2395     return;
2396   }
2397
2398   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting address for peer %u\n",
2399       op->peer_id);
2400   p->is_requested = GNUNET_YES;
2401
2402   sh->sf->s_get (sh->sf->cls, &p->peer_id);
2403 }
2404
2405
2406 static void
2407 enforce_stop_request (struct GNUNET_ATS_TEST_Operation *op)
2408 {
2409   struct TestPeer *p;
2410
2411   if (NULL == (p = find_peer_by_id (op->peer_id)))
2412   {
2413     GNUNET_break (0);
2414     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2415         "Requesting address for unknown peer %u\n", op->peer_id);
2416     return;
2417   }
2418
2419   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2420               "Stop requesting address for peer %u\n",
2421               op->peer_id);
2422   p->is_requested = GNUNET_NO;
2423   p->assigned_bw_in = 0;
2424   p->assigned_bw_out = 0;
2425   sh->sf->s_get_stop (sh->sf->cls, &p->peer_id);
2426
2427   if (NULL != l)
2428   {
2429     GNUNET_ATS_solver_logging_now (l);
2430   }
2431
2432 }
2433
2434 static void enforce_episode (struct Episode *ep)
2435 {
2436   struct GNUNET_ATS_TEST_Operation *cur;
2437   for (cur = ep->head; NULL != cur; cur = cur->next)
2438   {
2439     switch (cur->type) {
2440       case SOLVER_OP_ADD_ADDRESS:
2441         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
2442             print_op (cur->type), cur->peer_id, cur->address_id);
2443         enforce_add_address (cur);
2444         break;
2445       case SOLVER_OP_DEL_ADDRESS:
2446         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
2447             print_op (cur->type), cur->peer_id, cur->address_id);
2448         enforce_del_address (cur);
2449         break;
2450       case SOLVER_OP_START_SET_PROPERTY:
2451         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2452             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2453         enforce_start_property (cur);
2454         break;
2455       case SOLVER_OP_STOP_SET_PROPERTY:
2456         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2457             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2458         enforce_stop_property (cur);
2459         break;
2460       case SOLVER_OP_START_SET_PREFERENCE:
2461         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2462             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2463         enforce_start_preference (cur);
2464         break;
2465       case SOLVER_OP_STOP_SET_PREFERENCE:
2466         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2467             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2468         enforce_stop_preference (cur);
2469         break;
2470       case SOLVER_OP_START_REQUEST:
2471         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
2472             print_op (cur->type), cur->peer_id);
2473         enforce_start_request (cur);
2474         break;
2475       case SOLVER_OP_STOP_REQUEST:
2476         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
2477             print_op (cur->type), cur->peer_id);
2478         enforce_stop_request (cur);
2479         break;
2480       default:
2481         break;
2482     }
2483   }
2484 }
2485
2486
2487 static void
2488 timeout_episode (void *cls)
2489 {
2490   struct Experiment *e = cls;
2491
2492   e->episode_timeout_task = NULL;
2493   if (NULL != e->ep_done_cb)
2494     e->ep_done_cb (e->cur);
2495
2496   /* Scheduling next */
2497   e->cur = e->cur->next;
2498   if (NULL == e->cur)
2499   {
2500     /* done */
2501     fprintf (stderr, "Last episode done!\n");
2502     if (NULL != e->experiment_timeout_task)
2503     {
2504       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
2505       e->experiment_timeout_task = NULL;
2506     }
2507     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
2508     return;
2509   }
2510
2511   fprintf (stderr, "Running episode %u with timeout %s\n",
2512       e->cur->id,
2513       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
2514   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
2515       &timeout_episode, e);
2516   enforce_episode(e->cur);
2517
2518
2519 }
2520
2521
2522 void
2523 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
2524     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
2525     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
2526 {
2527   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
2528       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
2529   e->e_done_cb = e_done_cb;
2530   e->ep_done_cb = ep_done_cb;
2531   e->start_time = GNUNET_TIME_absolute_get();
2532
2533   /* Start total time out */
2534   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
2535       &timeout_experiment, e);
2536
2537   /* Start */
2538   if (NULL == e->start)
2539   {
2540     GNUNET_break (0);
2541     return;
2542   }
2543
2544   e->cur = e->start;
2545   fprintf (stderr, "Running episode %u with timeout %s\n",
2546       e->cur->id,
2547       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
2548   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
2549       &timeout_episode, e);
2550   enforce_episode(e->cur);
2551
2552 }
2553
2554 void
2555 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
2556 {
2557   if (NULL != e->experiment_timeout_task)
2558   {
2559     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
2560     e->experiment_timeout_task = NULL;
2561   }
2562   if (NULL != e->episode_timeout_task)
2563   {
2564     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
2565     e->episode_timeout_task = NULL;
2566   }
2567   if (NULL != e->cfg)
2568   {
2569     GNUNET_CONFIGURATION_destroy(e->cfg);
2570     e->cfg = NULL;
2571   }
2572   free_experiment (e);
2573 }
2574
2575
2576 struct Experiment *
2577 GNUNET_ATS_solvers_experimentation_load (char *filename)
2578 {
2579   struct Experiment *e;
2580   struct GNUNET_CONFIGURATION_Handle *cfg;
2581   e = NULL;
2582
2583   cfg = GNUNET_CONFIGURATION_create();
2584   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
2585   {
2586     fprintf (stderr, "Failed to load `%s'\n", filename);
2587     GNUNET_CONFIGURATION_destroy (cfg);
2588     return NULL;
2589   }
2590
2591   e = create_experiment ();
2592
2593   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
2594       "name", &e->name))
2595   {
2596     fprintf (stderr, "Invalid %s \n", "name");
2597     free_experiment (e);
2598     return NULL;
2599   }
2600   else
2601     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment name: `%s'\n", e->name);
2602
2603   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
2604       "log_prefix", &e->log_prefix))
2605   {
2606     fprintf (stderr, "Invalid %s \n", "log_prefix");
2607     free_experiment (e);
2608     return NULL;
2609   }
2610   else
2611     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging prefix: `%s'\n",
2612         e->log_prefix);
2613
2614   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
2615       "log_output_dir", &e->log_output_dir))
2616   {
2617     e->log_output_dir = NULL;
2618   }
2619   else
2620     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging output directory: `%s'\n",
2621         e->log_output_dir);
2622
2623
2624   if (GNUNET_SYSERR == (e->log_append_time_stamp = GNUNET_CONFIGURATION_get_value_yesno(cfg,
2625       "experiment", "log_append_time_stamp")))
2626     e->log_append_time_stamp = GNUNET_YES;
2627   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging append timestamp: `%s'\n",
2628       (GNUNET_YES == e->log_append_time_stamp) ? "yes" : "no");
2629
2630
2631   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
2632       "cfg_file", &e->cfg_file))
2633   {
2634     fprintf (stderr, "Invalid %s \n", "cfg_file");
2635     free_experiment (e);
2636     return NULL;
2637   }
2638   else
2639   {
2640     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment configuration: `%s'\n", e->cfg_file);
2641     e->cfg = GNUNET_CONFIGURATION_create();
2642     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
2643     {
2644       fprintf (stderr, "Invalid configuration %s \n", "cfg_file");
2645       free_experiment (e);
2646       return NULL;
2647     }
2648
2649   }
2650
2651   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2652       "log_freq", &e->log_freq))
2653   {
2654     fprintf (stderr, "Invalid %s \n", "log_freq");
2655     free_experiment (e);
2656     return NULL;
2657   }
2658   else
2659     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging frequency: `%s'\n",
2660         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
2661
2662   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2663       "max_duration", &e->max_duration))
2664   {
2665     fprintf (stderr, "Invalid %s", "max_duration");
2666     free_experiment (e);
2667     return NULL;
2668   }
2669   else
2670     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment duration: `%s'\n",
2671         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
2672
2673   if (GNUNET_SYSERR == load_episodes (e, cfg))
2674   {
2675     GNUNET_ATS_solvers_experimentation_stop (e);
2676     GNUNET_CONFIGURATION_destroy (cfg);
2677     e = NULL;
2678     fprintf (stderr, "Failed to load experiment\n");
2679     return NULL;
2680   }
2681   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loaded %u episodes with total duration %s\n",
2682       e->num_episodes,
2683       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
2684
2685   GNUNET_CONFIGURATION_destroy (cfg);
2686   return e;
2687 }
2688
2689
2690
2691 /**
2692  * Solver
2693  */
2694
2695 static int
2696 free_all_it (void *cls,
2697     const struct GNUNET_PeerIdentity *key,
2698     void *value)
2699 {
2700   struct ATS_Address *address = value;
2701   GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (sh->env.addresses,
2702       key, value));
2703   GNUNET_free (address);
2704
2705   return GNUNET_OK;
2706 }
2707
2708 void
2709 GNUNET_ATS_solvers_solver_stop (struct SolverHandle *sh)
2710 {
2711  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
2712      GNUNET_NO);
2713  GNUNET_PLUGIN_unload (sh->plugin, sh->sf);
2714  sh->sf = NULL;
2715  GAS_normalization_stop();
2716
2717  GNUNET_CONTAINER_multipeermap_iterate (sh->addresses,
2718                                         &free_all_it,
2719                                         NULL);
2720  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
2721  GNUNET_free (sh->plugin);
2722  GNUNET_free (sh);
2723 }
2724
2725
2726 /**
2727  * Load quotas for networks from configuration
2728  *
2729  * @param cfg configuration handle
2730  * @param out_dest where to write outbound quotas
2731  * @param in_dest where to write inbound quotas
2732  * @param dest_length length of inbound and outbound arrays
2733  * @return number of networks loaded
2734  */
2735 unsigned int
2736 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
2737                                                  unsigned long long *out_dest,
2738                                                  unsigned long long *in_dest,
2739                                                  int dest_length)
2740 {
2741   char * entry_in = NULL;
2742   char * entry_out = NULL;
2743   char * quota_out_str;
2744   char * quota_in_str;
2745   int c;
2746   int res;
2747
2748   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
2749   {
2750     in_dest[c] = 0;
2751     out_dest[c] = 0;
2752     GNUNET_asprintf (&entry_out,
2753                      "%s_QUOTA_OUT",
2754                      GNUNET_ATS_print_network_type (c));
2755     GNUNET_asprintf (&entry_in,
2756                      "%s_QUOTA_IN",
2757                      GNUNET_ATS_print_network_type (c));
2758
2759     /* quota out */
2760     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
2761     {
2762       res = GNUNET_NO;
2763       if (0 == strcmp(quota_out_str, BIG_M_STRING))
2764       {
2765         out_dest[c] = GNUNET_ATS_MaxBandwidth;
2766         res = GNUNET_YES;
2767       }
2768       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
2769         res = GNUNET_YES;
2770       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
2771          res = GNUNET_YES;
2772
2773       if (GNUNET_NO == res)
2774       {
2775           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2776                       _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2777                       GNUNET_ATS_print_network_type (c),
2778                       quota_out_str,
2779                       GNUNET_ATS_DefaultBandwidth);
2780           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2781       }
2782       else
2783       {
2784           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2785                       "Outbound quota configure for network `%s' is %llu\n",
2786                       GNUNET_ATS_print_network_type (c),
2787                       out_dest[c]);
2788       }
2789       GNUNET_free (quota_out_str);
2790     }
2791     else
2792     {
2793       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2794                   _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
2795                   GNUNET_ATS_print_network_type (c),
2796                   GNUNET_ATS_DefaultBandwidth);
2797       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2798     }
2799
2800     /* quota in */
2801     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
2802     {
2803       res = GNUNET_NO;
2804       if (0 == strcmp(quota_in_str, BIG_M_STRING))
2805       {
2806         in_dest[c] = GNUNET_ATS_MaxBandwidth;
2807         res = GNUNET_YES;
2808       }
2809       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
2810         res = GNUNET_YES;
2811       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
2812          res = GNUNET_YES;
2813
2814       if (GNUNET_NO == res)
2815       {
2816           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2817                       _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2818                       GNUNET_ATS_print_network_type (c),
2819                       quota_in_str,
2820                       GNUNET_ATS_DefaultBandwidth);
2821           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
2822       }
2823       else
2824       {
2825           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2826                       "Inbound quota configured for network `%s' is %llu\n",
2827                       GNUNET_ATS_print_network_type (c),
2828                       in_dest[c]);
2829       }
2830       GNUNET_free (quota_in_str);
2831     }
2832     else
2833     {
2834       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2835                   _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
2836                   GNUNET_ATS_print_network_type (c),
2837                   GNUNET_ATS_DefaultBandwidth);
2838       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2839     }
2840     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2841                 "Loaded quota for network `%s' (in/out): %llu %llu\n",
2842                 GNUNET_ATS_print_network_type (c),
2843                 in_dest[c],
2844                 out_dest[c]);
2845     GNUNET_free (entry_out);
2846     GNUNET_free (entry_in);
2847   }
2848   return GNUNET_ATS_NetworkTypeCount;
2849 }
2850
2851
2852 /**
2853  * Information callback for the solver
2854  *
2855  * @param cls the closure
2856  * @param op the solver operation
2857  * @param stat status of the solver operation
2858  * @param add additional solver information
2859  */
2860 static void
2861 solver_info_cb (void *cls,
2862                 enum GAS_Solver_Operation op,
2863                 enum GAS_Solver_Status stat,
2864                 enum GAS_Solver_Additional_Information add)
2865 {
2866   char *add_info;
2867   switch (add) {
2868     case GAS_INFO_NONE:
2869       add_info = "GAS_INFO_NONE";
2870       break;
2871     case GAS_INFO_FULL:
2872       add_info = "GAS_INFO_MLP_FULL";
2873       break;
2874     case GAS_INFO_UPDATED:
2875       add_info = "GAS_INFO_MLP_UPDATED";
2876       break;
2877     case GAS_INFO_PROP_ALL:
2878       add_info = "GAS_INFO_PROP_ALL";
2879       break;
2880     case GAS_INFO_PROP_SINGLE:
2881       add_info = "GAS_INFO_PROP_SINGLE";
2882       break;
2883     default:
2884       add_info = "INVALID";
2885       break;
2886   }
2887
2888   switch (op)
2889   {
2890     case GAS_OP_SOLVE_START:
2891       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2892           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
2893           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2894       return;
2895     case GAS_OP_SOLVE_STOP:
2896       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2897           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
2898           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2899       return;
2900
2901     case GAS_OP_SOLVE_SETUP_START:
2902       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2903           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
2904           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2905       return;
2906
2907     case GAS_OP_SOLVE_SETUP_STOP:
2908       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2909           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
2910           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2911       return;
2912
2913     case GAS_OP_SOLVE_MLP_LP_START:
2914       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2915           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
2916           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2917       return;
2918     case GAS_OP_SOLVE_MLP_LP_STOP:
2919       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2920           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
2921           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2922       return;
2923
2924     case GAS_OP_SOLVE_MLP_MLP_START:
2925       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2926           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
2927           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2928       return;
2929     case GAS_OP_SOLVE_MLP_MLP_STOP:
2930       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2931           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
2932           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2933       return;
2934     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
2935       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2936           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
2937           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2938       return;
2939     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
2940       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2941           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
2942           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2943       return;
2944     default:
2945       break;
2946     }
2947 }
2948
2949 static void
2950 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
2951 {
2952   struct GNUNET_TIME_Relative duration;
2953   struct TestPeer *p;
2954   static struct PreferenceGenerator *pg;
2955   uint32_t delta;
2956   if ( (0 == address->assigned_bw_out) && (0 == address->assigned_bw_in) )
2957   {
2958     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2959                 "Solver notified to disconnect peer `%s'\n",
2960                 GNUNET_i2s (&address->peer));
2961   }
2962   p = find_peer_by_pid(&address->peer);
2963   if (NULL == p)
2964     return;
2965   p->assigned_bw_out = address->assigned_bw_out;
2966   p->assigned_bw_in = address->assigned_bw_in;
2967
2968   for (pg = pref_gen_head; NULL != pg; pg = pg->next)
2969   {
2970     if (pg->peer == p->id)
2971     {
2972       duration = GNUNET_TIME_absolute_get_duration(pg->feedback_last_bw_update);
2973       delta = duration.rel_value_us * pg->last_assigned_bw_out;
2974       pg->feedback_bw_out_acc += delta;
2975
2976       delta = duration.rel_value_us * pg->last_assigned_bw_in;
2977       pg->feedback_bw_in_acc += delta;
2978
2979       pg->last_assigned_bw_in = address->assigned_bw_in;
2980       pg->last_assigned_bw_out = address->assigned_bw_out;
2981       pg->feedback_last_bw_update = GNUNET_TIME_absolute_get();
2982     }
2983   }
2984
2985   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2986       "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
2987       GNUNET_i2s (&address->peer),
2988       address,
2989       address->assigned_bw_out,
2990           address->assigned_bw_in);
2991
2992   if (NULL != l)
2993     GNUNET_ATS_solver_logging_now (l);
2994
2995   return;
2996 }
2997
2998 const double *
2999 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
3000 {
3001   struct TestPeer *p;
3002   if (GNUNET_YES == opt_disable_normalization)
3003   {
3004     if (NULL == (p = find_peer_by_pid (id)))
3005       return NULL;
3006     return p->pref_abs;
3007   }
3008   else
3009     return GAS_preference_get_by_peer (NULL,
3010                                        id);
3011 }
3012
3013
3014 struct SolverHandle *
3015 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
3016 {
3017   struct SolverHandle *sh;
3018   char * solver_str;
3019
3020   switch (type) {
3021     case GNUNET_ATS_SOLVER_PROPORTIONAL:
3022       solver_str = "proportional";
3023       break;
3024     case GNUNET_ATS_SOLVER_MLP:
3025       solver_str = "mlp";
3026       break;
3027     case GNUNET_ATS_SOLVER_RIL:
3028       solver_str = "ril";
3029       break;
3030     default:
3031       GNUNET_break (0);
3032       return NULL;
3033       break;
3034   }
3035
3036   sh = GNUNET_new (struct SolverHandle);
3037   GNUNET_asprintf (&sh->plugin,
3038                    "libgnunet_plugin_ats_%s",
3039                    solver_str);
3040   sh->addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
3041
3042   /* setup environment */
3043   sh->env.cfg = e->cfg;
3044   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
3045   sh->env.addresses = sh->addresses;
3046   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
3047   sh->env.get_preferences = &get_preferences_cb;
3048   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
3049   sh->env.info_cb = &solver_info_cb;
3050   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
3051
3052   /* start normalization */
3053   GAS_normalization_start ();
3054
3055   /* load quotas */
3056   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
3057       sh->env.out_quota, sh->env.in_quota, GNUNET_ATS_NetworkTypeCount))
3058   {
3059     GNUNET_break(0);
3060     GNUNET_free (sh->plugin);
3061     GNUNET_free (sh);
3062     end_now ();
3063     return NULL;
3064   }
3065
3066   sh->sf = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
3067   if (NULL == sh->sf)
3068   {
3069     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
3070     GNUNET_break(0);
3071     GNUNET_free (sh->plugin);
3072     GNUNET_free (sh);
3073     end_now ();
3074     return NULL;
3075   }
3076   return sh;
3077 }
3078
3079
3080 static void
3081 done ()
3082 {
3083   struct TestPeer *cur;
3084   struct TestPeer *next;
3085
3086   struct TestAddress *cur_a;
3087   struct TestAddress *next_a;
3088
3089   /* Stop logging */
3090   GNUNET_ATS_solver_logging_stop (l);
3091
3092   /* Stop all preference generation */
3093   GNUNET_ATS_solver_generate_preferences_stop_all ();
3094
3095   /* Stop all property generation */
3096   GNUNET_ATS_solver_generate_property_stop_all ();
3097
3098   if (opt_print)
3099   {
3100     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Printing log information \n");
3101     GNUNET_ATS_solver_logging_eval (l);
3102   }
3103   if (opt_save)
3104   {
3105     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Saving log information \n");
3106     GNUNET_ATS_solver_logging_write_to_disk (l, e->log_append_time_stamp,
3107         e->log_output_dir);
3108   }
3109
3110   if (NULL != l)
3111   {
3112     GNUNET_ATS_solver_logging_free (l);
3113     l = NULL;
3114   }
3115
3116   /* Clean up experiment */
3117   if (NULL != e)
3118   {
3119     GNUNET_ATS_solvers_experimentation_stop (e);
3120     e = NULL;
3121   }
3122
3123   next = peer_head;
3124   while  (NULL != (cur = next))
3125   {
3126     next = cur->next;
3127     GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, cur);
3128     next_a = cur->addr_head;
3129     while  (NULL != (cur_a = next_a))
3130     {
3131       next_a = cur_a->next;
3132       GNUNET_CONTAINER_DLL_remove (cur->addr_head, cur->addr_tail, cur_a);
3133       GNUNET_free (cur_a);
3134     }
3135     GNUNET_free (cur);
3136   }
3137   if (NULL != sh)
3138   {
3139     GNUNET_ATS_solvers_solver_stop (sh);
3140     sh = NULL;
3141   }
3142
3143   /* Shutdown */
3144   end_now();
3145 }
3146
3147 static void
3148 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
3149 {
3150   if (GNUNET_OK == success)
3151     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
3152         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
3153   else
3154     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
3155
3156   GNUNET_SCHEDULER_add_now (&done, NULL);
3157 }
3158
3159 static void
3160 episode_done_cb (struct Episode *ep)
3161 {
3162   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
3163 }
3164
3165
3166
3167 /**
3168  * Do shutdown
3169  */
3170 static void
3171 end_now ()
3172 {
3173   if (NULL != e)
3174   {
3175     GNUNET_ATS_solvers_experimentation_stop (e);
3176     e = NULL;
3177   }
3178   if (NULL != sh)
3179   {
3180     GNUNET_ATS_solvers_solver_stop (sh);
3181     sh = NULL;
3182   }
3183 }
3184
3185 static void
3186 run (void *cls, char * const *args, const char *cfgfile,
3187     const struct GNUNET_CONFIGURATION_Handle *cfg)
3188 {
3189   enum GNUNET_ATS_Solvers solver;
3190   int c;
3191
3192   if (NULL == opt_exp_file)
3193   {
3194     fprintf (stderr, "No experiment given ...\n");
3195     res = 1;
3196     end_now ();
3197     return;
3198   }
3199
3200   if (NULL == opt_solver)
3201   {
3202     fprintf (stderr, "No solver given ...\n");
3203     res = 1;
3204     end_now ();
3205     return;
3206   }
3207
3208   if (0 == strcmp(opt_solver, "mlp"))
3209   {
3210     solver = GNUNET_ATS_SOLVER_MLP;
3211   }
3212   else if (0 == strcmp(opt_solver, "proportional"))
3213   {
3214     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
3215   }
3216   else if (0 == strcmp(opt_solver, "ril"))
3217   {
3218     solver = GNUNET_ATS_SOLVER_RIL;
3219   }
3220   else
3221   {
3222     fprintf (stderr, "No solver given ...");
3223     res = 1;
3224     end_now ();
3225     return;
3226   }
3227
3228   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
3229     default_properties[c] = DEFAULT_REL_QUALITY;
3230
3231   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
3232     default_preferences[c] = DEFAULT_REL_PREFERENCE;
3233
3234   /* load experiment */
3235   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading experiment\n");
3236   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
3237   if (NULL == e)
3238   {
3239     fprintf (stderr, "Failed to load experiment ...\n");
3240     res = 1;
3241     end_now ();
3242     return;
3243   }
3244
3245   /* load solver */
3246   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading solver\n");
3247   sh = GNUNET_ATS_solvers_solver_start (solver);
3248   if (NULL == sh)
3249   {
3250     fprintf (stderr, "Failed to start solver ...\n");
3251     end_now ();
3252     res = 1;
3253     return;
3254   }
3255
3256   /* start logging */
3257   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Start logging \n");
3258   l = GNUNET_ATS_solver_logging_start (e->log_freq);
3259
3260   /* run experiment */
3261   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Running experiment \n");
3262   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
3263       experiment_done_cb);
3264
3265   /* WAIT */
3266 }
3267
3268
3269 /**
3270  * Main function of the benchmark
3271  *
3272  * @param argc argument count
3273  * @param argv argument values
3274  */
3275 int
3276 main (int argc, char *argv[])
3277 {
3278   opt_exp_file = NULL;
3279   opt_solver = NULL;
3280   opt_log = GNUNET_NO;
3281   opt_save = GNUNET_NO;
3282
3283   res = 0;
3284
3285   static struct GNUNET_GETOPT_CommandLineOption options[] =
3286   {
3287     GNUNET_GETOPT_option_string ('s',
3288                                  "solver",
3289                                  gettext_noop ("solver to use"),
3290                                  &opt_solver),
3291
3292     GNUNET_GETOPT_option_string ('e',
3293                                  "experiment"
3294                                  gettext_noop ("experiment to use"),
3295                                  &opt_exp_file),
3296
3297     GNUNET_GETOPT_option_verbose (&opt_verbose),
3298
3299     GNUNET_GETOPT_option_flag ('p', 
3300                                   "print",
3301                                   gettext_noop ("print logging"),
3302                                   &opt_print),
3303
3304     GNUNET_GETOPT_option_flag ('f',
3305                                   "file",
3306                                   gettext_noop ("save logging to disk"),
3307                                   &opt_save),
3308
3309     GNUNET_GETOPT_option_flag ('d', 
3310                                   "dn",
3311                                   gettext_noop ("disable normalization"),
3312                                   &opt_disable_normalization),
3313
3314     GNUNET_GETOPT_OPTION_END
3315   };
3316
3317   GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
3318       NULL, options, &run, argv[0]);
3319
3320   return res;
3321 }
3322 /* end of file ats-testing-experiment.c*/