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