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