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