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