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