moved eval tool to ats
[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
31 #define BIG_M_STRING "unlimited"
32
33 static struct Experiment *e;
34
35 static struct GNUNET_ATS_TESTING_SolverHandle *sh;
36
37 /**
38  * cmd option -e: experiment file
39  */
40 static char *opt_exp_file;
41
42 static char *opt_solver;
43
44 /**
45  * cmd option -l: enable logging
46  */
47 static int opt_log;
48
49 /**
50  * cmd option -p: enable plots
51  */
52 static int opt_plot;
53
54 /**
55  * cmd option -v: verbose logs
56  */
57 static int opt_verbose;
58
59 static int res;
60
61 static void
62 end_now ();
63
64 /**
65  * Experiments
66  */
67
68 const char *
69 print_op (enum OperationType op)
70 {
71   switch (op) {
72     case SOLVER_OP_ADD_ADDRESS:
73       return "ADD_ADDRESS";
74     case SOLVER_OP_DEL_ADDRESS:
75       return "DEL_ADDRESS";
76     case SOLVER_OP_START_SET_PREFERENCE:
77       return "START_SET_PREFERENCE";
78     case SOLVER_OP_STOP_SET_PREFERENCE:
79       return "STOP_STOP_PREFERENCE";
80     case SOLVER_OP_START_SET_PROPERTY:
81           return "START_SET_PROPERTY";
82     case SOLVER_OP_STOP_SET_PROPERTY:
83       return "STOP_SET_PROPERTY";
84     default:
85       break;
86   }
87   return "";
88 }
89
90
91 static struct Experiment *
92 create_experiment ()
93 {
94   struct Experiment *e;
95   e = GNUNET_new (struct Experiment);
96   e->name = NULL;
97   e->num_masters = 0;
98   e->num_slaves = 0;
99   e->start = NULL;
100   e->total_duration = GNUNET_TIME_UNIT_ZERO;
101   return e;
102 }
103
104 static void
105 free_experiment (struct Experiment *e)
106 {
107   struct Episode *cur;
108   struct Episode *next;
109   struct GNUNET_ATS_TEST_Operation *cur_o;
110   struct GNUNET_ATS_TEST_Operation *next_o;
111
112   next = e->start;
113   for (cur = next; NULL != cur; cur = next)
114   {
115     next = cur->next;
116
117     next_o = cur->head;
118     for (cur_o = next_o; NULL != cur_o; cur_o = next_o)
119     {
120       next_o = cur_o->next;
121       GNUNET_free (cur_o);
122     }
123     GNUNET_free (cur);
124   }
125
126   GNUNET_free_non_null (e->name);
127   GNUNET_free_non_null (e->cfg_file);
128   GNUNET_free (e);
129 }
130
131
132 static int
133 load_op_add_address (struct GNUNET_ATS_TEST_Operation *o,
134     int op_counter,
135     char *sec_name,
136     const struct GNUNET_CONFIGURATION_Handle *cfg)
137 {
138   char *op_name;
139
140   /* peer id */
141   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
142   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
143       sec_name, op_name, &o->peer_id))
144   {
145     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
146         op_counter, "ADD_ADDRESS", op_name);
147     GNUNET_free (op_name);
148     return GNUNET_SYSERR;
149   }
150   GNUNET_free (op_name);
151
152   /* address id */
153   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
154   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
155       sec_name, op_name, &o->address_id))
156   {
157     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
158         op_counter, "ADD_ADDRESS", op_name);
159     GNUNET_free (op_name);
160     return GNUNET_SYSERR;
161   }
162   GNUNET_free (op_name);
163
164   /* plugin */
165   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
166   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
167       sec_name, op_name, &o->plugin))
168   {
169     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
170         op_counter, "ADD_ADDRESS", op_name);
171     GNUNET_free (op_name);
172     return GNUNET_SYSERR;
173   }
174   GNUNET_free (op_name);
175
176   /* address  */
177   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
178   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
179       sec_name, op_name, &o->address))
180   {
181     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
182         op_counter, "ADD_ADDRESS", op_name);
183     GNUNET_free (op_name);
184     return GNUNET_SYSERR;
185   }
186   GNUNET_free (op_name);
187
188   /* session */
189   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
190   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
191       sec_name, op_name, &o->address_session))
192   {
193     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
194         op_counter, "ADD_ADDRESS", op_name);
195     GNUNET_free (op_name);
196     return GNUNET_SYSERR;
197   }
198   GNUNET_free (op_name);
199
200   /* network */
201   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
202   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
203       sec_name, op_name, &o->address_network))
204   {
205     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
206         op_counter, "ADD_ADDRESS", op_name);
207     GNUNET_free (op_name);
208     return GNUNET_SYSERR;
209   }
210   GNUNET_free (op_name);
211
212   fprintf (stderr,
213       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
214       "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
215
216   return GNUNET_OK;
217 }
218
219 static int
220 load_op_del_address (struct GNUNET_ATS_TEST_Operation *o,
221     int op_counter,
222     char *sec_name,
223     const struct GNUNET_CONFIGURATION_Handle *cfg)
224 {
225   char *op_name;
226
227   /* peer id */
228   GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter);
229   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
230       sec_name, op_name, &o->peer_id))
231   {
232     fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n",
233         op_counter, "DEL_ADDRESS", op_name);
234     GNUNET_free (op_name);
235     return GNUNET_SYSERR;
236   }
237   GNUNET_free (op_name);
238
239   /* address id */
240   GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter);
241   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
242       sec_name, op_name, &o->address_id))
243   {
244     fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n",
245         op_counter, "DEL_ADDRESS", op_name);
246     GNUNET_free (op_name);
247     return GNUNET_SYSERR;
248   }
249   GNUNET_free (op_name);
250
251   /* plugin */
252   GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter);
253   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
254       sec_name, op_name, &o->plugin))
255   {
256     fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n",
257         op_counter, "DEL_ADDRESS", op_name);
258     GNUNET_free (op_name);
259     return GNUNET_SYSERR;
260   }
261   GNUNET_free (op_name);
262
263   /* address  */
264   GNUNET_asprintf(&op_name, "op-%u-address", op_counter);
265   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
266       sec_name, op_name, &o->address))
267   {
268     fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n",
269         op_counter, "DEL_ADDRESS", op_name);
270     GNUNET_free (op_name);
271     return GNUNET_SYSERR;
272   }
273   GNUNET_free (op_name);
274
275   /* session */
276   GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter);
277   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
278       sec_name, op_name, &o->address_session))
279   {
280     fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n",
281         op_counter, "DEL_ADDRESS", op_name);
282     GNUNET_free (op_name);
283     return GNUNET_SYSERR;
284   }
285   GNUNET_free (op_name);
286
287   /* network */
288   GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter);
289   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
290       sec_name, op_name, &o->address_network))
291   {
292     fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n",
293         op_counter, "DEL_ADDRESS", op_name);
294     GNUNET_free (op_name);
295     return GNUNET_SYSERR;
296   }
297   GNUNET_free (op_name);
298
299   fprintf (stderr,
300       "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n",
301       "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin);
302
303   return GNUNET_OK;
304 }
305
306 static int
307 load_episode (struct Experiment *e, struct Episode *cur,
308     struct GNUNET_CONFIGURATION_Handle *cfg)
309 {
310   struct GNUNET_ATS_TEST_Operation *o;
311   char *sec_name;
312   char *op_name;
313   char *op;
314   char *type;
315   char *pref;
316   int op_counter = 0;
317   fprintf (stderr, "Parsing episode %u\n",cur->id);
318   GNUNET_asprintf(&sec_name, "episode-%u", cur->id);
319
320   while (1)
321   {
322     /* Load operation */
323     GNUNET_asprintf(&op_name, "op-%u-operation", op_counter);
324     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg,
325         sec_name, op_name, &op))
326     {
327       GNUNET_free (op_name);
328       break;
329     }
330     o = GNUNET_new (struct GNUNET_ATS_TEST_Operation);
331     /* operations = set_rate, start_send, stop_send, set_preference */
332     if (0 == strcmp (op, "address_add"))
333     {
334       o->type = SOLVER_OP_ADD_ADDRESS;
335       if (GNUNET_SYSERR == load_op_add_address (o, op_counter, sec_name, cfg))
336       {
337         GNUNET_free (o);
338         GNUNET_free (op);
339         GNUNET_free (op_name);
340         return GNUNET_SYSERR;
341       }
342     }
343     else if (0 == strcmp (op, "address_del"))
344     {
345       o->type = SOLVER_OP_DEL_ADDRESS;
346       if (GNUNET_SYSERR == load_op_del_address (o, op_counter, sec_name, cfg))
347       {
348         GNUNET_free (o);
349         GNUNET_free (op);
350         GNUNET_free (op_name);
351         return GNUNET_SYSERR;
352       }
353     }
354     else if (0 == strcmp (op, "start_set_property"))
355     {
356       o->type = SOLVER_OP_START_SET_PROPERTY;
357     }
358     else if (0 == strcmp (op, "stop_set_property"))
359     {
360       o->type = SOLVER_OP_STOP_SET_PROPERTY;
361     }
362     else if (0 == strcmp (op, "start_set_preference"))
363     {
364       o->type = SOLVER_OP_START_SET_PREFERENCE;
365     }
366     else if (0 == strcmp (op, "stop_set_preference"))
367     {
368       o->type = SOLVER_OP_STOP_SET_PREFERENCE;
369     }
370     else
371     {
372       fprintf (stderr, "Invalid operation %u `%s' in episode %u\n",
373           op_counter, op, cur->id);
374       GNUNET_free (op);
375       GNUNET_free (op_name);
376       return GNUNET_SYSERR;
377     }
378     GNUNET_free (op);
379     GNUNET_free (op_name);
380
381     GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o);
382     op_counter++;
383   }
384   GNUNET_free (sec_name);
385
386
387 #if 0
388     /* Get source */
389     GNUNET_asprintf(&op_name, "op-%u-src", op_counter);
390     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
391         sec_name, op_name, &o->src_id))
392     {
393       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
394           op_counter, op, cur->id);
395       GNUNET_free (op);
396       GNUNET_free (op_name);
397       return GNUNET_SYSERR;
398     }
399     if (o->src_id > (e->num_masters - 1))
400     {
401       fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n",
402           o->src_id, op_counter, op, cur->id);
403       GNUNET_free (op);
404       GNUNET_free (op_name);
405       return GNUNET_SYSERR;
406     }
407     GNUNET_free (op_name);
408
409     /* Get destination */
410     GNUNET_asprintf(&op_name, "op-%u-dest", op_counter);
411     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
412         sec_name, op_name, &o->dest_id))
413     {
414       fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n",
415           op_counter, op, cur->id);
416       GNUNET_free (op);
417       GNUNET_free (op_name);
418       return GNUNET_SYSERR;
419     }
420     if (o->dest_id > (e->num_slaves - 1))
421     {
422       fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n",
423           o->dest_id, op_counter, op, cur->id);
424       GNUNET_free (op);
425       GNUNET_free (op_name);
426       return GNUNET_SYSERR;
427     }
428     GNUNET_free (op_name);
429
430     GNUNET_asprintf(&op_name, "op-%u-type", op_counter);
431     if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg,
432             sec_name, op_name, &type)) &&
433         ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type)))
434     {
435       /* Load arguments for set_rate, start_send, set_preference */
436       if (0 == strcmp (type, "constant"))
437       {
438         o->tg_type = GNUNET_ATS_TEST_TG_CONSTANT;
439       }
440       else if (0 == strcmp (type, "linear"))
441       {
442         o->tg_type = GNUNET_ATS_TEST_TG_LINEAR;
443       }
444       else if (0 == strcmp (type, "sinus"))
445       {
446         o->tg_type = GNUNET_ATS_TEST_TG_SINUS;
447       }
448       else if (0 == strcmp (type, "random"))
449       {
450         o->tg_type = GNUNET_ATS_TEST_TG_RANDOM;
451       }
452       else
453       {
454         fprintf (stderr, "Invalid type %u `%s' in episode %u\n",
455             op_counter, op, cur->id);
456         GNUNET_free (type);
457         GNUNET_free (op);
458         GNUNET_free (op_name);
459         return GNUNET_SYSERR;
460       }
461       GNUNET_free (op_name);
462
463       /* Get base rate */
464       GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter);
465       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
466           sec_name, op_name, &o->base_rate))
467       {
468         fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n",
469             op_counter, op, cur->id);
470         GNUNET_free (type);
471         GNUNET_free (op);
472         GNUNET_free (op_name);
473         return GNUNET_SYSERR;
474       }
475       GNUNET_free (op_name);
476
477       /* Get max rate */
478       GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter);
479       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg,
480           sec_name, op_name, &o->max_rate))
481       {
482         if ((GNUNET_ATS_TEST_TG_LINEAR == o->tg_type) ||
483             (GNUNET_ATS_TEST_TG_RANDOM == o->tg_type) ||
484             (GNUNET_ATS_TEST_TG_SINUS == o->tg_type))
485         {
486           fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n",
487               op_counter, op, cur->id);
488           GNUNET_free (type);
489           GNUNET_free (op_name);
490           GNUNET_free (op);
491           return GNUNET_SYSERR;
492         }
493       }
494       GNUNET_free (op_name);
495
496       /* Get period */
497       GNUNET_asprintf(&op_name, "op-%u-period", op_counter);
498       if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
499           sec_name, op_name, &o->period))
500       {
501         o->period = cur->duration;
502       }
503       GNUNET_free (op_name);
504
505       if (START_PREFERENCE == o->type)
506       {
507           /* Get frequency */
508           GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter);
509           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg,
510               sec_name, op_name, &o->frequency))
511           {
512               fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n",
513                   op_counter, op, cur->id);
514               GNUNET_free (type);
515               GNUNET_free (op_name);
516               GNUNET_free (op);
517               return GNUNET_SYSERR;
518           }
519           GNUNET_free (op_name);
520
521           /* Get preference */
522           GNUNET_asprintf(&op_name, "op-%u-pref", op_counter);
523           if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
524               sec_name, op_name, &pref))
525           {
526               fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n",
527                   op_counter, op, cur->id);
528               GNUNET_free (type);
529               GNUNET_free (op_name);
530               GNUNET_free (op);
531               GNUNET_free_non_null (pref);
532               return GNUNET_SYSERR;
533           }
534
535           if (0 == strcmp(pref, "bandwidth"))
536             o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH;
537           else if (0 == strcmp(pref, "latency"))
538             o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY;
539           else
540           {
541               fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n",
542                   op_counter, op, cur->id);
543               GNUNET_free (type);
544               GNUNET_free (op_name);
545               GNUNET_free (op);
546               GNUNET_free (pref);
547               GNUNET_free_non_null (pref);
548               return GNUNET_SYSERR;
549           }
550           GNUNET_free (pref);
551           GNUNET_free (op_name);
552       }
553     }
554
555     /* Safety checks */
556     if ((GNUNET_ATS_TEST_TG_LINEAR == o->tg_type) ||
557         (GNUNET_ATS_TEST_TG_SINUS == o->tg_type))
558     {
559       if ((o->max_rate - o->base_rate) > o->base_rate)
560       {
561         /* This will cause an underflow */
562         GNUNET_break (0);
563       }
564       fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n");
565     }
566
567     if ((START_SEND == o->type) || (START_PREFERENCE == o->type))
568       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n",
569         op_counter, cur->id, print_op (o->type), o->src_id,
570         o->dest_id, (NULL != type) ? type : "",
571         o->base_rate, o->max_rate,
572         GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES));
573     else
574       fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n",
575         op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id);
576
577     GNUNET_free_non_null (type);
578     GNUNET_free (op);
579 #endif
580
581   return GNUNET_OK;
582 }
583
584 static int
585 load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg)
586 {
587   int e_counter = 0;
588   char *sec_name;
589   struct GNUNET_TIME_Relative e_duration;
590   struct Episode *cur;
591   struct Episode *last;
592
593   e_counter = 0;
594   last = NULL;
595   while (1)
596   {
597     GNUNET_asprintf(&sec_name, "episode-%u", e_counter);
598     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg,
599         sec_name, "duration", &e_duration))
600     {
601       GNUNET_free (sec_name);
602       break;
603     }
604
605     cur = GNUNET_new (struct Episode);
606     cur->duration = e_duration;
607     cur->id = e_counter;
608
609     if (GNUNET_OK != load_episode (e, cur, cfg))
610     {
611       GNUNET_free (sec_name);
612       GNUNET_free (cur);
613       return GNUNET_SYSERR;
614     }
615
616     fprintf (stderr, "Found episode %u with duration %s \n",
617         e_counter,
618         GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES));
619
620     /* Update experiment */
621     e->num_episodes ++;
622     e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration);
623     /* Put in linked list */
624     if (NULL == last)
625       e->start = cur;
626     else
627     last->next = cur;
628
629     GNUNET_free (sec_name);
630     e_counter ++;
631     last = cur;
632   }
633   return e_counter;
634 }
635
636 static void
637 timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
638 {
639   struct Experiment *e = cls;
640   e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
641   fprintf (stderr, "Experiment timeout!\n");
642
643   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
644   {
645     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
646     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
647   }
648
649   e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time),
650       GNUNET_SYSERR);
651 }
652
653 static void
654 enforce_add_address (struct GNUNET_ATS_TEST_Operation *op)
655 {
656   /*
657   struct BenchmarkPeer *peer;
658   struct BenchmarkPartner *partner;
659
660   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
661   if (NULL == peer)
662   {
663     GNUNET_break (0);
664     return;
665   }
666
667   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
668   if (NULL == partner)
669   {
670     GNUNET_break (0);
671     return;
672   }
673
674   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
675
676   if (NULL != partner->tg)
677   {
678     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id);
679     GNUNET_ATS_TEST_generate_traffic_stop(partner->tg);
680     partner->tg = NULL;
681   }
682
683   partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner,
684       op->tg_type, op->base_rate, op->max_rate, op->period,
685       GNUNET_TIME_UNIT_FOREVER_REL);
686    */
687 }
688
689 static void
690 enforce_del_address (struct GNUNET_ATS_TEST_Operation *op)
691 {
692   /*
693   struct BenchmarkPartner *p;
694   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
695   if (NULL == p)
696   {
697     GNUNET_break (0);
698     return;
699   }
700
701   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
702
703   if (NULL != p->tg)
704   {
705     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
706         op->src_id, op->dest_id);
707     GNUNET_ATS_TEST_generate_traffic_stop(p->tg);
708     p->tg = NULL;
709   }
710   */
711 }
712
713 static void
714 enforce_start_property (struct GNUNET_ATS_TEST_Operation *op)
715 {
716
717 }
718
719 static void
720 enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op)
721 {
722
723 }
724
725 static void
726 enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op)
727 {
728   /*
729   struct BenchmarkPeer *peer;
730   struct BenchmarkPartner *partner;
731
732   peer = GNUNET_ATS_TEST_get_peer (op->src_id);
733   if (NULL == peer)
734   {
735     GNUNET_break (0);
736     return;
737   }
738
739   partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
740   if (NULL == partner)
741   {
742     GNUNET_break (0);
743     return;
744   }
745
746   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
747
748   if (NULL != partner->pg)
749   {
750     fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",
751         op->src_id, op->dest_id);
752     GNUNET_ATS_TEST_generate_preferences_stop(partner->pg);
753     partner->pg = NULL;
754   }
755
756   partner->pg = GNUNET_ATS_TEST_generate_preferences_start(peer, partner,
757       op->tg_type, op->base_rate, op->max_rate, op->period, op->frequency,
758       op->pref_type);
759       */
760 }
761
762 static void
763 enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op)
764 {
765   /*
766   struct BenchmarkPartner *p;
767   p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id);
768   if (NULL == p)
769   {
770     GNUNET_break (0);
771     return;
772   }
773
774   fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id);
775
776   if (NULL != p->pg)
777   {
778     fprintf (stderr, "Stopping preference between master %llu slave %llu\n",
779         op->src_id, op->dest_id);
780     GNUNET_ATS_TEST_generate_preferences_stop (p->pg);
781     p->pg = NULL;
782   }
783   */
784 }
785
786 static void enforce_episode (struct Episode *ep)
787 {
788   struct GNUNET_ATS_TEST_Operation *cur;
789   for (cur = ep->head; NULL != cur; cur = cur->next)
790   {
791     switch (cur->type) {
792       case SOLVER_OP_ADD_ADDRESS:
793         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
794             print_op (cur->type), cur->peer_id, cur->address_id);
795         enforce_add_address (cur);
796         break;
797       case SOLVER_OP_DEL_ADDRESS:
798         fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n",
799             print_op (cur->type), cur->peer_id, cur->address_id);
800         enforce_del_address (cur);
801         break;
802       case SOLVER_OP_START_SET_PROPERTY:
803         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
804             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
805         enforce_start_property (cur);
806         break;
807       case SOLVER_OP_STOP_SET_PROPERTY:
808         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
809             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
810         enforce_stop_property (cur);
811         break;
812       case SOLVER_OP_START_SET_PREFERENCE:
813         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
814             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
815         enforce_start_preference (cur);
816         break;
817       case SOLVER_OP_STOP_SET_PREFERENCE:
818         fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n",
819             print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate);
820         enforce_stop_preference (cur);
821         break;
822       default:
823         break;
824     }
825   }
826 }
827
828 static void
829 timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc)
830 {
831   struct Experiment *e = cls;
832   e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
833   if (NULL != e->ep_done_cb)
834     e->ep_done_cb (e->cur);
835
836   /* Scheduling next */
837   e->cur = e->cur->next;
838   if (NULL == e->cur)
839   {
840     /* done */
841     fprintf (stderr, "Last episode done!\n");
842     if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
843     {
844       GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
845       e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
846     }
847     e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK);
848     return;
849   }
850
851   fprintf (stderr, "Running episode %u with timeout %s\n",
852       e->cur->id,
853       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
854   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
855       &timeout_episode, e);
856   enforce_episode(e->cur);
857
858
859 }
860
861
862 void
863 GNUNET_ATS_solvers_experimentation_run (struct Experiment *e,
864     GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb,
865     GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb)
866 {
867   fprintf (stderr, "Running experiment `%s'  with timeout %s\n", e->name,
868       GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES));
869   e->e_done_cb = e_done_cb;
870   e->ep_done_cb = ep_done_cb;
871   e->start_time = GNUNET_TIME_absolute_get();
872
873   /* Start total time out */
874   e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration,
875       &timeout_experiment, e);
876
877
878   /* Start */
879   if (NULL == e->start)
880   {
881     GNUNET_break (0);
882     return;
883   }
884   e->cur = e->start;
885   fprintf (stderr, "Running episode %u with timeout %s\n",
886       e->cur->id,
887       GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES));
888   e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration,
889       &timeout_episode, e);
890   enforce_episode(e->cur);
891
892 }
893
894
895 struct Experiment *
896 GNUNET_ATS_solvers_experimentation_load (char *filename)
897 {
898   struct Experiment *e;
899   struct GNUNET_CONFIGURATION_Handle *cfg;
900   e = NULL;
901
902   cfg = GNUNET_CONFIGURATION_create();
903   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename))
904   {
905     fprintf (stderr, "Failed to load `%s'\n", filename);
906     GNUNET_CONFIGURATION_destroy (cfg);
907     return NULL;
908   }
909
910   e = create_experiment ();
911
912   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment",
913       "name", &e->name))
914   {
915     fprintf (stderr, "Invalid %s", "name");
916     free_experiment (e);
917     return NULL;
918   }
919   else
920     fprintf (stderr, "Experiment name: `%s'\n", e->name);
921
922   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment",
923       "cfg_file", &e->cfg_file))
924   {
925     fprintf (stderr, "Invalid %s", "cfg_file");
926     free_experiment (e);
927     return NULL;
928   }
929   else
930   {
931     fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file);
932     e->cfg = GNUNET_CONFIGURATION_create();
933     if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file))
934     {
935       fprintf (stderr, "Invalid configuration %s", "cfg_file");
936       free_experiment (e);
937       return NULL;
938     }
939
940   }
941
942   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
943       "masters", &e->num_masters))
944   {
945     fprintf (stderr, "Invalid %s", "masters");
946     free_experiment (e);
947     return NULL;
948   }
949   else
950     fprintf (stderr, "Experiment masters: `%llu'\n",
951         e->num_masters);
952
953   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment",
954       "slaves", &e->num_slaves))
955   {
956     fprintf (stderr, "Invalid %s", "slaves");
957     free_experiment (e);
958     return NULL;
959   }
960   else
961     fprintf (stderr, "Experiment slaves: `%llu'\n",
962         e->num_slaves);
963
964   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
965       "log_freq", &e->log_freq))
966   {
967     fprintf (stderr, "Invalid %s", "log_freq");
968     free_experiment (e);
969     return NULL;
970   }
971   else
972     fprintf (stderr, "Experiment logging frequency: `%s'\n",
973         GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES));
974
975   if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment",
976       "max_duration", &e->max_duration))
977   {
978     fprintf (stderr, "Invalid %s", "max_duration");
979     free_experiment (e);
980     return NULL;
981   }
982   else
983     fprintf (stderr, "Experiment duration: `%s'\n",
984         GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES));
985
986   load_episodes (e, cfg);
987   fprintf (stderr, "Loaded %u episodes with total duration %s\n",
988       e->num_episodes,
989       GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES));
990
991   GNUNET_CONFIGURATION_destroy (cfg);
992   return e;
993 }
994
995 void
996 GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e)
997 {
998   if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task)
999   {
1000     GNUNET_SCHEDULER_cancel (e->experiment_timeout_task);
1001     e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1002   }
1003   if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task)
1004   {
1005     GNUNET_SCHEDULER_cancel (e->episode_timeout_task);
1006     e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK;
1007   }
1008   if (NULL != e->cfg)
1009   {
1010     GNUNET_CONFIGURATION_destroy(e->cfg);
1011     e->cfg = NULL;
1012   }
1013   free_experiment (e);
1014 }
1015
1016 /**
1017  * Logging
1018  */
1019
1020
1021 /**
1022  * Solver
1023  */
1024
1025 struct GNUNET_ATS_TESTING_SolverHandle
1026 {
1027   char * plugin;
1028   struct GNUNET_ATS_PluginEnvironment env;
1029   void *solver;
1030   struct GNUNET_CONTAINER_MultiPeerMap *addresses;
1031 };
1032
1033 enum GNUNET_ATS_Solvers
1034 {
1035   GNUNET_ATS_SOLVER_PROPORTIONAL,
1036   GNUNET_ATS_SOLVER_MLP,
1037   GNUNET_ATS_SOLVER_RIL,
1038 };
1039
1040 void
1041 GNUNET_ATS_solvers_solver_stop (struct GNUNET_ATS_TESTING_SolverHandle *sh)
1042 {
1043  GNUNET_PLUGIN_unload (sh->plugin, sh->solver);
1044  GNUNET_CONTAINER_multipeermap_destroy(sh->addresses);
1045  GNUNET_free (sh->plugin);
1046  GNUNET_free (sh);
1047 }
1048
1049 /**
1050  * Load quotas for networks from configuration
1051  *
1052  * @param cfg configuration handle
1053  * @param out_dest where to write outbound quotas
1054  * @param in_dest where to write inbound quotas
1055  * @param dest_length length of inbound and outbound arrays
1056  * @return number of networks loaded
1057  */
1058 unsigned int
1059 GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg,
1060                                                  unsigned long long *out_dest,
1061                                                  unsigned long long *in_dest,
1062                                                  int dest_length)
1063 {
1064   char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
1065   char * entry_in = NULL;
1066   char * entry_out = NULL;
1067   char * quota_out_str;
1068   char * quota_in_str;
1069   int c;
1070   int res;
1071
1072   for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++)
1073   {
1074     in_dest[c] = 0;
1075     out_dest[c] = 0;
1076     GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]);
1077     GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]);
1078
1079     /* quota out */
1080     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, &quota_out_str))
1081     {
1082       res = GNUNET_NO;
1083       if (0 == strcmp(quota_out_str, BIG_M_STRING))
1084       {
1085         out_dest[c] = GNUNET_ATS_MaxBandwidth;
1086         res = GNUNET_YES;
1087       }
1088       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c])))
1089         res = GNUNET_YES;
1090       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out,  &out_dest[c])))
1091          res = GNUNET_YES;
1092
1093       if (GNUNET_NO == res)
1094       {
1095           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
1096               network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth);
1097           out_dest[c] = GNUNET_ATS_DefaultBandwidth;
1098       }
1099       else
1100       {
1101           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"),
1102               network_str[c], out_dest[c]);
1103       }
1104       GNUNET_free (quota_out_str);
1105     }
1106     else
1107     {
1108       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"),
1109           network_str[c], GNUNET_ATS_DefaultBandwidth);
1110       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
1111     }
1112
1113     /* quota in */
1114     if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, &quota_in_str))
1115     {
1116       res = GNUNET_NO;
1117       if (0 == strcmp(quota_in_str, BIG_M_STRING))
1118       {
1119         in_dest[c] = GNUNET_ATS_MaxBandwidth;
1120         res = GNUNET_YES;
1121       }
1122       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c])))
1123         res = GNUNET_YES;
1124       if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in,  &in_dest[c])))
1125          res = GNUNET_YES;
1126
1127       if (GNUNET_NO == res)
1128       {
1129           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s':  `%s', assigning default bandwidth %llu\n"),
1130               network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth);
1131           in_dest[c] = GNUNET_ATS_DefaultBandwidth;
1132       }
1133       else
1134       {
1135           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"),
1136               network_str[c], in_dest[c]);
1137       }
1138       GNUNET_free (quota_in_str);
1139     }
1140     else
1141     {
1142       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"),
1143           network_str[c], GNUNET_ATS_DefaultBandwidth);
1144       out_dest[c] = GNUNET_ATS_DefaultBandwidth;
1145     }
1146     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded quota for network `%s' (in/out): %llu %llu\n", network_str[c], in_dest[c], out_dest[c]);
1147     GNUNET_free (entry_out);
1148     GNUNET_free (entry_in);
1149   }
1150   return GNUNET_ATS_NetworkTypeCount;
1151 }
1152
1153 /**
1154  * Information callback for the solver
1155  *
1156  * @param op the solver operation
1157  * @param stat status of the solver operation
1158  * @param add additional solver information
1159  */
1160 static void
1161 solver_info_cb (void *cls,
1162     enum GAS_Solver_Operation op,
1163     enum GAS_Solver_Status stat,
1164     enum GAS_Solver_Additional_Information add)
1165 {
1166   char *add_info;
1167   switch (add) {
1168     case GAS_INFO_NONE:
1169       add_info = "GAS_INFO_NONE";
1170       break;
1171     case GAS_INFO_FULL:
1172       add_info = "GAS_INFO_MLP_FULL";
1173       break;
1174     case GAS_INFO_UPDATED:
1175       add_info = "GAS_INFO_MLP_UPDATED";
1176       break;
1177     case GAS_INFO_PROP_ALL:
1178       add_info = "GAS_INFO_PROP_ALL";
1179       break;
1180     case GAS_INFO_PROP_SINGLE:
1181       add_info = "GAS_INFO_PROP_SINGLE";
1182       break;
1183     default:
1184       add_info = "INVALID";
1185       break;
1186   }
1187
1188   switch (op)
1189   {
1190     case GAS_OP_SOLVE_START:
1191       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1192           "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START",
1193           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
1194       return;
1195     case GAS_OP_SOLVE_STOP:
1196       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1197           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP",
1198           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info);
1199       return;
1200
1201     case GAS_OP_SOLVE_SETUP_START:
1202       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1203           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START",
1204           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1205       return;
1206
1207     case GAS_OP_SOLVE_SETUP_STOP:
1208       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1209           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP",
1210           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1211       return;
1212
1213     case GAS_OP_SOLVE_MLP_LP_START:
1214       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1215           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START",
1216           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1217       return;
1218     case GAS_OP_SOLVE_MLP_LP_STOP:
1219       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1220           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP",
1221           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1222       return;
1223
1224     case GAS_OP_SOLVE_MLP_MLP_START:
1225       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1226           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START",
1227           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1228       return;
1229     case GAS_OP_SOLVE_MLP_MLP_STOP:
1230       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1231           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP",
1232           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1233       return;
1234     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START:
1235       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1236           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START",
1237           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1238       return;
1239     case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP:
1240       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1241           "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP",
1242           (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL");
1243       return;
1244     default:
1245       break;
1246     }
1247 }
1248
1249 static void
1250 solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address)
1251 {
1252   if ( (0 == ntohl (address->assigned_bw_out.value__)) &&
1253        (0 == ntohl (address->assigned_bw_in.value__)) )
1254     return;
1255
1256   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1257               "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n",
1258               GNUNET_i2s (&address->peer),
1259               address,
1260               (unsigned int) ntohl (address->assigned_bw_out.value__),
1261               (unsigned int) ntohl (address->assigned_bw_in.value__));
1262   /*if (GNUNET_YES == ph.bulk_running)
1263     GNUNET_break (0);*/
1264   return;
1265 }
1266
1267 const double *
1268 get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id)
1269 {
1270   return GAS_normalization_get_preferences_by_peer (id);
1271 }
1272
1273
1274 const double *
1275 get_property_cb (void *cls, const struct ATS_Address *address)
1276 {
1277   return GAS_normalization_get_properties ((struct ATS_Address *) address);
1278 }
1279
1280 static void
1281 normalized_property_changed_cb (void *cls, struct ATS_Address *peer,
1282     uint32_t type, double prop_rel)
1283 {
1284   /* TODO */
1285 }
1286
1287
1288 struct GNUNET_ATS_TESTING_SolverHandle *
1289 GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type)
1290 {
1291   struct GNUNET_ATS_TESTING_SolverHandle *sh;
1292   char * solver_str;
1293   unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
1294   unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
1295
1296   switch (type) {
1297     case GNUNET_ATS_SOLVER_PROPORTIONAL:
1298       solver_str = "proportional";
1299       break;
1300     case GNUNET_ATS_SOLVER_MLP:
1301       solver_str = "mlp";
1302       break;
1303     case GNUNET_ATS_SOLVER_RIL:
1304       solver_str = "ril";
1305       break;
1306     default:
1307       GNUNET_break (0);
1308       return NULL;
1309       break;
1310   }
1311
1312   sh = GNUNET_new (struct GNUNET_ATS_TESTING_SolverHandle);
1313   GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str);
1314
1315   /* setup environment */
1316   sh->env.cfg = e->cfg;
1317   sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg);
1318   sh->env.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1319   sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb;
1320   sh->env.get_preferences = &get_preferences_cb;
1321   sh->env.get_property = &get_property_cb;
1322   sh->env.network_count = GNUNET_ATS_NetworkTypeCount;
1323   sh->env.info_cb = &solver_info_cb;
1324   sh->env.info_cb_cls = NULL;
1325
1326   /* start normalization */
1327   GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL );
1328
1329   /* load quotas */
1330   if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg,
1331       quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount))
1332   {
1333     GNUNET_break(0);
1334     GNUNET_free (sh->plugin);
1335     GNUNET_free (sh);
1336     end_now ();
1337     return NULL;
1338   }
1339
1340   sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env);
1341   if (NULL == sh->solver)
1342   {
1343     fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin);
1344     GNUNET_break(0);
1345     GNUNET_free (sh->plugin);
1346     GNUNET_free (sh);
1347     end_now ();
1348     return NULL;
1349   }
1350
1351   sh->addresses = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
1352
1353   return sh;
1354 }
1355
1356 static void
1357 done ()
1358 {
1359   /* Clean up experiment */
1360   GNUNET_ATS_solvers_experimentation_stop (e);
1361   e = NULL;
1362
1363   /* Shutdown */
1364   end_now();
1365
1366 }
1367
1368 static void
1369 experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success)
1370 {
1371   if (GNUNET_OK == success)
1372     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n",
1373         GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES));
1374   else
1375     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n");
1376
1377   /* Stop logging */
1378   // GNUNET_ATS_TEST_logging_stop (l);
1379
1380   /* Stop traffic generation */
1381   // GNUNET_ATS_TEST_generate_traffic_stop_all();
1382
1383   /* Stop all preference generations */
1384   // GNUNET_ATS_TEST_generate_preferences_stop_all ();
1385
1386   /*
1387   evaluate (duration);
1388   if (opt_log)
1389     GNUNET_ATS_TEST_logging_write_to_file(l, opt_exp_file, opt_plot);
1390
1391   if (NULL != l)
1392   {
1393     GNUNET_ATS_TEST_logging_stop (l);
1394     GNUNET_ATS_TEST_logging_clean_up (l);
1395     l = NULL;
1396   }
1397   */
1398   GNUNET_SCHEDULER_add_now (&done, NULL);
1399 }
1400
1401 static void
1402 episode_done_cb (struct Episode *ep)
1403 {
1404   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id);
1405 }
1406
1407
1408
1409 /**
1410  * Do shutdown
1411  */
1412 static void
1413 end_now ()
1414 {
1415   if (NULL != e)
1416   {
1417     GNUNET_ATS_solvers_experimentation_stop (e);
1418     e = NULL;
1419   }
1420   if (NULL != sh)
1421   {
1422     GNUNET_ATS_solvers_solver_stop (sh);
1423     sh = NULL;
1424   }
1425 }
1426
1427 static void
1428 run (void *cls, char * const *args, const char *cfgfile,
1429     const struct GNUNET_CONFIGURATION_Handle *cfg)
1430 {
1431   enum GNUNET_ATS_Solvers solver;
1432
1433   if (NULL == opt_exp_file)
1434   {
1435     fprintf (stderr, "No experiment given ...\n");
1436     res = 1;
1437     end_now ();
1438     return;
1439   }
1440
1441   if (NULL == opt_solver)
1442   {
1443     fprintf (stderr, "No solver given ...\n");
1444     res = 1;
1445     end_now ();
1446     return;
1447   }
1448
1449   if (0 == strcmp(opt_solver, "mlp"))
1450   {
1451     solver = GNUNET_ATS_SOLVER_MLP;
1452   }
1453   else if (0 == strcmp(opt_solver, "proportional"))
1454   {
1455     solver = GNUNET_ATS_SOLVER_PROPORTIONAL;
1456   }
1457   else if (0 == strcmp(opt_solver, "ril"))
1458   {
1459     solver = GNUNET_ATS_SOLVER_RIL;
1460   }
1461   else
1462   {
1463     fprintf (stderr, "No solver given ...");
1464     res = 1;
1465     end_now ();
1466     return;
1467   }
1468
1469   /* load experiment */
1470   e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file);
1471   if (NULL == e)
1472   {
1473     fprintf (stderr, "Failed to load experiment ...\n");
1474     res = 1;
1475     end_now ();
1476     return;
1477   }
1478
1479
1480   /* load solver */
1481   sh = GNUNET_ATS_solvers_solver_start (solver);
1482   if (NULL == sh)
1483   {
1484     fprintf (stderr, "Failed to start solver ...\n");
1485     end_now ();
1486     res = 1;
1487     return;
1488   }
1489
1490   /* start logging */
1491
1492
1493   /* run experiment */
1494   GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb,
1495       experiment_done_cb);
1496
1497   /* WAIT */
1498 }
1499
1500
1501 /**
1502  * Main function of the benchmark
1503  *
1504  * @param argc argument count
1505  * @param argv argument values
1506  */
1507 int
1508 main (int argc, char *argv[])
1509 {
1510   opt_exp_file = NULL;
1511   opt_solver = NULL;
1512   opt_log = GNUNET_NO;
1513   opt_plot = GNUNET_NO;
1514
1515   res = 0;
1516
1517   static struct GNUNET_GETOPT_CommandLineOption options[] =
1518   {
1519     { 's', "solver", NULL,
1520         gettext_noop ("solver to use"),
1521         1, &GNUNET_GETOPT_set_string, &opt_solver},
1522     {  'e', "experiment", NULL,
1523       gettext_noop ("experiment to use"),
1524       1, &GNUNET_GETOPT_set_string, &opt_exp_file},
1525     {  'e', "experiment", NULL,
1526       gettext_noop ("experiment to use"),
1527       1, &GNUNET_GETOPT_set_one, &opt_verbose},
1528     GNUNET_GETOPT_OPTION_END
1529   };
1530
1531   GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]);
1532
1533   return res;
1534 }
1535 /* end of file ats-testing-experiment.c*/
1536