simplify normalization logic, also have clients access norm array of address directly
[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_normalize_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     normalize_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, GNUNET_NO);
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   const struct ATS_Address *res;
2386
2387   if (NULL == (p = find_peer_by_id (op->peer_id)))
2388   {
2389     GNUNET_break (0);
2390     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2391         "Requesting address for unknown peer %u\n", op->peer_id);
2392     return;
2393   }
2394
2395   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting address for peer %u\n",
2396       op->peer_id);
2397   p->is_requested = GNUNET_YES;
2398
2399   res = sh->sf->s_get (sh->sf->cls, &p->peer_id);
2400   if (NULL != res)
2401   {
2402     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Suggested address for peer %u: %llu %llu\n",
2403         op->peer_id,
2404         res->assigned_bw_in,
2405         res->assigned_bw_out);
2406     if (NULL != l)
2407       GNUNET_ATS_solver_logging_now (l);
2408   }
2409 }
2410
2411 static void
2412 enforce_stop_request (struct GNUNET_ATS_TEST_Operation *op)
2413 {
2414   struct TestPeer *p;
2415
2416   if (NULL == (p = find_peer_by_id (op->peer_id)))
2417   {
2418     GNUNET_break (0);
2419     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2420         "Requesting address for unknown peer %u\n", op->peer_id);
2421     return;
2422   }
2423
2424
2425
2426   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop requesting address for peer %u\n",
2427       op->peer_id);
2428   p->is_requested = GNUNET_NO;
2429   p->assigned_bw_in = 0;
2430   p->assigned_bw_out = 0;
2431   sh->sf->s_get_stop (sh->sf->cls, &p->peer_id);
2432
2433   if (NULL != l)
2434   {
2435     GNUNET_ATS_solver_logging_now (l);
2436   }
2437
2438 }
2439
2440 static void enforce_episode (struct Episode *ep)
2441 {
2442   struct GNUNET_ATS_TEST_Operation *cur;
2443   for (cur = ep->head; NULL != cur; cur = cur->next)
2444   {
2445     switch (cur->type) {
2446       case SOLVER_OP_ADD_ADDRESS:
2447         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
2448             print_op (cur->type), cur->peer_id, cur->address_id);
2449         enforce_add_address (cur);
2450         break;
2451       case SOLVER_OP_DEL_ADDRESS:
2452         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
2453             print_op (cur->type), cur->peer_id, cur->address_id);
2454         enforce_del_address (cur);
2455         break;
2456       case SOLVER_OP_START_SET_PROPERTY:
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_property (cur);
2460         break;
2461       case SOLVER_OP_STOP_SET_PROPERTY:
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_property (cur);
2465         break;
2466       case SOLVER_OP_START_SET_PREFERENCE:
2467         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2468             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2469         enforce_start_preference (cur);
2470         break;
2471       case SOLVER_OP_STOP_SET_PREFERENCE:
2472         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
2473             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
2474         enforce_stop_preference (cur);
2475         break;
2476       case SOLVER_OP_START_REQUEST:
2477         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
2478             print_op (cur->type), cur->peer_id);
2479         enforce_start_request (cur);
2480         break;
2481       case SOLVER_OP_STOP_REQUEST:
2482         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
2483             print_op (cur->type), cur->peer_id);
2484         enforce_stop_request (cur);
2485         break;
2486       default:
2487         break;
2488     }
2489   }
2490 }
2491
2492 static void
2493 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
2494 {
2495   struct Experiment *e = cls;
2496   e->episode_timeout_task = NULL;
2497   if (NULL != e->ep_done_cb)
2498     e->ep_done_cb (e->cur);
2499
2500   /* Scheduling next */
2501   e->cur = e->cur->next;
2502   if (NULL == e->cur)
2503   {
2504     /* done */
2505     fprintf (stderr, "Last episode done!\n");
2506     if (NULL != e->experiment_timeout_task)
2507     {
2508       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
2509       e->experiment_timeout_task = NULL;
2510     }
2511     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
2512     return;
2513   }
2514
2515   fprintf (stderr, "Running episode %u with timeout %s\n",
2516       e->cur->id,
2517       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
2518   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
2519       &timeout_episode, e);
2520   enforce_episode(e->cur);
2521
2522
2523 }
2524
2525
2526 void
2527 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
2528     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
2529     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
2530 {
2531   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
2532       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
2533   e->e_done_cb = e_done_cb;
2534   e->ep_done_cb = ep_done_cb;
2535   e->start_time = GNUNET_TIME_absolute_get();
2536
2537   /* Start total time out */
2538   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
2539       &timeout_experiment, e);
2540
2541   /* Start */
2542   if (NULL == e->start)
2543   {
2544     GNUNET_break (0);
2545     return;
2546   }
2547
2548   e->cur = e->start;
2549   fprintf (stderr, "Running episode %u with timeout %s\n",
2550       e->cur->id,
2551       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
2552   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
2553       &timeout_episode, e);
2554   enforce_episode(e->cur);
2555
2556 }
2557
2558 void
2559 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
2560 {
2561   if (NULL != e->experiment_timeout_task)
2562   {
2563     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
2564     e->experiment_timeout_task = NULL;
2565   }
2566   if (NULL != e->episode_timeout_task)
2567   {
2568     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
2569     e->episode_timeout_task = NULL;
2570   }
2571   if (NULL != e->cfg)
2572   {
2573     GNUNET_CONFIGURATION_destroy(e->cfg);
2574     e->cfg = NULL;
2575   }
2576   free_experiment (e);
2577 }
2578
2579
2580 struct Experiment *
2581 GNUNET_ATS_solvers_experimentation_load (char *filename)
2582 {
2583   struct Experiment *e;
2584   struct GNUNET_CONFIGURATION_Handle *cfg;
2585   e = NULL;
2586
2587   cfg = GNUNET_CONFIGURATION_create();
2588   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
2589   {
2590     fprintf (stderr, "Failed to load `%s'\n", filename);
2591     GNUNET_CONFIGURATION_destroy (cfg);
2592     return NULL;
2593   }
2594
2595   e = create_experiment ();
2596
2597   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
2598       "name", &e->name))
2599   {
2600     fprintf (stderr, "Invalid %s \n", "name");
2601     free_experiment (e);
2602     return NULL;
2603   }
2604   else
2605     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment name: `%s'\n", e->name);
2606
2607   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
2608       "log_prefix", &e->log_prefix))
2609   {
2610     fprintf (stderr, "Invalid %s \n", "log_prefix");
2611     free_experiment (e);
2612     return NULL;
2613   }
2614   else
2615     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging prefix: `%s'\n",
2616         e->log_prefix);
2617
2618   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
2619       "log_output_dir", &e->log_output_dir))
2620   {
2621     e->log_output_dir = NULL;
2622   }
2623   else
2624     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging output directory: `%s'\n",
2625         e->log_output_dir);
2626
2627
2628   if (GNUNET_SYSERR == (e->log_append_time_stamp = GNUNET_CONFIGURATION_get_value_yesno(cfg,
2629       "experiment", "log_append_time_stamp")))
2630     e->log_append_time_stamp = GNUNET_YES;
2631   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging append timestamp: `%s'\n",
2632       (GNUNET_YES == e->log_append_time_stamp) ? "yes" : "no");
2633
2634
2635   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
2636       "cfg_file", &e->cfg_file))
2637   {
2638     fprintf (stderr, "Invalid %s \n", "cfg_file");
2639     free_experiment (e);
2640     return NULL;
2641   }
2642   else
2643   {
2644     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment configuration: `%s'\n", e->cfg_file);
2645     e->cfg = GNUNET_CONFIGURATION_create();
2646     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
2647     {
2648       fprintf (stderr, "Invalid configuration %s \n", "cfg_file");
2649       free_experiment (e);
2650       return NULL;
2651     }
2652
2653   }
2654
2655   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2656       "log_freq", &e->log_freq))
2657   {
2658     fprintf (stderr, "Invalid %s \n", "log_freq");
2659     free_experiment (e);
2660     return NULL;
2661   }
2662   else
2663     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment logging frequency: `%s'\n",
2664         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
2665
2666   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2667       "max_duration", &e->max_duration))
2668   {
2669     fprintf (stderr, "Invalid %s", "max_duration");
2670     free_experiment (e);
2671     return NULL;
2672   }
2673   else
2674     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment duration: `%s'\n",
2675         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
2676
2677   if (GNUNET_SYSERR == load_episodes (e, cfg))
2678   {
2679     GNUNET_ATS_solvers_experimentation_stop (e);
2680     GNUNET_CONFIGURATION_destroy (cfg);
2681     e = NULL;
2682     fprintf (stderr, "Failed to load experiment\n");
2683     return NULL;
2684   }
2685   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loaded %u episodes with total duration %s\n",
2686       e->num_episodes,
2687       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
2688
2689   GNUNET_CONFIGURATION_destroy (cfg);
2690   return e;
2691 }
2692
2693
2694
2695 /**
2696  * Solver
2697  */
2698
2699 static int
2700 free_all_it (void *cls,
2701     const struct GNUNET_PeerIdentity *key,
2702     void *value)
2703 {
2704   struct ATS_Address *address = value;
2705   GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (sh->env.addresses,
2706       key, value));
2707   GNUNET_free (address);
2708
2709   return GNUNET_OK;
2710 }
2711
2712 void
2713 GNUNET_ATS_solvers_solver_stop (struct SolverHandle *sh)
2714 {
2715  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
2716      GNUNET_NO);
2717  GNUNET_PLUGIN_unload (sh->plugin, sh->sf);
2718  sh->sf = NULL;
2719  GAS_normalization_stop();
2720
2721  GNUNET_CONTAINER_multipeermap_iterate (sh->addresses,
2722                                         &free_all_it,
2723                                         NULL);
2724  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
2725  GNUNET_free (sh->plugin);
2726  GNUNET_free (sh);
2727 }
2728
2729
2730 /**
2731  * Load quotas for networks from configuration
2732  *
2733  * @param cfg configuration handle
2734  * @param out_dest where to write outbound quotas
2735  * @param in_dest where to write inbound quotas
2736  * @param dest_length length of inbound and outbound arrays
2737  * @return number of networks loaded
2738  */
2739 unsigned int
2740 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
2741                                                  unsigned long long *out_dest,
2742                                                  unsigned long long *in_dest,
2743                                                  int dest_length)
2744 {
2745   char * entry_in = NULL;
2746   char * entry_out = NULL;
2747   char * quota_out_str;
2748   char * quota_in_str;
2749   int c;
2750   int res;
2751
2752   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
2753   {
2754     in_dest[c] = 0;
2755     out_dest[c] = 0;
2756     GNUNET_asprintf (&entry_out,
2757                      "%s_QUOTA_OUT",
2758                      GNUNET_ATS_print_network_type (c));
2759     GNUNET_asprintf (&entry_in,
2760                      "%s_QUOTA_IN",
2761                      GNUNET_ATS_print_network_type (c));
2762
2763     /* quota out */
2764     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
2765     {
2766       res = GNUNET_NO;
2767       if (0 == strcmp(quota_out_str, BIG_M_STRING))
2768       {
2769         out_dest[c] = GNUNET_ATS_MaxBandwidth;
2770         res = GNUNET_YES;
2771       }
2772       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
2773         res = GNUNET_YES;
2774       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
2775          res = GNUNET_YES;
2776
2777       if (GNUNET_NO == res)
2778       {
2779           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2780                       _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2781                       GNUNET_ATS_print_network_type (c),
2782                       quota_out_str,
2783                       GNUNET_ATS_DefaultBandwidth);
2784           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2785       }
2786       else
2787       {
2788           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2789                       "Outbound quota configure for network `%s' is %llu\n",
2790                       GNUNET_ATS_print_network_type (c),
2791                       out_dest[c]);
2792       }
2793       GNUNET_free (quota_out_str);
2794     }
2795     else
2796     {
2797       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2798                   _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
2799                   GNUNET_ATS_print_network_type (c),
2800                   GNUNET_ATS_DefaultBandwidth);
2801       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2802     }
2803
2804     /* quota in */
2805     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
2806     {
2807       res = GNUNET_NO;
2808       if (0 == strcmp(quota_in_str, BIG_M_STRING))
2809       {
2810         in_dest[c] = GNUNET_ATS_MaxBandwidth;
2811         res = GNUNET_YES;
2812       }
2813       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
2814         res = GNUNET_YES;
2815       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
2816          res = GNUNET_YES;
2817
2818       if (GNUNET_NO == res)
2819       {
2820           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2821                       _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2822                       GNUNET_ATS_print_network_type (c),
2823                       quota_in_str,
2824                       GNUNET_ATS_DefaultBandwidth);
2825           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
2826       }
2827       else
2828       {
2829           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2830                       "Inbound quota configured for network `%s' is %llu\n",
2831                       GNUNET_ATS_print_network_type (c),
2832                       in_dest[c]);
2833       }
2834       GNUNET_free (quota_in_str);
2835     }
2836     else
2837     {
2838       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2839                   _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
2840                   GNUNET_ATS_print_network_type (c),
2841                   GNUNET_ATS_DefaultBandwidth);
2842       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2843     }
2844     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2845                 "Loaded quota for network `%s' (in/out): %llu %llu\n",
2846                 GNUNET_ATS_print_network_type (c),
2847                 in_dest[c],
2848                 out_dest[c]);
2849     GNUNET_free (entry_out);
2850     GNUNET_free (entry_in);
2851   }
2852   return GNUNET_ATS_NetworkTypeCount;
2853 }
2854
2855
2856 /**
2857  * Information callback for the solver
2858  *
2859  * @param cls the closure
2860  * @param op the solver operation
2861  * @param stat status of the solver operation
2862  * @param add additional solver information
2863  */
2864 static void
2865 solver_info_cb (void *cls,
2866                 enum GAS_Solver_Operation op,
2867                 enum GAS_Solver_Status stat,
2868                 enum GAS_Solver_Additional_Information add)
2869 {
2870   char *add_info;
2871   switch (add) {
2872     case GAS_INFO_NONE:
2873       add_info = "GAS_INFO_NONE";
2874       break;
2875     case GAS_INFO_FULL:
2876       add_info = "GAS_INFO_MLP_FULL";
2877       break;
2878     case GAS_INFO_UPDATED:
2879       add_info = "GAS_INFO_MLP_UPDATED";
2880       break;
2881     case GAS_INFO_PROP_ALL:
2882       add_info = "GAS_INFO_PROP_ALL";
2883       break;
2884     case GAS_INFO_PROP_SINGLE:
2885       add_info = "GAS_INFO_PROP_SINGLE";
2886       break;
2887     default:
2888       add_info = "INVALID";
2889       break;
2890   }
2891
2892   switch (op)
2893   {
2894     case GAS_OP_SOLVE_START:
2895       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2896           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
2897           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2898       return;
2899     case GAS_OP_SOLVE_STOP:
2900       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2901           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
2902           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2903       return;
2904
2905     case GAS_OP_SOLVE_SETUP_START:
2906       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2907           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
2908           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2909       return;
2910
2911     case GAS_OP_SOLVE_SETUP_STOP:
2912       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2913           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
2914           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2915       return;
2916
2917     case GAS_OP_SOLVE_MLP_LP_START:
2918       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2919           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
2920           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2921       return;
2922     case GAS_OP_SOLVE_MLP_LP_STOP:
2923       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2924           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
2925           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2926       return;
2927
2928     case GAS_OP_SOLVE_MLP_MLP_START:
2929       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2930           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
2931           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2932       return;
2933     case GAS_OP_SOLVE_MLP_MLP_STOP:
2934       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2935           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
2936           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2937       return;
2938     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
2939       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2940           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
2941           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2942       return;
2943     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
2944       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2945           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
2946           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2947       return;
2948     default:
2949       break;
2950     }
2951 }
2952
2953 static void
2954 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
2955 {
2956   struct GNUNET_TIME_Relative duration;
2957   struct TestPeer *p;
2958   static struct PreferenceGenerator *pg;
2959   uint32_t delta;
2960   if ( (0 == address->assigned_bw_out) && (0 == address->assigned_bw_in) )
2961   {
2962     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2963                 "Solver notified to disconnect peer `%s'\n",
2964                 GNUNET_i2s (&address->peer));
2965   }
2966   p = find_peer_by_pid(&address->peer);
2967   if (NULL == p)
2968     return;
2969   p->assigned_bw_out = address->assigned_bw_out;
2970   p->assigned_bw_in = address->assigned_bw_in;
2971
2972   for (pg = pref_gen_head; NULL != pg; pg = pg->next)
2973   {
2974     if (pg->peer == p->id)
2975     {
2976       duration = GNUNET_TIME_absolute_get_duration(pg->feedback_last_bw_update);
2977       delta = duration.rel_value_us * pg->last_assigned_bw_out;
2978       pg->feedback_bw_out_acc += delta;
2979
2980       delta = duration.rel_value_us * pg->last_assigned_bw_in;
2981       pg->feedback_bw_in_acc += delta;
2982
2983       pg->last_assigned_bw_in = address->assigned_bw_in;
2984       pg->last_assigned_bw_out = address->assigned_bw_out;
2985       pg->feedback_last_bw_update = GNUNET_TIME_absolute_get();
2986     }
2987   }
2988
2989   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2990       "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
2991       GNUNET_i2s (&address->peer),
2992       address,
2993       address->assigned_bw_out,
2994           address->assigned_bw_in);
2995
2996   if (NULL != l)
2997     GNUNET_ATS_solver_logging_now (l);
2998
2999   return;
3000 }
3001
3002 const double *
3003 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
3004 {
3005   struct TestPeer *p;
3006   if (GNUNET_YES == opt_disable_normalization)
3007   {
3008     if (NULL == (p = find_peer_by_pid (id)))
3009       return NULL;
3010     return p->pref_abs;
3011   }
3012   else
3013     return GAS_normalization_get_preferences_by_peer (NULL,
3014                                                       id);
3015 }
3016
3017
3018 struct SolverHandle *
3019 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
3020 {
3021   struct SolverHandle *sh;
3022   char * solver_str;
3023
3024   switch (type) {
3025     case GNUNET_ATS_SOLVER_PROPORTIONAL:
3026       solver_str = "proportional";
3027       break;
3028     case GNUNET_ATS_SOLVER_MLP:
3029       solver_str = "mlp";
3030       break;
3031     case GNUNET_ATS_SOLVER_RIL:
3032       solver_str = "ril";
3033       break;
3034     default:
3035       GNUNET_break (0);
3036       return NULL;
3037       break;
3038   }
3039
3040   sh = GNUNET_new (struct SolverHandle);
3041   GNUNET_asprintf (&sh->plugin,
3042                    "libgnunet_plugin_ats_%s",
3043                    solver_str);
3044   sh->addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
3045
3046   /* setup environment */
3047   sh->env.cfg = e->cfg;
3048   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
3049   sh->env.addresses = sh->addresses;
3050   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
3051   sh->env.get_preferences = &get_preferences_cb;
3052   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
3053   sh->env.info_cb = &solver_info_cb;
3054   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
3055
3056   /* start normalization */
3057   GAS_normalization_start ();
3058
3059   /* load quotas */
3060   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
3061       sh->env.out_quota, sh->env.in_quota, GNUNET_ATS_NetworkTypeCount))
3062   {
3063     GNUNET_break(0);
3064     GNUNET_free (sh->plugin);
3065     GNUNET_free (sh);
3066     end_now ();
3067     return NULL;
3068   }
3069
3070   sh->sf = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
3071   if (NULL == sh->sf)
3072   {
3073     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
3074     GNUNET_break(0);
3075     GNUNET_free (sh->plugin);
3076     GNUNET_free (sh);
3077     end_now ();
3078     return NULL;
3079   }
3080   return sh;
3081 }
3082
3083
3084 static void
3085 done ()
3086 {
3087   struct TestPeer *cur;
3088   struct TestPeer *next;
3089
3090   struct TestAddress *cur_a;
3091   struct TestAddress *next_a;
3092
3093   /* Stop logging */
3094   GNUNET_ATS_solver_logging_stop (l);
3095
3096   /* Stop all preference generation */
3097   GNUNET_ATS_solver_generate_preferences_stop_all ();
3098
3099   /* Stop all property generation */
3100   GNUNET_ATS_solver_generate_property_stop_all ();
3101
3102   if (opt_print)
3103   {
3104     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Printing log information \n");
3105     GNUNET_ATS_solver_logging_eval (l);
3106   }
3107   if (opt_save)
3108   {
3109     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "== Saving log information \n");
3110     GNUNET_ATS_solver_logging_write_to_disk (l, e->log_append_time_stamp,
3111         e->log_output_dir);
3112   }
3113
3114   if (NULL != l)
3115   {
3116     GNUNET_ATS_solver_logging_free (l);
3117     l = NULL;
3118   }
3119
3120   /* Clean up experiment */
3121   if (NULL != e)
3122   {
3123     GNUNET_ATS_solvers_experimentation_stop (e);
3124     e = NULL;
3125   }
3126
3127   next = peer_head;
3128   while  (NULL != (cur = next))
3129   {
3130     next = cur->next;
3131     GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, cur);
3132     next_a = cur->addr_head;
3133     while  (NULL != (cur_a = next_a))
3134     {
3135       next_a = cur_a->next;
3136       GNUNET_CONTAINER_DLL_remove (cur->addr_head, cur->addr_tail, cur_a);
3137       GNUNET_free (cur_a);
3138     }
3139     GNUNET_free (cur);
3140   }
3141   if (NULL != sh)
3142   {
3143     GNUNET_ATS_solvers_solver_stop (sh);
3144     sh = NULL;
3145   }
3146
3147   /* Shutdown */
3148   end_now();
3149 }
3150
3151 static void
3152 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
3153 {
3154   if (GNUNET_OK == success)
3155     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
3156         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
3157   else
3158     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
3159
3160   GNUNET_SCHEDULER_add_now (&done, NULL);
3161 }
3162
3163 static void
3164 episode_done_cb (struct Episode *ep)
3165 {
3166   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
3167 }
3168
3169
3170
3171 /**
3172  * Do shutdown
3173  */
3174 static void
3175 end_now ()
3176 {
3177   if (NULL != e)
3178   {
3179     GNUNET_ATS_solvers_experimentation_stop (e);
3180     e = NULL;
3181   }
3182   if (NULL != sh)
3183   {
3184     GNUNET_ATS_solvers_solver_stop (sh);
3185     sh = NULL;
3186   }
3187 }
3188
3189 static void
3190 run (void *cls, char * const *args, const char *cfgfile,
3191     const struct GNUNET_CONFIGURATION_Handle *cfg)
3192 {
3193   enum GNUNET_ATS_Solvers solver;
3194   int c;
3195
3196   if (NULL == opt_exp_file)
3197   {
3198     fprintf (stderr, "No experiment given ...\n");
3199     res = 1;
3200     end_now ();
3201     return;
3202   }
3203
3204   if (NULL == opt_solver)
3205   {
3206     fprintf (stderr, "No solver given ...\n");
3207     res = 1;
3208     end_now ();
3209     return;
3210   }
3211
3212   if (0 == strcmp(opt_solver, "mlp"))
3213   {
3214     solver = GNUNET_ATS_SOLVER_MLP;
3215   }
3216   else if (0 == strcmp(opt_solver, "proportional"))
3217   {
3218     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
3219   }
3220   else if (0 == strcmp(opt_solver, "ril"))
3221   {
3222     solver = GNUNET_ATS_SOLVER_RIL;
3223   }
3224   else
3225   {
3226     fprintf (stderr, "No solver given ...");
3227     res = 1;
3228     end_now ();
3229     return;
3230   }
3231
3232   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
3233     default_properties[c] = DEFAULT_REL_QUALITY;
3234
3235   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
3236     default_preferences[c] = DEFAULT_REL_PREFERENCE;
3237
3238   /* load experiment */
3239   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading experiment\n");
3240   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
3241   if (NULL == e)
3242   {
3243     fprintf (stderr, "Failed to load experiment ...\n");
3244     res = 1;
3245     end_now ();
3246     return;
3247   }
3248
3249   /* load solver */
3250   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Loading solver\n");
3251   sh = GNUNET_ATS_solvers_solver_start (solver);
3252   if (NULL == sh)
3253   {
3254     fprintf (stderr, "Failed to start solver ...\n");
3255     end_now ();
3256     res = 1;
3257     return;
3258   }
3259
3260   /* start logging */
3261   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Start logging \n");
3262   l = GNUNET_ATS_solver_logging_start (e->log_freq);
3263
3264   /* run experiment */
3265   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "=== Running experiment \n");
3266   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
3267       experiment_done_cb);
3268
3269   /* WAIT */
3270 }
3271
3272
3273 /**
3274  * Main function of the benchmark
3275  *
3276  * @param argc argument count
3277  * @param argv argument values
3278  */
3279 int
3280 main (int argc, char *argv[])
3281 {
3282   opt_exp_file = NULL;
3283   opt_solver = NULL;
3284   opt_log = GNUNET_NO;
3285   opt_save = GNUNET_NO;
3286
3287   res = 0;
3288
3289   static struct GNUNET_GETOPT_CommandLineOption options[] =
3290   {
3291     { 's', "solver", NULL,
3292         gettext_noop ("solver to use"),
3293         1, &GNUNET_GETOPT_set_string, &opt_solver},
3294     {  'e', "experiment", NULL,
3295       gettext_noop ("experiment to use"),
3296       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
3297     {  'V', "verbose", NULL,
3298       gettext_noop ("be verbose"),
3299       0, &GNUNET_GETOPT_set_one, &opt_verbose},
3300     {  'p', "print", NULL,
3301       gettext_noop ("print logging"),
3302       0, &GNUNET_GETOPT_set_one, &opt_print},
3303     {  'f', "file", NULL,
3304         gettext_noop ("save logging to disk"),
3305         0, &GNUNET_GETOPT_set_one, &opt_save},
3306     {  'd', "dn", NULL,
3307         gettext_noop ("disable normalization"),
3308         0, &GNUNET_GETOPT_set_one, &opt_disable_normalization},
3309     GNUNET_GETOPT_OPTION_END
3310   };
3311
3312   GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
3313       NULL, options, &run, argv[0]);
3314
3315   return res;
3316 }
3317 /* end of file ats-testing-experiment.c*/