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