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