+ setting preference
[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 /**
42  * cmd option -e: experiment file
43  */
44 static char *opt_exp_file;
45
46 static char *opt_solver;
47
48 /**
49  * cmd option -l: enable logging
50  */
51 static int opt_log;
52
53 /**
54  * cmd option -p: enable plots
55  */
56 static int opt_plot;
57
58 /**
59  * cmd option -v: verbose logs
60  */
61 static int opt_verbose;
62
63 static int res;
64
65 static void
66 end_now ();
67
68 static char *
69 print_generator_type (enum GeneratorType g)
70 {
71   switch (g) {
72     case GNUNET_ATS_TEST_TG_CONSTANT:
73       return "CONSTANT";
74     case GNUNET_ATS_TEST_TG_LINEAR:
75       return "LINEAR";
76     case GNUNET_ATS_TEST_TG_RANDOM:
77       return "RANDOM";
78     case GNUNET_ATS_TEST_TG_SINUS:
79       return "SINUS";
80     default:
81       return "INVALID";
82       break;
83   }
84 }
85
86 struct AddressLookupCtx
87 {
88   struct ATS_Address *res;
89   char *plugin;
90   char *addr;
91 };
92
93
94 int find_address_it (void *cls,
95                      const struct GNUNET_PeerIdentity *key,
96                      void *value)
97 {
98   struct AddressLookupCtx *ctx = cls;
99   struct ATS_Address *addr = value;
100
101   if ( (0 == strcmp (ctx->plugin, addr->plugin)) &&
102        (0 == strcmp (ctx->addr, addr->addr)) )
103   {
104        ctx->res = addr;
105        return GNUNET_NO;
106   }
107   return GNUNET_YES;
108 }
109
110 static struct TestPeer *
111 find_peer_by_id (int id)
112 {
113   struct TestPeer *cur;
114   for (cur = peer_head; NULL != cur; cur = cur->next)
115     if (cur->id == id)
116       return cur;
117   return NULL;
118 }
119
120 static struct TestAddress *
121 find_address_by_id (struct TestPeer *peer, int aid)
122 {
123   struct TestAddress *cur;
124   for (cur = peer->addr_head; NULL != cur; cur = cur->next)
125     if (cur->aid == aid)
126       return cur;
127   return NULL;
128 }
129
130
131
132 /**
133  * Logging
134  */
135
136 static void
137 logging_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
138 {
139   struct LoggingHandle *l = cls;
140
141   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
142
143   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging\n");
144
145   l->logging_task = GNUNET_SCHEDULER_add_delayed (l->log_freq, &logging_task, l);
146
147 }
148
149 struct LoggingHandle *
150 GNUNET_ATS_solver_logging_start (struct GNUNET_TIME_Relative freq)
151 {
152   struct LoggingHandle *l;
153   l = GNUNET_new (struct LoggingHandle);
154
155   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start logging every  %s\n",
156       GNUNET_STRINGS_relative_time_to_string(freq, GNUNET_NO));
157
158   /* Iterate over peers */
159
160   l->log_freq = freq;
161   l->logging_task = GNUNET_SCHEDULER_add_now (&logging_task, l);
162
163   return l;
164 }
165
166 void
167 GNUNET_ATS_solver_logging_now (struct LoggingHandle *l)
168 {
169   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging\n");
170 }
171
172 void
173 GNUNET_ATS_solver_logging_stop (struct LoggingHandle *l)
174 {
175   if (GNUNET_SCHEDULER_NO_TASK != l->logging_task)
176     GNUNET_SCHEDULER_cancel (l->logging_task);
177
178   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop logging\n");
179
180   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
181 }
182
183 void
184 GNUNET_ATS_solver_logging_eval (struct LoggingHandle *l)
185 {
186
187 }
188
189 void
190 GNUNET_ATS_solver_logging_free (struct LoggingHandle *l)
191 {
192   if (GNUNET_SCHEDULER_NO_TASK != l->logging_task)
193     GNUNET_SCHEDULER_cancel (l->logging_task);
194   l->logging_task = GNUNET_SCHEDULER_NO_TASK;
195   GNUNET_free (l);
196 }
197
198 /**
199  * Property Generators
200  */
201
202 static struct PropertyGenerator *prop_gen_head;
203 static struct PropertyGenerator *prop_gen_tail;
204
205 static double
206 get_property (struct PropertyGenerator *pg)
207 {
208   struct GNUNET_TIME_Relative time_delta;
209   double delta_value;
210   double pref_value;
211
212   /* Calculate the current preference value */
213   switch (pg->type) {
214     case GNUNET_ATS_TEST_TG_CONSTANT:
215       pref_value = pg->base_value;
216       break;
217     case GNUNET_ATS_TEST_TG_LINEAR:
218       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
219       /* Calculate point of time in the current period */
220       time_delta.rel_value_us = time_delta.rel_value_us %
221           pg->duration_period.rel_value_us;
222       delta_value = ((double) time_delta.rel_value_us  /
223           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
224       if ((pg->max_value < pg->base_value) &&
225           ((pg->max_value - pg->base_value) > pg->base_value))
226       {
227         /* This will cause an underflow */
228         GNUNET_break (0);
229       }
230       pref_value = pg->base_value + delta_value;
231       break;
232     case GNUNET_ATS_TEST_TG_RANDOM:
233       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
234           10000 * (pg->max_value - pg->base_value)) / 10000;
235       pref_value = pg->base_value + delta_value;
236       break;
237     case GNUNET_ATS_TEST_TG_SINUS:
238       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
239       /* Calculate point of time in the current period */
240       time_delta.rel_value_us = time_delta.rel_value_us %
241           pg->duration_period.rel_value_us;
242       if ((pg->max_value - pg->base_value) > pg->base_value)
243       {
244         /* This will cause an underflow for second half of sinus period,
245          * will be detected in general when experiments are loaded */
246         GNUNET_break (0);
247       }
248       delta_value = (pg->max_value - pg->base_value) *
249           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
250               time_delta.rel_value_us);
251       pref_value = pg->base_value + delta_value;
252       break;
253     default:
254       pref_value = 0.0;
255       break;
256   }
257   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current property value is %f\n",
258       pref_value);
259   return pref_value;
260 }
261
262
263 static void
264 set_prop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
265 {
266   struct PropertyGenerator *pg = cls;
267   double pref_value;
268   struct GNUNET_ATS_Information atsi;
269
270   pg->set_task = GNUNET_SCHEDULER_NO_TASK;
271
272   if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains_value (sh->addresses,
273       &pg->test_peer->peer_id, pg->test_address->ats_addr))
274   {
275     GNUNET_break (0);
276     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
277         "Setting property generation for unknown address [%u:%u]\n",
278         pg->peer, pg->address_id);
279     return;
280   }
281
282   pref_value = get_property (pg);
283
284   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
285       "Setting property for peer [%u] address [%u] for %s to %f\n",
286       pg->peer, pg->address_id,
287       GNUNET_ATS_print_property_type (pg->ats_property), pref_value);
288
289
290   atsi.type = htonl (pg->ats_property);
291   atsi.value = htonl ((uint32_t) pref_value);
292
293   /* set performance here! */
294   sh->env.sf.s_bulk_start (sh->solver);
295   GAS_normalization_normalize_property (sh->addresses,
296       pg->test_address->ats_addr, &atsi, 1);
297   sh->env.sf.s_bulk_stop (sh->solver);
298
299   switch (pg->ats_property) {
300     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
301       //p->pref_bandwidth = pref_value;
302       break;
303     case GNUNET_ATS_PREFERENCE_LATENCY:
304       //p->pref_delay = pref_value;
305       break;
306     default:
307       break;
308   }
309
310   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
311       &set_prop_task, pg);
312
313 }
314
315 static struct PropertyGenerator *
316 find_prop_gen (unsigned int peer, unsigned int address,
317     uint32_t ats_property)
318 {
319   struct PropertyGenerator *cur;
320   for (cur = prop_gen_head; NULL != cur; cur = cur->next)
321     if ((cur->peer == peer) && (cur->address_id == address) &&
322         (cur->ats_property == ats_property))
323       return cur;
324   return NULL;
325 }
326
327 void
328 GNUNET_ATS_solver_generate_property_stop (struct PropertyGenerator *pg)
329 {
330   GNUNET_CONTAINER_DLL_remove (prop_gen_head, prop_gen_tail, pg);
331
332   if (GNUNET_SCHEDULER_NO_TASK != pg->set_task)
333   {
334     GNUNET_SCHEDULER_cancel (pg->set_task);
335     pg->set_task = GNUNET_SCHEDULER_NO_TASK;
336   }
337   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
338       "Removing old up preference generator peer [%u] address [%u] `%s'\n",
339       pg->peer, pg->address_id,
340       GNUNET_ATS_print_property_type(pg->ats_property));
341
342   GNUNET_free (pg);
343 }
344
345
346 /**
347  * Generate between the source master and the partner and set preferences with a
348  * value depending on the generator.
349  *
350  * @param src source
351  * @param dest partner
352  * @param type type of preferences to generate
353  * @param base_rate traffic base rate to send data with
354  * @param max_rate  traffic maximum rate to send data with
355  * @param period duration of a period of traffic generation (~ 1/frequency)
356  * @param duration how long to generate traffic
357  * @return the traffic generator
358  */
359 struct PropertyGenerator *
360 GNUNET_ATS_solver_generate_property_start (unsigned int peer,
361     unsigned int address_id,
362     struct TestPeer *test_peer,
363     struct TestAddress *test_address,
364     enum GeneratorType type,
365     long int base_value,
366     long int value_rate,
367     struct GNUNET_TIME_Relative period,
368     struct GNUNET_TIME_Relative frequency,
369     uint32_t ats_property)
370 {
371   struct PropertyGenerator *pg;
372
373   pg = GNUNET_new (struct PropertyGenerator);
374   GNUNET_CONTAINER_DLL_insert (prop_gen_head, prop_gen_tail, pg);
375   pg->type = type;
376   pg->peer = peer;
377   pg->test_address = test_address;
378   pg->test_peer = test_peer;
379   pg->address_id = address_id;
380   pg->ats_property = ats_property;
381   pg->base_value = base_value;
382   pg->max_value = value_rate;
383   pg->duration_period = period;
384   pg->frequency = frequency;
385   pg->time_start = GNUNET_TIME_absolute_get();
386
387   switch (type) {
388     case GNUNET_ATS_TEST_TG_CONSTANT:
389       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
390           "Setting up %s property generator peer [%u] address [%u] `%s'"\
391           "max %u Bips\n",
392           print_generator_type(type), pg->peer, pg->address_id,
393           GNUNET_ATS_print_property_type (ats_property),
394           base_value);
395       break;
396     case GNUNET_ATS_TEST_TG_LINEAR:
397       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
398           "Setting up %s property generator peer [%u] address [%u] `%s' " \
399           "min %u Bips max %u Bips\n",
400           print_generator_type(type), pg->peer, pg->address_id,
401           GNUNET_ATS_print_property_type(ats_property),
402           base_value, value_rate);
403       break;
404     case GNUNET_ATS_TEST_TG_SINUS:
405       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
406           "Setting up %s property generator peer [%u] address [%u] `%s' "\
407           "baserate %u Bips, amplitude %u Bps\n",
408           print_generator_type(type), pg->peer, pg->address_id,
409           GNUNET_ATS_print_property_type(ats_property),
410           base_value, value_rate);
411       break;
412     case GNUNET_ATS_TEST_TG_RANDOM:
413       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
414           "Setting up %s property generator peer [%u] address [%u] `%s' "\
415           "min %u Bips max %u Bps\n",
416           print_generator_type(type), pg->peer, pg->address_id,
417           GNUNET_ATS_print_property_type(ats_property),
418           base_value, value_rate);
419       break;
420     default:
421       break;
422   }
423
424   pg->set_task = GNUNET_SCHEDULER_add_now (&set_prop_task, pg);
425   return pg;
426 }
427
428
429
430 /**
431  * Stop all preferences generators
432  */
433 void
434 GNUNET_ATS_solver_generate_property_stop_all ()
435 {
436   struct PropertyGenerator *cur;
437   struct PropertyGenerator *next;
438   next = prop_gen_head;
439   for (cur = next; NULL != cur; cur = next)
440   {
441       next = cur->next;
442       GNUNET_ATS_solver_generate_property_stop (cur);
443   }
444 }
445
446
447 /**
448  * Preference Generators
449  */
450
451 static struct PreferenceGenerator *pref_gen_head;
452 static struct PreferenceGenerator *pref_gen_tail;
453
454 static double
455 get_preference (struct PreferenceGenerator *pg)
456 {
457   struct GNUNET_TIME_Relative time_delta;
458   double delta_value;
459   double pref_value;
460
461   /* Calculate the current preference value */
462   switch (pg->type) {
463     case GNUNET_ATS_TEST_TG_CONSTANT:
464       pref_value = pg->base_value;
465       break;
466     case GNUNET_ATS_TEST_TG_LINEAR:
467       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
468       /* Calculate point of time in the current period */
469       time_delta.rel_value_us = time_delta.rel_value_us %
470           pg->duration_period.rel_value_us;
471       delta_value = ((double) time_delta.rel_value_us  /
472           pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value);
473       if ((pg->max_value < pg->base_value) &&
474           ((pg->max_value - pg->base_value) > pg->base_value))
475       {
476         /* This will cause an underflow */
477         GNUNET_break (0);
478       }
479       pref_value = pg->base_value + delta_value;
480       break;
481     case GNUNET_ATS_TEST_TG_RANDOM:
482       delta_value =  (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
483           10000 * (pg->max_value - pg->base_value)) / 10000;
484       pref_value = pg->base_value + delta_value;
485       break;
486     case GNUNET_ATS_TEST_TG_SINUS:
487       time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start);
488       /* Calculate point of time in the current period */
489       time_delta.rel_value_us = time_delta.rel_value_us %
490           pg->duration_period.rel_value_us;
491       if ((pg->max_value - pg->base_value) > pg->base_value)
492       {
493         /* This will cause an underflow for second half of sinus period,
494          * will be detected in general when experiments are loaded */
495         GNUNET_break (0);
496       }
497       delta_value = (pg->max_value - pg->base_value) *
498           sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) *
499               time_delta.rel_value_us);
500       pref_value = pg->base_value + delta_value;
501       break;
502     default:
503       pref_value = 0.0;
504       break;
505   }
506   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n",
507       pref_value);
508   return pref_value;
509 }
510
511
512 static void
513 set_pref_task (void *cls,
514                     const struct GNUNET_SCHEDULER_TaskContext *tc)
515 {
516   struct PreferenceGenerator *pg = cls;
517   struct TestPeer *p;
518   double pref_value;
519   pg->set_task = GNUNET_SCHEDULER_NO_TASK;
520
521   if (NULL == (p = find_peer_by_id (pg->peer)))
522   {
523     GNUNET_break (0);
524     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
525         "Setting preference for unknown peer %u\n", pg->peer);
526     return;
527   }
528
529   pref_value = get_preference (pg);
530
531   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
532       "Setting preference for peer [%u] address [%u] for client %p pref %s to %f\n",
533       pg->peer, pg->address_id, NULL + (pg->client_id),
534       GNUNET_ATS_print_preference_type (pg->kind), pref_value);
535
536   sh->env.sf.s_bulk_start (sh->solver);
537   GAS_normalization_normalize_preference (NULL + (pg->client_id), &p->peer_id,
538       pg->kind, pref_value);
539   sh->env.sf.s_bulk_stop (sh->solver);
540
541   switch (pg->kind) {
542     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
543       //p->pref_bandwidth = pref_value;
544       break;
545     case GNUNET_ATS_PREFERENCE_LATENCY:
546       //p->pref_delay = pref_value;
547       break;
548     default:
549       break;
550   }
551
552   pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency,
553       set_pref_task, pg);
554
555 }
556
557 static struct PreferenceGenerator *
558 find_pref_gen (unsigned int peer, unsigned int address,
559     enum GNUNET_ATS_PreferenceKind kind)
560 {
561   struct PreferenceGenerator *cur;
562   for (cur = pref_gen_head; NULL != cur; cur = cur->next)
563     if ((cur->peer == peer) && (cur->address_id == address) && (cur->kind == kind))
564       return cur;
565   return NULL;
566 }
567
568 void
569 GNUNET_ATS_solver_generate_preferences_stop (struct PreferenceGenerator *pg)
570 {
571   GNUNET_CONTAINER_DLL_remove (pref_gen_head, pref_gen_tail, pg);
572
573   if (GNUNET_SCHEDULER_NO_TASK != pg->set_task)
574   {
575     GNUNET_SCHEDULER_cancel (pg->set_task);
576     pg->set_task = GNUNET_SCHEDULER_NO_TASK;
577   }
578   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
579       "Removing old up preference generator peer [%u] address [%u] `%s'\n",
580       pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(pg->kind));
581
582   GNUNET_free (pg);
583 }
584
585
586 /**
587  * Generate between the source master and the partner and set preferences with a
588  * value depending on the generator.
589  *
590  * @param src source
591  * @param dest partner
592  * @param type type of preferences to generate
593  * @param base_rate traffic base rate to send data with
594  * @param max_rate  traffic maximum rate to send data with
595  * @param period duration of a period of traffic generation (~ 1/frequency)
596  * @param duration how long to generate traffic
597  * @return the traffic generator
598  */
599 struct PreferenceGenerator *
600 GNUNET_ATS_solver_generate_preferences_start (unsigned int peer,
601     unsigned int address_id,
602     unsigned int client_id,
603     enum GeneratorType type,
604     long int base_value,
605     long int value_rate,
606     struct GNUNET_TIME_Relative period,
607     struct GNUNET_TIME_Relative frequency,
608     enum GNUNET_ATS_PreferenceKind kind)
609 {
610   struct PreferenceGenerator *pg;
611
612   pg = GNUNET_new (struct PreferenceGenerator);
613   GNUNET_CONTAINER_DLL_insert (pref_gen_head, pref_gen_tail, pg);
614   pg->type = type;
615   pg->peer = peer;
616   pg->address_id = address_id;
617   pg->client_id = client_id;
618   pg->kind = kind;
619   pg->base_value = base_value;
620   pg->max_value = value_rate;
621   pg->duration_period = period;
622   pg->frequency = frequency;
623   pg->time_start = GNUNET_TIME_absolute_get();
624
625   switch (type) {
626     case GNUNET_ATS_TEST_TG_CONSTANT:
627       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
628           "Setting up %s preference generator peer [%u] address [%u] `%s' max %u Bips\n",
629           print_generator_type (type), pg->peer, pg->address_id,
630           GNUNET_ATS_print_preference_type(kind),
631           base_value);
632       break;
633     case GNUNET_ATS_TEST_TG_LINEAR:
634       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
635           "Setting up %s preference generator peer [%u] address [%u] `%s' min %u Bips max %u Bips\n",
636           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
637           base_value, value_rate);
638       break;
639     case GNUNET_ATS_TEST_TG_SINUS:
640       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
641           "Setting up %s preference generator peer [%u] address [%u] `%s' baserate %u Bips, amplitude %u Bps\n",
642           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
643           base_value, value_rate);
644       break;
645     case GNUNET_ATS_TEST_TG_RANDOM:
646       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
647           "Setting up %s preference generator peer [%u] address [%u] `%s' min %u Bips max %u Bps\n",
648           print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind),
649           base_value, value_rate);
650       break;
651     default:
652       break;
653   }
654
655   pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, pg);
656   return pg;
657 }
658
659
660
661 /**
662  * Stop all preferences generators
663  */
664 void
665 GNUNET_ATS_solver_generate_preferences_stop_all ()
666 {
667   struct PreferenceGenerator *cur;
668   struct PreferenceGenerator *next;
669   next = pref_gen_head;
670   for (cur = next; NULL != cur; cur = next)
671   {
672       next = cur->next;
673       GNUNET_ATS_solver_generate_preferences_stop(cur);
674   }
675 }
676
677
678
679 /**
680  * Experiments
681  */
682
683 const char *
684 print_op (enum OperationType op)
685 {
686   switch (op) {
687     case SOLVER_OP_ADD_ADDRESS:
688       return "ADD_ADDRESS";
689     case SOLVER_OP_DEL_ADDRESS:
690       return "DEL_ADDRESS";
691     case SOLVER_OP_START_SET_PREFERENCE:
692       return "START_SET_PREFERENCE";
693     case SOLVER_OP_STOP_SET_PREFERENCE:
694       return "STOP_STOP_PREFERENCE";
695     case SOLVER_OP_START_SET_PROPERTY:
696       return "START_SET_PROPERTY";
697     case SOLVER_OP_STOP_SET_PROPERTY:
698       return "STOP_SET_PROPERTY";
699     case SOLVER_OP_START_REQUEST:
700       return "START_REQUEST";
701     case SOLVER_OP_STOP_REQUEST:
702       return "STOP_REQUEST";
703     default:
704       break;
705   }
706   return "";
707 }
708
709 static struct Experiment *
710 create_experiment ()
711 {
712   struct Experiment *e;
713   e = GNUNET_new (struct Experiment);
714   e->name = NULL;
715   e->start = NULL;
716   e->total_duration = GNUNET_TIME_UNIT_ZERO;
717   return e;
718 }
719
720 static void
721 free_experiment (struct Experiment *e)
722 {
723   struct Episode *cur;
724   struct Episode *next;
725   struct GNUNET_ATS_TEST_Operation *cur_o;
726   struct GNUNET_ATS_TEST_Operation *next_o;
727
728   next = e->start;
729   for (cur = next; NULL != cur; cur = next)
730   {
731     next = cur->next;
732
733     next_o = cur->head;
734     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
735     {
736       next_o = cur_o->next;
737       GNUNET_free_non_null (cur_o->address);
738       GNUNET_free_non_null (cur_o->plugin);
739       GNUNET_free (cur_o);
740     }
741     GNUNET_free (cur);
742   }
743
744   GNUNET_free_non_null (e->name);
745   GNUNET_free_non_null (e->cfg_file);
746   GNUNET_free (e);
747 }
748
749
750 static int
751 load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
752     struct Episode *e,
753     int op_counter,
754     char *sec_name,
755     const struct GNUNET_CONFIGURATION_Handle *cfg)
756 {
757   char *op_name;
758
759   /* peer id */
760   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
761   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
762       sec_name, op_name, &o->peer_id))
763   {
764     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
765         op_counter, "ADD_ADDRESS", op_name);
766     GNUNET_free (op_name);
767     return GNUNET_SYSERR;
768   }
769   GNUNET_free (op_name);
770
771   /* address id */
772   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
773   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
774       sec_name, op_name, &o->address_id))
775   {
776     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
777         op_counter, "ADD_ADDRESS", op_name);
778     GNUNET_free (op_name);
779     return GNUNET_SYSERR;
780   }
781   GNUNET_free (op_name);
782
783   /* plugin */
784   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
785   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
786       sec_name, op_name, &o->plugin))
787   {
788     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
789         op_counter, "ADD_ADDRESS", op_name);
790     GNUNET_free (op_name);
791     return GNUNET_SYSERR;
792   }
793   GNUNET_free (op_name);
794
795   /* address  */
796   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
797   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
798       sec_name, op_name, &o->address))
799   {
800     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
801         op_counter, "ADD_ADDRESS", op_name);
802     GNUNET_free (op_name);
803     return GNUNET_SYSERR;
804   }
805   GNUNET_free (op_name);
806
807   /* session */
808   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
809   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
810       sec_name, op_name, &o->address_session))
811   {
812     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
813         op_counter, "ADD_ADDRESS", op_name);
814     GNUNET_free (op_name);
815     return GNUNET_SYSERR;
816   }
817   GNUNET_free (op_name);
818
819   /* network */
820   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
821   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
822       sec_name, op_name, &o->address_network))
823   {
824     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
825         op_counter, "ADD_ADDRESS", op_name);
826     GNUNET_free (op_name);
827     return GNUNET_SYSERR;
828   }
829   GNUNET_free (op_name);
830
831   fprintf (stderr,
832       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
833       "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
834
835   return GNUNET_OK;
836 }
837
838 static int
839 load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
840     struct Episode *e,
841     int op_counter,
842     char *sec_name,
843     const struct GNUNET_CONFIGURATION_Handle *cfg)
844 {
845   char *op_name;
846
847   /* peer id */
848   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
849   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
850       sec_name, op_name, &o->peer_id))
851   {
852     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
853         op_counter, "DEL_ADDRESS", op_name);
854     GNUNET_free (op_name);
855     return GNUNET_SYSERR;
856   }
857   GNUNET_free (op_name);
858
859   /* address id */
860   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
861   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
862       sec_name, op_name, &o->address_id))
863   {
864     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
865         op_counter, "DEL_ADDRESS", op_name);
866     GNUNET_free (op_name);
867     return GNUNET_SYSERR;
868   }
869   GNUNET_free (op_name);
870
871   /* plugin */
872   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
873   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
874       sec_name, op_name, &o->plugin))
875   {
876     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
877         op_counter, "DEL_ADDRESS", op_name);
878     GNUNET_free (op_name);
879     return GNUNET_SYSERR;
880   }
881   GNUNET_free (op_name);
882
883   /* address  */
884   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
885   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
886       sec_name, op_name, &o->address))
887   {
888     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
889         op_counter, "DEL_ADDRESS", op_name);
890     GNUNET_free (op_name);
891     return GNUNET_SYSERR;
892   }
893   GNUNET_free (op_name);
894
895   /* session */
896   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
897   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
898       sec_name, op_name, &o->address_session))
899   {
900     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
901         op_counter, "DEL_ADDRESS", op_name);
902     GNUNET_free (op_name);
903     return GNUNET_SYSERR;
904   }
905   GNUNET_free (op_name);
906
907   /* network */
908   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
909   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
910       sec_name, op_name, &o->address_network))
911   {
912     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
913         op_counter, "DEL_ADDRESS", op_name);
914     GNUNET_free (op_name);
915     return GNUNET_SYSERR;
916   }
917   GNUNET_free (op_name);
918
919   fprintf (stderr,
920       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
921       "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
922
923   return GNUNET_OK;
924 }
925
926 static enum GNUNET_ATS_Property
927 parse_preference_string (const char * str)
928 {
929   int c = 0;
930   char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
931
932   for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
933     if (0 == strcmp(str, props[c]))
934       return c;
935   return 0;
936 };
937
938 static int
939 load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o,
940     struct Episode *e,
941     int op_counter,
942     char *sec_name,
943     const struct GNUNET_CONFIGURATION_Handle *cfg)
944 {
945   char *op_name;
946   char *type;
947   char *pref;
948
949   /* peer id */
950   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
951   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
952       sec_name, op_name, &o->peer_id))
953   {
954     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
955         op_counter, "START_SET_PREFERENCE", op_name);
956     GNUNET_free (op_name);
957     return GNUNET_SYSERR;
958   }
959   GNUNET_free (op_name);
960
961   /* address id */
962   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
963   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
964       sec_name, op_name, &o->address_id))
965   {
966     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
967         op_counter, "START_SET_PREFERENCE", op_name);
968     GNUNET_free (op_name);
969     return GNUNET_SYSERR;
970   }
971   GNUNET_free (op_name);
972
973   /* address id */
974   GNUNET_asprintf(&op_name, "op-%u-client-id", op_counter);
975   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
976       sec_name, op_name, &o->client_id))
977   {
978     fprintf (stderr, "Missing client-id in operation %u `%s' in episode `%s'\n",
979         op_counter, "START_SET_PREFERENCE", op_name);
980     GNUNET_free (op_name);
981     return GNUNET_SYSERR;
982   }
983   GNUNET_free (op_name);
984
985   /* generator */
986   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
987   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
988           sec_name, op_name, &type)) )
989   {
990     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
991         op_counter, "START_SET_PREFERENCE", op_name);
992     GNUNET_free (op_name);
993     return GNUNET_SYSERR;
994   }
995
996   /* Load arguments for set_rate, start_send, set_preference */
997   if (0 == strcmp (type, "constant"))
998   {
999     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1000   }
1001   else if (0 == strcmp (type, "linear"))
1002   {
1003     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1004   }
1005   else if (0 == strcmp (type, "sinus"))
1006   {
1007     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1008   }
1009   else if (0 == strcmp (type, "random"))
1010   {
1011     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1012   }
1013   else
1014   {
1015     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1016         op_counter, op_name, e->id);
1017     GNUNET_free (type);
1018     GNUNET_free (op_name);
1019     return GNUNET_SYSERR;
1020   }
1021   GNUNET_free (type);
1022   GNUNET_free (op_name);
1023
1024
1025   /* Get base rate */
1026   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1027   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1028       sec_name, op_name, &o->base_rate))
1029   {
1030     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1031         op_counter, op_name, e->id);
1032     GNUNET_free (op_name);
1033     return GNUNET_SYSERR;
1034   }
1035   GNUNET_free (op_name);
1036
1037
1038   /* Get max rate */
1039   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1040   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1041       sec_name, op_name, &o->max_rate))
1042   {
1043     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1044         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1045         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1046     {
1047       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1048           op_counter, op_name, e->id);
1049       GNUNET_free (op_name);
1050       return GNUNET_SYSERR;
1051     }
1052   }
1053   GNUNET_free (op_name);
1054
1055   /* Get period */
1056   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1057   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1058       sec_name, op_name, &o->period))
1059   {
1060     o->period = e->duration;
1061   }
1062   GNUNET_free (op_name);
1063
1064   /* Get frequency */
1065   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1066   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1067       sec_name, op_name, &o->frequency))
1068   {
1069       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1070           op_counter, op_name, e->id);
1071       GNUNET_free (op_name);
1072       return GNUNET_SYSERR;
1073   }
1074   GNUNET_free (op_name);
1075
1076   /* Get preference */
1077   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1078   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1079       sec_name, op_name, &pref))
1080   {
1081       fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
1082           op_counter, op_name, e->id);
1083       GNUNET_free (op_name);
1084       return GNUNET_SYSERR;
1085   }
1086
1087   if (0 == (o->pref_type = parse_preference_string(pref)))
1088   {
1089       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1090           op_counter, op_name, e->id);
1091       GNUNET_free (op_name);
1092       GNUNET_free (pref);
1093       return GNUNET_SYSERR;
1094   }
1095   GNUNET_free (pref);
1096   GNUNET_free (op_name);
1097
1098   fprintf (stderr,
1099       "Found operation %s: [%llu:%llu]: %s = %llu\n",
1100       "START_SET_PREFERENCE", o->peer_id, o->address_id,
1101       GNUNET_ATS_print_preference_type(o->pref_type), o->base_rate);
1102
1103   return GNUNET_OK;
1104 }
1105
1106 static int
1107 load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o,
1108     struct Episode *e,
1109     int op_counter,
1110     char *sec_name,
1111     const struct GNUNET_CONFIGURATION_Handle *cfg)
1112 {
1113   char *op_name;
1114   char *pref;
1115
1116   /* peer id */
1117   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1118   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1119       sec_name, op_name, &o->peer_id))
1120   {
1121     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1122         op_counter, "STOP_SET_PREFERENCE", op_name);
1123     GNUNET_free (op_name);
1124     return GNUNET_SYSERR;
1125   }
1126   GNUNET_free (op_name);
1127
1128   /* address id */
1129   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1130   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1131       sec_name, op_name, &o->address_id))
1132   {
1133     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1134         op_counter, "STOP_SET_PREFERENCE", op_name);
1135     GNUNET_free (op_name);
1136     return GNUNET_SYSERR;
1137   }
1138   GNUNET_free (op_name);
1139
1140   /* Get preference */
1141   GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
1142   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1143       sec_name, op_name, &pref))
1144   {
1145     fprintf (stderr, "Missing preference in operation %u `%s' in episode `%s'\n",
1146         op_counter, "STOP_SET_PREFERENCE", op_name);
1147       GNUNET_free (op_name);
1148       return GNUNET_SYSERR;
1149   }
1150
1151   if (0 == (o->pref_type = parse_preference_string(pref)))
1152   {
1153       fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
1154           op_counter, op_name, e->id);
1155       GNUNET_free (op_name);
1156       GNUNET_free (pref);
1157       return GNUNET_SYSERR;
1158   }
1159   GNUNET_free (pref);
1160   GNUNET_free (op_name);
1161
1162   fprintf (stderr,
1163       "Found operation %s: [%llu:%llu]: %s\n",
1164       "STOP_SET_PREFERENCE", o->peer_id, o->address_id,
1165       GNUNET_ATS_print_preference_type(o->pref_type));
1166   return GNUNET_OK;
1167 }
1168
1169 static enum GNUNET_ATS_Property
1170 parse_property_string (const char * str)
1171 {
1172   int c = 0;
1173   char *props[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings;
1174
1175   for (c = 0; c < GNUNET_ATS_PropertyCount; c++)
1176     if (0 == strcmp(str, props[c]))
1177       return c;
1178   return 0;
1179 };
1180
1181 static int
1182 load_op_start_set_property(struct GNUNET_ATS_TEST_Operation *o,
1183     struct Episode *e,
1184     int op_counter,
1185     char *sec_name,
1186     const struct GNUNET_CONFIGURATION_Handle *cfg)
1187 {
1188   char *op_name;
1189   char *type;
1190   char *prop;
1191
1192   /* peer id */
1193   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1194   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1195       sec_name, op_name, &o->peer_id))
1196   {
1197     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1198         op_counter, "START_SET_PROPERTY", op_name);
1199     GNUNET_free (op_name);
1200     return GNUNET_SYSERR;
1201   }
1202   GNUNET_free (op_name);
1203
1204   /* address id */
1205   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1206   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1207       sec_name, op_name, &o->address_id))
1208   {
1209     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1210         op_counter, "START_SET_PROPERTY", op_name);
1211     GNUNET_free (op_name);
1212     return GNUNET_SYSERR;
1213   }
1214   GNUNET_free (op_name);
1215
1216   /* generator */
1217   GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter);
1218   if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1219           sec_name, op_name, &type)) )
1220   {
1221     fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n",
1222         op_counter, "START_SET_PROPERTY", op_name);
1223     GNUNET_free (op_name);
1224     return GNUNET_SYSERR;
1225   }
1226
1227   /* Load arguments for set_rate, start_send, set_preference */
1228   if (0 == strcmp (type, "constant"))
1229   {
1230     o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT;
1231   }
1232   else if (0 == strcmp (type, "linear"))
1233   {
1234     o->gen_type = GNUNET_ATS_TEST_TG_LINEAR;
1235   }
1236   else if (0 == strcmp (type, "sinus"))
1237   {
1238     o->gen_type = GNUNET_ATS_TEST_TG_SINUS;
1239   }
1240   else if (0 == strcmp (type, "random"))
1241   {
1242     o->gen_type = GNUNET_ATS_TEST_TG_RANDOM;
1243   }
1244   else
1245   {
1246     fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n",
1247         op_counter, op_name, e->id);
1248     GNUNET_free (type);
1249     GNUNET_free (op_name);
1250     return GNUNET_SYSERR;
1251   }
1252   GNUNET_free (type);
1253   GNUNET_free (op_name);
1254
1255
1256   /* Get base rate */
1257   GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
1258   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1259       sec_name, op_name, &o->base_rate))
1260   {
1261     fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
1262         op_counter, op_name, e->id);
1263     GNUNET_free (op_name);
1264     return GNUNET_SYSERR;
1265   }
1266   GNUNET_free (op_name);
1267
1268
1269   /* Get max rate */
1270   GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
1271   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1272       sec_name, op_name, &o->max_rate))
1273   {
1274     if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) ||
1275         (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) ||
1276         (GNUNET_ATS_TEST_TG_SINUS == o->gen_type))
1277     {
1278       fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
1279           op_counter, op_name, e->id);
1280       GNUNET_free (op_name);
1281       return GNUNET_SYSERR;
1282     }
1283   }
1284   GNUNET_free (op_name);
1285
1286   /* Get period */
1287   GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
1288   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1289       sec_name, op_name, &o->period))
1290   {
1291     o->period = e->duration;
1292   }
1293   GNUNET_free (op_name);
1294
1295   /* Get frequency */
1296   GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
1297   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
1298       sec_name, op_name, &o->frequency))
1299   {
1300       fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
1301           op_counter, op_name, e->id);
1302       GNUNET_free (op_name);
1303       return GNUNET_SYSERR;
1304   }
1305   GNUNET_free (op_name);
1306
1307   /* Get preference */
1308   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1309   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1310       sec_name, op_name, &prop))
1311   {
1312       fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n",
1313           op_counter, op_name, e->id);
1314       GNUNET_free (op_name);
1315       GNUNET_free_non_null (prop);
1316       return GNUNET_SYSERR;
1317   }
1318
1319   if (0 == (o->prop_type = parse_property_string(prop)))
1320   {
1321       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1322           op_counter, op_name, e->id);
1323       GNUNET_free (op_name);
1324       GNUNET_free (prop);
1325       return GNUNET_SYSERR;
1326   }
1327
1328   GNUNET_free (prop);
1329   GNUNET_free (op_name);
1330
1331   fprintf (stderr,
1332       "Found operation %s: [%llu:%llu] %s = %llu\n",
1333       "START_SET_PROPERTY", o->peer_id, o->address_id,
1334       GNUNET_ATS_print_property_type (o->prop_type), o->base_rate);
1335
1336   return GNUNET_OK;
1337 }
1338
1339 static int
1340 load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o,
1341     struct Episode *e,
1342     int op_counter,
1343     char *sec_name,
1344     const struct GNUNET_CONFIGURATION_Handle *cfg)
1345 {
1346   char *op_name;
1347   char *pref;
1348
1349   /* peer id */
1350   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1351   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1352       sec_name, op_name, &o->peer_id))
1353   {
1354     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1355         op_counter, "STOP_SET_PROPERTY", op_name);
1356     GNUNET_free (op_name);
1357     return GNUNET_SYSERR;
1358   }
1359   GNUNET_free (op_name);
1360
1361   /* address id */
1362   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
1363   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1364       sec_name, op_name, &o->address_id))
1365   {
1366     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
1367         op_counter, "STOP_SET_PROPERTY", op_name);
1368     GNUNET_free (op_name);
1369     return GNUNET_SYSERR;
1370   }
1371   GNUNET_free (op_name);
1372
1373   /* Get property */
1374   GNUNET_asprintf(&op_name, "op-%u-property", op_counter);
1375   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
1376       sec_name, op_name, &pref))
1377   {
1378     fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n",
1379         op_counter, "STOP_SET_PROPERTY", op_name);
1380       GNUNET_free (op_name);
1381       GNUNET_free_non_null (pref);
1382       return GNUNET_SYSERR;
1383   }
1384
1385   if (0 == (o->prop_type = parse_property_string(pref)))
1386   {
1387       fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n",
1388           op_counter, op_name, e->id);
1389       GNUNET_free (op_name);
1390       GNUNET_free (pref);
1391       GNUNET_free_non_null (pref);
1392       return GNUNET_SYSERR;
1393   }
1394
1395   GNUNET_free (pref);
1396   GNUNET_free (op_name);
1397
1398   fprintf (stderr,
1399       "Found operation %s: [%llu:%llu] %s\n",
1400       "STOP_SET_PROPERTY", o->peer_id, o->address_id,
1401       GNUNET_ATS_print_property_type (o->prop_type));
1402
1403   return GNUNET_OK;
1404 }
1405
1406
1407 static int
1408 load_op_start_request (struct GNUNET_ATS_TEST_Operation *o,
1409     struct Episode *e,
1410     int op_counter,
1411     char *sec_name,
1412     const struct GNUNET_CONFIGURATION_Handle *cfg)
1413 {
1414   char *op_name;
1415
1416   /* peer id */
1417   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1418   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1419       sec_name, op_name, &o->peer_id))
1420   {
1421     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1422         op_counter, "START_REQUEST", op_name);
1423     GNUNET_free (op_name);
1424     return GNUNET_SYSERR;
1425   }
1426   GNUNET_free (op_name);
1427   return GNUNET_OK;
1428 }
1429
1430 static int
1431 load_op_stop_request (struct GNUNET_ATS_TEST_Operation *o,
1432     struct Episode *e,
1433     int op_counter,
1434     char *sec_name,
1435     const struct GNUNET_CONFIGURATION_Handle *cfg)
1436 {
1437   char *op_name;
1438
1439   /* peer id */
1440   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
1441   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
1442       sec_name, op_name, &o->peer_id))
1443   {
1444     fprintf (stderr, "Missing peer-id in operation %u  `%s' in episode `%s'\n",
1445         op_counter, "STOP_REQUEST", op_name);
1446     GNUNET_free (op_name);
1447     return GNUNET_SYSERR;
1448   }
1449   GNUNET_free (op_name);
1450   return GNUNET_OK;
1451 }
1452
1453
1454 static int
1455 load_episode (struct Experiment *e, struct Episode *cur,
1456     struct GNUNET_CONFIGURATION_Handle *cfg)
1457 {
1458   struct GNUNET_ATS_TEST_Operation *o;
1459   char *sec_name;
1460   char *op_name;
1461   char *op;
1462   int op_counter = 0;
1463   int res;
1464   fprintf (stderr, "Parsing episode %u\n",cur->id);
1465   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
1466
1467   while (1)
1468   {
1469     /* Load operation */
1470     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
1471     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
1472         sec_name, op_name, &op))
1473     {
1474       GNUNET_free (op_name);
1475       break;
1476     }
1477     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
1478     /* operations = set_rate, start_send, stop_send, set_preference */
1479     if (0 == strcmp (op, "address_add"))
1480     {
1481       o->type = SOLVER_OP_ADD_ADDRESS;
1482       res = load_op_add_address (o, cur,
1483           op_counter, sec_name, cfg);
1484     }
1485     else if (0 == strcmp (op, "address_del"))
1486     {
1487       o->type = SOLVER_OP_DEL_ADDRESS;
1488       res = load_op_del_address (o, cur,
1489           op_counter, sec_name, cfg);
1490     }
1491     else if (0 == strcmp (op, "start_set_property"))
1492     {
1493       o->type = SOLVER_OP_START_SET_PROPERTY;
1494       res = load_op_start_set_property (o, cur,
1495           op_counter, sec_name, cfg);
1496     }
1497     else if (0 == strcmp (op, "stop_set_property"))
1498     {
1499       o->type = SOLVER_OP_STOP_SET_PROPERTY;
1500       res = load_op_stop_set_property (o, cur,
1501           op_counter, sec_name, cfg);
1502     }
1503     else if (0 == strcmp (op, "start_set_preference"))
1504     {
1505       o->type = SOLVER_OP_START_SET_PREFERENCE;
1506       res =  load_op_start_set_preference (o, cur,
1507           op_counter, sec_name, cfg);
1508     }
1509     else if (0 == strcmp (op, "stop_set_preference"))
1510     {
1511       o->type = SOLVER_OP_STOP_SET_PREFERENCE;
1512       res =  load_op_stop_set_preference (o, cur,
1513           op_counter, sec_name, cfg);
1514     }
1515     else if (0 == strcmp (op, "start_request"))
1516     {
1517       o->type = SOLVER_OP_START_REQUEST;
1518       res = load_op_start_request (o, cur,
1519           op_counter, sec_name, cfg);
1520     }
1521     else if (0 == strcmp (op, "stop_request"))
1522     {
1523       o->type = SOLVER_OP_STOP_REQUEST;
1524       res = load_op_stop_request(o, cur,
1525           op_counter, sec_name, cfg);
1526     }
1527     else
1528     {
1529       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
1530           op_counter, op, cur->id);
1531       res = GNUNET_SYSERR;
1532     }
1533
1534     GNUNET_free (op);
1535     GNUNET_free (op_name);
1536
1537     if (GNUNET_SYSERR == res)
1538     {
1539       GNUNET_free (o);
1540       GNUNET_free (sec_name);
1541       return GNUNET_SYSERR;
1542     }
1543
1544     GNUNET_CONTAINER_DLL_insert_tail (cur->head,cur->tail, o);
1545     op_counter++;
1546   }
1547   GNUNET_free (sec_name);
1548   return GNUNET_OK;
1549 }
1550
1551 static int
1552 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
1553 {
1554   int e_counter = 0;
1555   char *sec_name;
1556   struct GNUNET_TIME_Relative e_duration;
1557   struct Episode *cur;
1558   struct Episode *last;
1559
1560   e_counter = 0;
1561   last = NULL;
1562   while (1)
1563   {
1564     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
1565     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
1566         sec_name, "duration", &e_duration))
1567     {
1568       fprintf (stderr, "Missing duration in episode %u \n",e_counter);
1569       GNUNET_free (sec_name);
1570       break;
1571     }
1572
1573     cur = GNUNET_new (struct Episode);
1574     cur->duration = e_duration;
1575     cur->id = e_counter;
1576
1577     if (GNUNET_OK != load_episode (e, cur, cfg))
1578     {
1579       GNUNET_free (sec_name);
1580       GNUNET_free (cur);
1581       return GNUNET_SYSERR;
1582     }
1583
1584     fprintf (stderr, "Found episode %u with duration %s \n",
1585         e_counter,
1586         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
1587
1588     /* Update experiment */
1589     e->num_episodes ++;
1590     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
1591     /* Put in linked list */
1592     if (NULL == last)
1593       e->start = cur;
1594     else
1595       last->next = cur;
1596
1597     GNUNET_free (sec_name);
1598     e_counter ++;
1599     last = cur;
1600   }
1601   return e_counter;
1602 }
1603
1604 static void
1605 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1606 {
1607   struct Experiment *e = cls;
1608   e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1609   fprintf (stderr, "Experiment timeout!\n");
1610
1611   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1612   {
1613     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1614     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1615   }
1616
1617   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
1618       GNUNET_SYSERR);
1619 }
1620
1621 struct ATS_Address *
1622 create_ats_address (const struct GNUNET_PeerIdentity *peer,
1623                 const char *plugin_name,
1624                 const void *plugin_addr, size_t plugin_addr_len,
1625                 uint32_t session_id)
1626 {
1627   struct ATS_Address *aa = NULL;
1628
1629   aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len + strlen (plugin_name) + 1);
1630   aa->peer = *peer;
1631   aa->addr_len = plugin_addr_len;
1632   aa->addr = &aa[1];
1633   aa->plugin = (char *) &aa[1] + plugin_addr_len;
1634   memcpy (&aa[1], plugin_addr, plugin_addr_len);
1635   memcpy (aa->plugin, plugin_name, strlen (plugin_name) + 1);
1636   aa->session_id = session_id;
1637   aa->active = GNUNET_NO;
1638   aa->used = GNUNET_NO;
1639   aa->solver_information = NULL;
1640   aa->assigned_bw_in = GNUNET_BANDWIDTH_value_init(0);
1641   aa->assigned_bw_out = GNUNET_BANDWIDTH_value_init(0);
1642   return aa;
1643 }
1644
1645
1646
1647 static void
1648 enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
1649 {
1650   struct TestPeer *p;
1651   struct TestAddress *a;
1652
1653   if (NULL == (p = find_peer_by_id (op->peer_id)))
1654   {
1655     p = GNUNET_new (struct TestPeer);
1656     p->id = op->peer_id;
1657     memset (&p->peer_id, op->peer_id, sizeof (p->peer_id));
1658     GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, p);
1659   }
1660
1661   if (NULL != (a = find_address_by_id (p, op->address_id)))
1662   {
1663     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Duplicate address %u for peer %u\n",
1664         op->address_id, op->peer_id);
1665   }
1666
1667   a = GNUNET_new (struct TestAddress);
1668   a->aid = op->address_id;
1669   a->ats_addr = create_ats_address (&p->peer_id, op->plugin, op->address,
1670       strlen (op->address) + 1, op->address_session);
1671   memset (&p->peer_id, op->peer_id, sizeof (p->peer_id));
1672   GNUNET_CONTAINER_DLL_insert (p->addr_head, p->addr_tail, a);
1673
1674   GNUNET_CONTAINER_multipeermap_put (sh->addresses, &p->peer_id, a->ats_addr,
1675     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1676
1677   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding address %u for peer %u\n",
1678     op->address_id, op->peer_id);
1679
1680   sh->env.sf.s_add (sh->solver, a->ats_addr, op->address_network);
1681
1682 }
1683
1684
1685 static void
1686 enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
1687 {
1688   struct TestPeer *p;
1689   struct TestAddress *a;
1690   struct AddressLookupCtx ctx;
1691
1692   if (NULL == (p = find_peer_by_id (op->peer_id)))
1693   {
1694     GNUNET_break (0);
1695     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1696         "Deleting address for unknown peer %u\n", op->peer_id);
1697     return;
1698   }
1699
1700   ctx.plugin = op->plugin;
1701   ctx.addr = op->address;
1702   ctx.res = NULL;
1703   GNUNET_CONTAINER_multipeermap_get_multiple (sh->addresses, &p->peer_id,
1704       find_address_it, &ctx);
1705   if (NULL == ctx.res)
1706   {
1707     GNUNET_break (0);
1708     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1709         "Deleting unknown address for peer %u\n", op->peer_id);
1710     return;
1711   }
1712
1713   if (NULL == (a = find_address_by_id (p, op->address_id)))
1714   {
1715     GNUNET_break (0);
1716     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1717         "Deleting address for unknown peer %u\n", op->peer_id);
1718     return;
1719   }
1720   GNUNET_CONTAINER_DLL_remove (p->addr_head, p->addr_tail, a);
1721
1722   GNUNET_CONTAINER_multipeermap_remove (sh->addresses, &p->peer_id, ctx.res);
1723
1724   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Removing address %u for peer %u\n",
1725       op->address_id, op->peer_id);
1726
1727   sh->env.sf.s_del (sh->solver, ctx.res, GNUNET_NO);
1728   GNUNET_free (ctx.res);
1729
1730 }
1731
1732 static void
1733 enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
1734 {
1735   struct PropertyGenerator *pg;
1736   struct TestPeer *p;
1737   struct TestAddress *a;
1738
1739   if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type)))
1740   {
1741     GNUNET_ATS_solver_generate_property_stop (pg);
1742     GNUNET_free (pg);
1743   }
1744
1745   if (NULL == (p = find_peer_by_id (op->peer_id)))
1746   {
1747     GNUNET_break (0);
1748     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1749         "Starting property generation for unknown peer %u\n", op->peer_id);
1750     return;
1751   }
1752
1753   if (NULL == (a = find_address_by_id (p, op->address_id)))
1754   {
1755     GNUNET_break (0);
1756     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1757         "Setting property for unknown address %u\n", op->peer_id);
1758     return;
1759   }
1760
1761   GNUNET_ATS_solver_generate_property_start (op->peer_id,
1762     op->address_id,
1763     p, a,
1764     op->gen_type,
1765     op->base_rate,
1766     op->max_rate,
1767     op->period,
1768     op->frequency,
1769     op->prop_type);
1770 }
1771
1772 static void
1773 enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
1774 {
1775   struct PropertyGenerator *pg = find_prop_gen(op->peer_id, op->address_id,
1776       op->prop_type);
1777   if (NULL != pg)
1778       GNUNET_ATS_solver_generate_property_stop (pg);
1779 }
1780
1781 static void
1782 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
1783 {
1784   struct PreferenceGenerator *pg;
1785   struct TestPeer *p;
1786   if (NULL != (pg = find_pref_gen (op->peer_id, op->address_id, op->pref_type)))
1787   {
1788     GNUNET_ATS_solver_generate_preferences_stop (pg);
1789     GNUNET_free (pg);
1790   }
1791
1792   if (NULL == (p = find_peer_by_id (op->peer_id)))
1793   {
1794     GNUNET_break (0);
1795     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1796         "Starting preference generation for unknown peer %u\n", op->peer_id);
1797     return;
1798   }
1799
1800   GNUNET_ATS_solver_generate_preferences_start (op->peer_id,
1801     op->address_id,
1802     op->client_id,
1803     op->gen_type,
1804     op->base_rate,
1805     op->max_rate,
1806     op->period,
1807     op->frequency,
1808     op->pref_type);
1809 }
1810
1811 static void
1812 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
1813 {
1814   struct PreferenceGenerator *pg = find_pref_gen(op->peer_id, op->address_id,
1815       op->pref_type);
1816   if (NULL != pg)
1817       GNUNET_ATS_solver_generate_preferences_stop (pg);
1818 }
1819
1820
1821 static void
1822 enforce_start_request (struct GNUNET_ATS_TEST_Operation *op)
1823 {
1824   struct TestPeer *p;
1825   const struct ATS_Address *res;
1826
1827   if (NULL == (p = find_peer_by_id (op->peer_id)))
1828   {
1829     GNUNET_break (0);
1830     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1831         "Requesting address for unknown peer %u\n", op->peer_id);
1832     return;
1833   }
1834
1835   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting address for peer %u\n",
1836       op->peer_id);
1837
1838   res = sh->env.sf.s_get (sh->solver, &p->peer_id);
1839   if (NULL != res)
1840   {
1841
1842   }
1843
1844 }
1845
1846 static void
1847 enforce_stop_request (struct GNUNET_ATS_TEST_Operation *op)
1848 {
1849   struct TestPeer *p;
1850
1851   if (NULL == (p = find_peer_by_id (op->peer_id)))
1852   {
1853     GNUNET_break (0);
1854     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1855         "Requesting address for unknown peer %u\n", op->peer_id);
1856     return;
1857   }
1858
1859   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop requesting address for peer %u\n",
1860       op->peer_id);
1861
1862   sh->env.sf.s_get_stop (sh->solver, &p->peer_id);
1863 }
1864
1865 static void enforce_episode (struct Episode *ep)
1866 {
1867   struct GNUNET_ATS_TEST_Operation *cur;
1868   for (cur = ep->head; NULL != cur; cur = cur->next)
1869   {
1870     switch (cur->type) {
1871       case SOLVER_OP_ADD_ADDRESS:
1872         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1873             print_op (cur->type), cur->peer_id, cur->address_id);
1874         enforce_add_address (cur);
1875         break;
1876       case SOLVER_OP_DEL_ADDRESS:
1877         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
1878             print_op (cur->type), cur->peer_id, cur->address_id);
1879         enforce_del_address (cur);
1880         break;
1881       case SOLVER_OP_START_SET_PROPERTY:
1882         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1883             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1884         enforce_start_property (cur);
1885         break;
1886       case SOLVER_OP_STOP_SET_PROPERTY:
1887         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1888             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1889         enforce_stop_property (cur);
1890         break;
1891       case SOLVER_OP_START_SET_PREFERENCE:
1892         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1893             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1894         enforce_start_preference (cur);
1895         break;
1896       case SOLVER_OP_STOP_SET_PREFERENCE:
1897         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
1898             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
1899         enforce_stop_preference (cur);
1900         break;
1901       case SOLVER_OP_START_REQUEST:
1902         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
1903             print_op (cur->type), cur->peer_id);
1904         enforce_start_request (cur);
1905         break;
1906       case SOLVER_OP_STOP_REQUEST:
1907         fprintf (stderr, "Enforcing operation: %s [%llu]\n",
1908             print_op (cur->type), cur->peer_id);
1909         enforce_stop_request (cur);
1910         break;
1911       default:
1912         break;
1913     }
1914   }
1915 }
1916
1917 static void
1918 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
1919 {
1920   struct Experiment *e = cls;
1921   e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1922   if (NULL != e->ep_done_cb)
1923     e->ep_done_cb (e->cur);
1924
1925   /* Scheduling next */
1926   e->cur = e->cur->next;
1927   if (NULL == e->cur)
1928   {
1929     /* done */
1930     fprintf (stderr, "Last episode done!\n");
1931     if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1932     {
1933       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1934       e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1935     }
1936     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
1937     return;
1938   }
1939
1940   fprintf (stderr, "Running episode %u with timeout %s\n",
1941       e->cur->id,
1942       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1943   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1944       &timeout_episode, e);
1945   enforce_episode(e->cur);
1946
1947
1948 }
1949
1950
1951 void
1952 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
1953     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
1954     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
1955 {
1956   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
1957       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
1958   e->e_done_cb = e_done_cb;
1959   e->ep_done_cb = ep_done_cb;
1960   e->start_time = GNUNET_TIME_absolute_get();
1961
1962   /* Start total time out */
1963   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
1964       &timeout_experiment, e);
1965
1966
1967   /* Start */
1968   if (NULL == e->start)
1969   {
1970     GNUNET_break (0);
1971     return;
1972   }
1973   e->cur = e->start;
1974   fprintf (stderr, "Running episode %u with timeout %s\n",
1975       e->cur->id,
1976       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
1977   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
1978       &timeout_episode, e);
1979   enforce_episode(e->cur);
1980
1981 }
1982
1983 void
1984 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
1985 {
1986   if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
1987   {
1988     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1989     e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1990   }
1991   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1992   {
1993     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1994     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1995   }
1996   if (NULL != e->cfg)
1997   {
1998     GNUNET_CONFIGURATION_destroy(e->cfg);
1999     e->cfg = NULL;
2000   }
2001   free_experiment (e);
2002 }
2003
2004
2005 struct Experiment *
2006 GNUNET_ATS_solvers_experimentation_load (char *filename)
2007 {
2008   struct Experiment *e;
2009   struct GNUNET_CONFIGURATION_Handle *cfg;
2010   e = NULL;
2011
2012   cfg = GNUNET_CONFIGURATION_create();
2013   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
2014   {
2015     fprintf (stderr, "Failed to load `%s'\n", filename);
2016     GNUNET_CONFIGURATION_destroy (cfg);
2017     return NULL;
2018   }
2019
2020   e = create_experiment ();
2021
2022   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
2023       "name", &e->name))
2024   {
2025     fprintf (stderr, "Invalid %s", "name");
2026     free_experiment (e);
2027     return NULL;
2028   }
2029   else
2030     fprintf (stderr, "Experiment name: `%s'\n", e->name);
2031
2032   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
2033       "cfg_file", &e->cfg_file))
2034   {
2035     fprintf (stderr, "Invalid %s", "cfg_file");
2036     free_experiment (e);
2037     return NULL;
2038   }
2039   else
2040   {
2041     fprintf (stderr, "Experiment configuration: `%s'\n", e->cfg_file);
2042     e->cfg = GNUNET_CONFIGURATION_create();
2043     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
2044     {
2045       fprintf (stderr, "Invalid configuration %s", "cfg_file");
2046       free_experiment (e);
2047       return NULL;
2048     }
2049
2050   }
2051
2052   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2053       "log_freq", &e->log_freq))
2054   {
2055     fprintf (stderr, "Invalid %s", "log_freq");
2056     free_experiment (e);
2057     return NULL;
2058   }
2059   else
2060     fprintf (stderr, "Experiment logging frequency: `%s'\n",
2061         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
2062
2063   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
2064       "max_duration", &e->max_duration))
2065   {
2066     fprintf (stderr, "Invalid %s", "max_duration");
2067     free_experiment (e);
2068     return NULL;
2069   }
2070   else
2071     fprintf (stderr, "Experiment duration: `%s'\n",
2072         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
2073
2074   if (GNUNET_SYSERR == load_episodes (e, cfg))
2075   {
2076     GNUNET_ATS_solvers_experimentation_stop (e);
2077     GNUNET_CONFIGURATION_destroy (cfg);
2078     e = NULL;
2079     fprintf (stderr, "Failed to load experiment\n");
2080     return NULL;
2081   }
2082   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
2083       e->num_episodes,
2084       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
2085
2086   GNUNET_CONFIGURATION_destroy (cfg);
2087   return e;
2088 }
2089
2090
2091
2092 /**
2093  * Solver
2094  */
2095
2096 static int
2097 free_all_it (void *cls,
2098     const struct GNUNET_PeerIdentity *key,
2099     void *value)
2100 {
2101   struct ATS_Address *address = value;
2102   GNUNET_CONTAINER_multipeermap_remove (sh->env.addresses, key, value);
2103   GNUNET_free (address);
2104
2105   return GNUNET_OK;
2106 }
2107
2108 void
2109 GNUNET_ATS_solvers_solver_stop (struct SolverHandle *sh)
2110 {
2111  GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats,
2112      GNUNET_NO);
2113  GNUNET_PLUGIN_unload (sh->plugin, sh->solver);
2114  GNUNET_CONTAINER_multipeermap_iterate (sh->addresses, &free_all_it, NULL);
2115  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
2116  GNUNET_free (sh->plugin);
2117  GNUNET_free (sh);
2118 }
2119
2120 /**
2121  * Load quotas for networks from configuration
2122  *
2123  * @param cfg configuration handle
2124  * @param out_dest where to write outbound quotas
2125  * @param in_dest where to write inbound quotas
2126  * @param dest_length length of inbound and outbound arrays
2127  * @return number of networks loaded
2128  */
2129 unsigned int
2130 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
2131                                                  unsigned long long *out_dest,
2132                                                  unsigned long long *in_dest,
2133                                                  int dest_length)
2134 {
2135   char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
2136   char * entry_in = NULL;
2137   char * entry_out = NULL;
2138   char * quota_out_str;
2139   char * quota_in_str;
2140   int c;
2141   int res;
2142
2143   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
2144   {
2145     in_dest[c] = 0;
2146     out_dest[c] = 0;
2147     GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]);
2148     GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]);
2149
2150     /* quota out */
2151     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
2152     {
2153       res = GNUNET_NO;
2154       if (0 == strcmp(quota_out_str, BIG_M_STRING))
2155       {
2156         out_dest[c] = GNUNET_ATS_MaxBandwidth;
2157         res = GNUNET_YES;
2158       }
2159       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
2160         res = GNUNET_YES;
2161       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
2162          res = GNUNET_YES;
2163
2164       if (GNUNET_NO == res)
2165       {
2166           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2167               network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth);
2168           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2169       }
2170       else
2171       {
2172           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"),
2173               network_str[c], out_dest[c]);
2174       }
2175       GNUNET_free (quota_out_str);
2176     }
2177     else
2178     {
2179       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
2180           network_str[c], GNUNET_ATS_DefaultBandwidth);
2181       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2182     }
2183
2184     /* quota in */
2185     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
2186     {
2187       res = GNUNET_NO;
2188       if (0 == strcmp(quota_in_str, BIG_M_STRING))
2189       {
2190         in_dest[c] = GNUNET_ATS_MaxBandwidth;
2191         res = GNUNET_YES;
2192       }
2193       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
2194         res = GNUNET_YES;
2195       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
2196          res = GNUNET_YES;
2197
2198       if (GNUNET_NO == res)
2199       {
2200           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
2201               network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth);
2202           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
2203       }
2204       else
2205       {
2206           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"),
2207               network_str[c], in_dest[c]);
2208       }
2209       GNUNET_free (quota_in_str);
2210     }
2211     else
2212     {
2213       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
2214           network_str[c], GNUNET_ATS_DefaultBandwidth);
2215       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
2216     }
2217     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]);
2218     GNUNET_free (entry_out);
2219     GNUNET_free (entry_in);
2220   }
2221   return GNUNET_ATS_NetworkTypeCount;
2222 }
2223
2224 /**
2225  * Information callback for the solver
2226  *
2227  * @param op the solver operation
2228  * @param stat status of the solver operation
2229  * @param add additional solver information
2230  */
2231 static void
2232 solver_info_cb (void *cls,
2233     enum GAS_Solver_Operation op,
2234     enum GAS_Solver_Status stat,
2235     enum GAS_Solver_Additional_Information add)
2236 {
2237   char *add_info;
2238   switch (add) {
2239     case GAS_INFO_NONE:
2240       add_info = "GAS_INFO_NONE";
2241       break;
2242     case GAS_INFO_FULL:
2243       add_info = "GAS_INFO_MLP_FULL";
2244       break;
2245     case GAS_INFO_UPDATED:
2246       add_info = "GAS_INFO_MLP_UPDATED";
2247       break;
2248     case GAS_INFO_PROP_ALL:
2249       add_info = "GAS_INFO_PROP_ALL";
2250       break;
2251     case GAS_INFO_PROP_SINGLE:
2252       add_info = "GAS_INFO_PROP_SINGLE";
2253       break;
2254     default:
2255       add_info = "INVALID";
2256       break;
2257   }
2258
2259   switch (op)
2260   {
2261     case GAS_OP_SOLVE_START:
2262       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2263           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
2264           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2265       return;
2266     case GAS_OP_SOLVE_STOP:
2267       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2268           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
2269           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
2270       return;
2271
2272     case GAS_OP_SOLVE_SETUP_START:
2273       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2274           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
2275           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2276       return;
2277
2278     case GAS_OP_SOLVE_SETUP_STOP:
2279       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2280           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
2281           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2282       return;
2283
2284     case GAS_OP_SOLVE_MLP_LP_START:
2285       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2286           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
2287           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2288       return;
2289     case GAS_OP_SOLVE_MLP_LP_STOP:
2290       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2291           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
2292           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2293       return;
2294
2295     case GAS_OP_SOLVE_MLP_MLP_START:
2296       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2297           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
2298           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2299       return;
2300     case GAS_OP_SOLVE_MLP_MLP_STOP:
2301       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2302           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
2303           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2304       return;
2305     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
2306       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2307           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
2308           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2309       return;
2310     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
2311       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2312           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
2313           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
2314       return;
2315     default:
2316       break;
2317     }
2318 }
2319
2320 static void
2321 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
2322 {
2323   if ( (0 == ntohl (address->assigned_bw_out.value__)) &&
2324        (0 == ntohl (address->assigned_bw_in.value__)) )
2325   {
2326     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2327                 "Solver notified to disconnect peer `%s'\n",
2328                 GNUNET_i2s (&address->peer));
2329     return;
2330   }
2331
2332   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2333               "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
2334               GNUNET_i2s (&address->peer),
2335               address,
2336               (unsigned int) ntohl (address->assigned_bw_out.value__),
2337               (unsigned int) ntohl (address->assigned_bw_in.value__));
2338   /*if (GNUNET_YES == ph.bulk_running)
2339     GNUNET_break (0);*/
2340   return;
2341 }
2342
2343 const double *
2344 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
2345 {
2346   return GAS_normalization_get_preferences_by_peer (id);
2347 }
2348
2349
2350 const double *
2351 get_property_cb (void *cls, const struct ATS_Address *address)
2352 {
2353   return GAS_normalization_get_properties ((struct ATS_Address *) address);
2354 }
2355
2356 static void
2357 normalized_property_changed_cb (void *cls, struct ATS_Address *address,
2358     uint32_t type, double prop_rel)
2359 {
2360   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2361       "Normalized property %s for peer `%s' changed to %.3f \n",
2362       GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer),
2363       prop_rel);
2364
2365   sh->env.sf.s_address_update_property (sh->solver, address, type, 0, prop_rel);
2366 }
2367
2368
2369 static void
2370 normalized_preference_changed_cb (void *cls,
2371     const struct GNUNET_PeerIdentity *peer,
2372     enum GNUNET_ATS_PreferenceKind kind,
2373     double pref_rel)
2374 {
2375   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
2376       "Normalized preference %s for peer `%s' changed to %.3f \n",
2377       GNUNET_ATS_print_preference_type (kind), GNUNET_i2s (peer),
2378       pref_rel);
2379
2380   sh->env.sf.s_pref (sh->solver, peer, kind, pref_rel);
2381 }
2382
2383
2384 struct SolverHandle *
2385 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
2386 {
2387   struct SolverHandle *sh;
2388   char * solver_str;
2389
2390   switch (type) {
2391     case GNUNET_ATS_SOLVER_PROPORTIONAL:
2392       solver_str = "proportional";
2393       break;
2394     case GNUNET_ATS_SOLVER_MLP:
2395       solver_str = "mlp";
2396       break;
2397     case GNUNET_ATS_SOLVER_RIL:
2398       solver_str = "ril";
2399       break;
2400     default:
2401       GNUNET_break (0);
2402       return NULL;
2403       break;
2404   }
2405
2406   sh = GNUNET_new (struct SolverHandle);
2407   GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
2408
2409   sh->addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
2410   /* setup environment */
2411   sh->env.cfg = e->cfg;
2412   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
2413   sh->env.addresses = sh->addresses;
2414   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
2415   sh->env.get_preferences = &get_preferences_cb;
2416   sh->env.get_property = &get_property_cb;
2417   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
2418   sh->env.info_cb = &solver_info_cb;
2419   sh->env.info_cb_cls = NULL;
2420
2421
2422   /* start normalization */
2423   GAS_normalization_start (&normalized_preference_changed_cb, NULL,
2424       &normalized_property_changed_cb, NULL );
2425
2426   /* load quotas */
2427   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
2428       sh->env.out_quota, sh->env.in_quota, GNUNET_ATS_NetworkTypeCount))
2429   {
2430     GNUNET_break(0);
2431     GNUNET_free (sh->plugin);
2432     GNUNET_free (sh);
2433     end_now ();
2434     return NULL;
2435   }
2436
2437   sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
2438   if (NULL == sh->solver)
2439   {
2440     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
2441     GNUNET_break(0);
2442     GNUNET_free (sh->plugin);
2443     GNUNET_free (sh);
2444     end_now ();
2445     return NULL;
2446   }
2447   return sh;
2448 }
2449
2450 static void
2451 done ()
2452 {
2453   struct TestPeer *cur;
2454   struct TestPeer *next;
2455
2456   struct TestAddress *cur_a;
2457   struct TestAddress *next_a;
2458
2459   /* Stop logging */
2460   GNUNET_ATS_solver_logging_stop (l);
2461
2462   /* Stop all preference generation */
2463   GNUNET_ATS_solver_generate_preferences_stop_all ();
2464
2465   /* Stop all property generation */
2466   GNUNET_ATS_solver_generate_property_stop_all ();
2467
2468   /* Clean up experiment */
2469   if (NULL != e)
2470   {
2471     GNUNET_ATS_solvers_experimentation_stop (e);
2472     e = NULL;
2473   }
2474
2475   if (NULL != l)
2476   {
2477     GNUNET_ATS_solver_logging_free (l);
2478     l = NULL;
2479   }
2480
2481   next = peer_head;
2482   while  (NULL != (cur = next))
2483   {
2484     next = cur->next;
2485     GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, cur);
2486     next_a = cur->addr_head;
2487     while  (NULL != (cur_a = next_a))
2488     {
2489       next_a = cur_a->next;
2490       GNUNET_CONTAINER_DLL_remove (cur->addr_head, cur->addr_tail, cur_a);
2491       GNUNET_free (cur_a);
2492     }
2493     GNUNET_free (cur);
2494   }
2495
2496   if (NULL != sh)
2497   {
2498     GNUNET_ATS_solvers_solver_stop (sh);
2499     sh = NULL;
2500   }
2501   /* Shutdown */
2502   end_now();
2503
2504 }
2505
2506 static void
2507 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
2508 {
2509   if (GNUNET_OK == success)
2510     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
2511         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
2512   else
2513     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
2514
2515
2516   /*
2517   evaluate (duration);
2518   if (opt_log)
2519     GNUNET_ATS_TEST_logging_write_to_file(l, opt_exp_file, opt_plot);
2520
2521   if (NULL != l)
2522   {
2523     GNUNET_ATS_TEST_logging_stop (l);
2524     GNUNET_ATS_TEST_logging_clean_up (l);
2525     l = NULL;
2526   }
2527   */
2528   GNUNET_SCHEDULER_add_now (&done, NULL);
2529 }
2530
2531 static void
2532 episode_done_cb (struct Episode *ep)
2533 {
2534   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
2535 }
2536
2537
2538
2539 /**
2540  * Do shutdown
2541  */
2542 static void
2543 end_now ()
2544 {
2545   if (NULL != e)
2546   {
2547     GNUNET_ATS_solvers_experimentation_stop (e);
2548     e = NULL;
2549   }
2550   if (NULL != sh)
2551   {
2552     GNUNET_ATS_solvers_solver_stop (sh);
2553     sh = NULL;
2554   }
2555 }
2556
2557 static void
2558 run (void *cls, char * const *args, const char *cfgfile,
2559     const struct GNUNET_CONFIGURATION_Handle *cfg)
2560 {
2561   enum GNUNET_ATS_Solvers solver;
2562
2563   if (NULL == opt_exp_file)
2564   {
2565     fprintf (stderr, "No experiment given ...\n");
2566     res = 1;
2567     end_now ();
2568     return;
2569   }
2570
2571   if (NULL == opt_solver)
2572   {
2573     fprintf (stderr, "No solver given ...\n");
2574     res = 1;
2575     end_now ();
2576     return;
2577   }
2578
2579   if (0 == strcmp(opt_solver, "mlp"))
2580   {
2581     solver = GNUNET_ATS_SOLVER_MLP;
2582   }
2583   else if (0 == strcmp(opt_solver, "proportional"))
2584   {
2585     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
2586   }
2587   else if (0 == strcmp(opt_solver, "ril"))
2588   {
2589     solver = GNUNET_ATS_SOLVER_RIL;
2590   }
2591   else
2592   {
2593     fprintf (stderr, "No solver given ...");
2594     res = 1;
2595     end_now ();
2596     return;
2597   }
2598
2599   /* load experiment */
2600   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
2601   if (NULL == e)
2602   {
2603     fprintf (stderr, "Failed to load experiment ...\n");
2604     res = 1;
2605     end_now ();
2606     return;
2607   }
2608
2609   /* load solver */
2610   sh = GNUNET_ATS_solvers_solver_start (solver);
2611   if (NULL == sh)
2612   {
2613     fprintf (stderr, "Failed to start solver ...\n");
2614     end_now ();
2615     res = 1;
2616     return;
2617   }
2618
2619   /* start logging */
2620   l = GNUNET_ATS_solver_logging_start (e->log_freq);
2621
2622   /* run experiment */
2623   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
2624       experiment_done_cb);
2625
2626   /* WAIT */
2627 }
2628
2629
2630 /**
2631  * Main function of the benchmark
2632  *
2633  * @param argc argument count
2634  * @param argv argument values
2635  */
2636 int
2637 main (int argc, char *argv[])
2638 {
2639   opt_exp_file = NULL;
2640   opt_solver = NULL;
2641   opt_log = GNUNET_NO;
2642   opt_plot = GNUNET_NO;
2643
2644   res = 0;
2645
2646   static struct GNUNET_GETOPT_CommandLineOption options[] =
2647   {
2648     { 's', "solver", NULL,
2649         gettext_noop ("solver to use"),
2650         1, &GNUNET_GETOPT_set_string, &opt_solver},
2651     {  'e', "experiment", NULL,
2652       gettext_noop ("experiment to use"),
2653       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
2654     {  'e', "experiment", NULL,
2655       gettext_noop ("experiment to use"),
2656       1, &GNUNET_GETOPT_set_one, &opt_verbose},
2657     GNUNET_GETOPT_OPTION_END
2658   };
2659
2660   GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval",
2661       NULL, options, &run, argv[0]);
2662
2663   return res;
2664 }
2665 /* end of file ats-testing-experiment.c*/
2666