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