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