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