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