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