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