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