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